From b097e0840b53698e3e5eedfc406cd839c2f0fbf8 Mon Sep 17 00:00:00 2001 From: Hauke Petersen Date: Tue, 8 Nov 2016 18:24:28 +0100 Subject: [PATCH] cpu/nrf5x+boards: adapted to new SPI API - adapted the SPI driver - merged SPI drivers from nrf51 and nrf52 - adapted all boards using the CPU --- boards/airfy-beacon/include/periph_conf.h | 23 +- boards/nrf52dk/Makefile.features | 1 + boards/nrf52dk/include/periph_conf.h | 15 ++ boards/nrf6310/include/periph_conf.h | 30 +-- boards/pca10005/include/periph_conf.h | 30 +-- boards/yunjia-nrf51822/include/periph_conf.h | 30 +-- cpu/nrf51/include/periph_cpu.h | 5 +- cpu/nrf51/periph/spi.c | 236 ----------------- cpu/nrf52/include/periph_cpu.h | 5 +- cpu/nrf52/periph/spi.c | 258 ------------------- cpu/nrf5x_common/include/periph_cpu_common.h | 50 +++- cpu/nrf5x_common/periph/spi.c | 118 +++++++++ 12 files changed, 248 insertions(+), 553 deletions(-) delete mode 100644 cpu/nrf51/periph/spi.c delete mode 100644 cpu/nrf52/periph/spi.c create mode 100644 cpu/nrf5x_common/periph/spi.c diff --git a/boards/airfy-beacon/include/periph_conf.h b/boards/airfy-beacon/include/periph_conf.h index bc7d1a0090..4aac804ea1 100644 --- a/boards/airfy-beacon/include/periph_conf.h +++ b/boards/airfy-beacon/include/periph_conf.h @@ -1,9 +1,9 @@ /* * Copyright (C) 2014 Christian Mehlis * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. */ /** @@ -83,15 +83,16 @@ static const timer_conf_t timer_config[] = { * @name SPI configuration * @{ */ -#define SPI_NUMOF (1U) -#define SPI_0_EN 1 -#define SPI_IRQ_PRIO 1 +static const spi_conf_t spi_config[] = { + { + .dev = NRF_SPI0, + .sclk = 15, + .mosi = 13, + .miso = 14 + } +}; -/* SPI_0 device configuration */ -#define SPI_0_DEV NRF_SPI0 -#define SPI_0_PIN_MOSI 13 -#define SPI_0_PIN_MISO 14 -#define SPI_0_PIN_SCK 15 +#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) /** @} */ /** diff --git a/boards/nrf52dk/Makefile.features b/boards/nrf52dk/Makefile.features index a12def18a0..748d31f896 100644 --- a/boards/nrf52dk/Makefile.features +++ b/boards/nrf52dk/Makefile.features @@ -4,6 +4,7 @@ FEATURES_PROVIDED += periph_flashpage FEATURES_PROVIDED += periph_gpio FEATURES_PROVIDED += periph_hwrng FEATURES_PROVIDED += periph_rtt +FEATURES_PROVIDED += periph_spi FEATURES_PROVIDED += periph_timer FEATURES_PROVIDED += periph_uart diff --git a/boards/nrf52dk/include/periph_conf.h b/boards/nrf52dk/include/periph_conf.h index 2975d5968f..5f128385b6 100644 --- a/boards/nrf52dk/include/periph_conf.h +++ b/boards/nrf52dk/include/periph_conf.h @@ -74,6 +74,21 @@ static const timer_conf_t timer_config[] = { #define UART_PIN_TX 6 /** @} */ +/** + * @name SPI configuration + * @{ + */ +static const spi_conf_t spi_config[] = { + { + .dev = NRF_SPI0, + .sclk = 15, + .mosi = 13, + .miso = 14 } +}; + +#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) +/** @} */ + #ifdef __cplusplus } #endif diff --git a/boards/nrf6310/include/periph_conf.h b/boards/nrf6310/include/periph_conf.h index 636b4e0f05..cc53add564 100644 --- a/boards/nrf6310/include/periph_conf.h +++ b/boards/nrf6310/include/periph_conf.h @@ -100,22 +100,22 @@ static const timer_conf_t timer_config[] = { * @name SPI configuration * @{ */ -#define SPI_NUMOF (2U) -#define SPI_0_EN 1 -#define SPI_1_EN 1 -#define SPI_IRQ_PRIO 1 +static const spi_conf_t spi_config[] = { + { + .dev = NRF_SPI0, + .sclk = 23, + .mosi = 22, + .miso = 20 + }, + { + .dev = NRF_SPI1, + .sclk = 16, + .mosi = 17, + .miso = 18 + } +}; -/* SPI Master 0 pin configuration */ -#define SPI_0_DEV NRF_SPI0 -#define SPI_0_PIN_SCK 23 -#define SPI_0_PIN_MISO 22 -#define SPI_0_PIN_MOSI 20 - -/* SPI Master 1 pin configuration */ -#define SPI_1_DEV NRF_SPI1 -#define SPI_1_PIN_SCK 16 -#define SPI_1_PIN_MISO 17 -#define SPI_1_PIN_MOSI 18 +#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) /** @} */ /** diff --git a/boards/pca10005/include/periph_conf.h b/boards/pca10005/include/periph_conf.h index de0ebb2cf5..09d183d89e 100644 --- a/boards/pca10005/include/periph_conf.h +++ b/boards/pca10005/include/periph_conf.h @@ -83,22 +83,22 @@ static const timer_conf_t timer_config[] = { * @name SPI configuration * @{ */ -#define SPI_NUMOF (2U) -#define SPI_0_EN 1 -#define SPI_1_EN 1 -#define SPI_IRQ_PRIO 1 +static const spi_conf_t spi_config[] = { + { + .dev = NRF_SPI0, + .sclk = 19, + .mosi = 17, + .miso = 18 + }, + { + .dev = NRF_SPI1, + .sclk = 22, + .mosi = 20, + .miso = 21 + } +}; -/* SPI_0 device configuration */ -#define SPI_0_DEV NRF_SPI0 -#define SPI_0_PIN_MOSI 17 -#define SPI_0_PIN_MISO 18 -#define SPI_0_PIN_SCK 19 - -/* SPI_1 device configuration */ -#define SPI_1_DEV NRF_SPI1 -#define SPI_1_PIN_MOSI 20 -#define SPI_1_PIN_MISO 21 -#define SPI_1_PIN_SCK 22 +#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) /** @} */ /** diff --git a/boards/yunjia-nrf51822/include/periph_conf.h b/boards/yunjia-nrf51822/include/periph_conf.h index 2e67cc9b36..ae07c27b1b 100644 --- a/boards/yunjia-nrf51822/include/periph_conf.h +++ b/boards/yunjia-nrf51822/include/periph_conf.h @@ -81,22 +81,22 @@ static const timer_conf_t timer_config[] = { * @name SPI configuration * @{ */ -#define SPI_NUMOF (2U) -#define SPI_0_EN 1 -#define SPI_1_EN 1 -#define SPI_IRQ_PRIO 1 +static const spi_conf_t spi_config[] = { + { + .dev = NRF_SPI0, + .sclk = 19, + .mosi = 17, + .miso = 18 + }, + { + .dev = NRF_SPI1, + .sclk = 22, + .mosi = 20, + .miso = 21 + } +}; -/* SPI_0 device configuration */ -#define SPI_0_DEV NRF_SPI0 -#define SPI_0_PIN_MOSI 17 -#define SPI_0_PIN_MISO 18 -#define SPI_0_PIN_SCK 19 - -/* SPI_1 device configuration */ -#define SPI_1_DEV NRF_SPI1 -#define SPI_1_PIN_MOSI 20 -#define SPI_1_PIN_MISO 21 -#define SPI_1_PIN_SCK 22 +#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) /** @} */ /** diff --git a/cpu/nrf51/include/periph_cpu.h b/cpu/nrf51/include/periph_cpu.h index 9e69280edb..594414a936 100644 --- a/cpu/nrf51/include/periph_cpu.h +++ b/cpu/nrf51/include/periph_cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2016 Freie Universität Berlin + * Copyright (C) 2015-2017 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -31,6 +31,9 @@ extern "C" { */ #define GPIO_BASE (NRF_GPIO) #define UART_IRQN (UART0_IRQn) +#define SPI_SCKSEL (dev(bus)->PSELSCK) +#define SPI_MOSISEL (dev(bus)->PSELMOSI) +#define SPI_MISOSEL (dev(bus)->PSELMISO) /** @} */ /** diff --git a/cpu/nrf51/periph/spi.c b/cpu/nrf51/periph/spi.c deleted file mode 100644 index 12bdd1b3da..0000000000 --- a/cpu/nrf51/periph/spi.c +++ /dev/null @@ -1,236 +0,0 @@ -/* - * Copyright (C) 2014 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser General - * Public License v2.1. See the file LICENSE in the top level directory for more - * details. - */ - -/** - * @ingroup cpu_nrf51822 - * @{ - * - * @file - * @brief Low-level SPI driver implementation - * - * @author Hauke Petersen - * @author Frank Holtz - * - * @} - */ - -#include "cpu.h" -#include "mutex.h" -#include "periph/spi.h" -#include "periph_conf.h" - -/* guard this file in case no SPI device is defined */ -#if SPI_NUMOF - -/* static port mapping */ -static NRF_SPI_Type *const spi[] = { -#if SPI_0_EN - SPI_0_DEV, -#endif -#if SPI_1_EN - SPI_1_DEV -#endif -}; - -/** - * @brief array holding one pre-initialized mutex for each SPI device - */ -static mutex_t locks[] = { -#if SPI_0_EN - [SPI_0] = MUTEX_INIT, -#endif -#if SPI_1_EN - [SPI_1] = MUTEX_INIT, -#endif -}; - -int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) -{ - spi_poweron(dev); - - /* disable the device -> nRF51822 reference 3.0 26.1.1 and 27.1*/ - spi[dev]->ENABLE = 0; - - switch(dev) { -#if SPI_0_EN - case SPI_0: - /* disable TWI Interface */ - NRF_TWI0->ENABLE = 0; - break; -#endif -#if SPI_1_EN - case SPI_1: - /* disable SPI Slave */ - NRF_SPIS1->ENABLE = 0; - /* disable TWI Interface */ - NRF_TWI1->ENABLE = 0; - break; -#endif - default: - return -1; - } - - /* configure direction of used pins */ - spi_conf_pins(dev); - /* configure SPI mode */ - switch (conf) { - case SPI_CONF_FIRST_RISING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveHigh << 2) | (SPI_CONFIG_CPHA_Leading << 1); - break; - case SPI_CONF_SECOND_RISING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveHigh << 2) | (SPI_CONFIG_CPHA_Trailing << 1); - break; - case SPI_CONF_FIRST_FALLING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveLow << 2) | (SPI_CONFIG_CPHA_Leading << 1); - break; - case SPI_CONF_SECOND_FALLING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveLow << 2) | (SPI_CONFIG_CPHA_Trailing << 1); - break; - } - - /* select bus speed */ - switch (speed) { - case SPI_SPEED_100KHZ: /* 125 KHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_K125; - break; - case SPI_SPEED_400KHZ: /* 500 KHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_K500; - break; - case SPI_SPEED_1MHZ: /* 1 MHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M1; - break; - case SPI_SPEED_5MHZ: /* 4 MHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M4; - break; - case SPI_SPEED_10MHZ: /* 8 MHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M8; - break; - } - - /* finally enable the device */ - spi[dev]->ENABLE = 1; - return 0; -} - -int spi_init_slave(spi_t dev, spi_conf_t conf, char (*cb)(char data)) -{ - (void) dev; - (void) conf; - (void) cb; - /* This API is incompatible with nRF51 SPIS */ - return -1; -} - -int spi_conf_pins(spi_t dev) -{ - switch (dev) { -#if SPI_0_EN - case SPI_0: - /* set pin direction */ - NRF_GPIO->DIRSET = (1 << SPI_0_PIN_MOSI) | (1 << SPI_0_PIN_SCK); - NRF_GPIO->DIRCLR = (1 << SPI_0_PIN_MISO); - /* select pins to be used by SPI */ - spi[dev]->PSELMOSI = SPI_0_PIN_MOSI; - spi[dev]->PSELMISO = SPI_0_PIN_MISO; - spi[dev]->PSELSCK = SPI_0_PIN_SCK; - break; -#endif -#if SPI_1_EN - case SPI_1: - /* set pin direction */ - NRF_GPIO->DIRSET = (1 << SPI_1_PIN_MOSI) | (1 << SPI_1_PIN_SCK); - NRF_GPIO->DIRCLR = (1 << SPI_1_PIN_MISO); - /* select pins to be used by SPI */ - spi[dev]->PSELMOSI = SPI_1_PIN_MOSI; - spi[dev]->PSELMISO = SPI_1_PIN_MISO; - spi[dev]->PSELSCK = SPI_1_PIN_SCK; - break; -#endif - default: - return -1; - } - return 0; -} - -int spi_acquire(spi_t dev) -{ - if ((unsigned int)dev >= SPI_NUMOF) { - return -1; - } - mutex_lock(&locks[dev]); - return 0; -} - -int spi_release(spi_t dev) -{ - if ((unsigned int)dev >= SPI_NUMOF) { - return -1; - } - mutex_unlock(&locks[dev]); - return 0; -} - -int spi_transfer_byte(spi_t dev, char out, char *in) -{ - return spi_transfer_bytes(dev, &out, in, 1); -} - -int spi_transfer_bytes(spi_t dev, char *out, char *in, unsigned int length) -{ - if ((unsigned int)dev >= SPI_NUMOF) { - return -1; - } - - for (unsigned i = 0; i < length; i++) { - char tmp = (out) ? out[i] : 0; - spi[dev]->EVENTS_READY = 0; - spi[dev]->TXD = (uint8_t)tmp; - while (spi[dev]->EVENTS_READY != 1) {} - tmp = (char)spi[dev]->RXD; - if (in) { - in[i] = tmp; - } - } - - return length; -} - -int spi_transfer_reg(spi_t dev, uint8_t reg, char out, char *in) -{ - spi_transfer_byte(dev, reg, 0); - return spi_transfer_byte(dev, out, in); -} - -int spi_transfer_regs(spi_t dev, uint8_t reg, char *out, char *in, unsigned int length) -{ - spi_transfer_byte(dev, reg, 0); - return spi_transfer_bytes(dev, out, in, length); -} - -void spi_transmission_begin(spi_t dev, char reset_val) -{ - (void) dev; - (void) reset_val; - /* spi slave is not implemented */ -} - -void spi_poweron(spi_t dev) -{ - if ((unsigned int)dev < SPI_NUMOF) { - spi[dev]->POWER = 1; - } -} - -void spi_poweroff(spi_t dev) -{ - if ((unsigned int)dev < SPI_NUMOF) { - spi[dev]->POWER = 0; - } -} - -#endif /* SPI_NUMOF */ diff --git a/cpu/nrf52/include/periph_cpu.h b/cpu/nrf52/include/periph_cpu.h index c263b3dead..e315106e64 100644 --- a/cpu/nrf52/include/periph_cpu.h +++ b/cpu/nrf52/include/periph_cpu.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2016 Freie Universität Berlin + * Copyright (C) 2015-2017 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -31,6 +31,9 @@ extern "C" { */ #define GPIO_BASE (NRF_P0) #define UART_IRQN (UARTE0_UART0_IRQn) +#define SPI_SCKSEL (dev(bus)->PSEL.SCK) +#define SPI_MOSISEL (dev(bus)->PSEL.MOSI) +#define SPI_MISOSEL (dev(bus)->PSEL.MISO) /** @} */ #ifdef __cplusplus diff --git a/cpu/nrf52/periph/spi.c b/cpu/nrf52/periph/spi.c deleted file mode 100644 index bd7012a82a..0000000000 --- a/cpu/nrf52/periph/spi.c +++ /dev/null @@ -1,258 +0,0 @@ -/* - * Copyright (C) 2015 Jan Wagner - * 2016 Freie Universität Berlin - * - * This file is subject to the terms and conditions of the GNU Lesser - * General Public License v2.1. See the file LICENSE in the top level - * directory for more details. - */ - -/** - * @ingroup cpu_nrf52 - * @{ - * - * @file - * @brief Implementation of the peripheral SPI interface - * - * @author Hauke Petersen - * @author Frank Holtz - * @author Jan Wagner - * - * @} - */ - -#include "cpu.h" -#include "mutex.h" -#include "periph/spi.h" -#include "periph_conf.h" - -/* guard this file in case no SPI device is defined */ -#if SPI_NUMOF - -/* static port mapping */ -static NRF_SPI_Type *const spi[] = { -#if SPI_0_EN - SPI_0_DEV, -#endif -#if SPI_1_EN - SPI_1_DEV -#endif -}; - -/** - * @brief array holding one pre-initialized mutex for each SPI device - */ -static mutex_t locks[] = { -#if SPI_0_EN - [SPI_0] = MUTEX_INIT, -#endif -#if SPI_1_EN - [SPI_1] = MUTEX_INIT, -#endif -}; - -int spi_init_master(spi_t dev, spi_conf_t conf, spi_speed_t speed) -{ - if (dev >= SPI_NUMOF) { - return -1; - } - - spi_poweron(dev); - - /* disable the device -> nRF51822 reference 3.0 26.1.1 and 27.1*/ - spi[dev]->ENABLE = 0; - - switch (dev) { -#if SPI_0_EN - - case SPI_0: - /* disable TWI Interface */ - NRF_TWI0->ENABLE = 0; - break; -#endif -#if SPI_1_EN - - case SPI_1: - /* disable SPI Slave */ - NRF_SPIS1->ENABLE = 0; - /* disable TWI Interface */ - NRF_TWI1->ENABLE = 0; - break; -#endif - - default: - return -1; - } - - /* configure direction of used pins */ - spi_conf_pins(dev); - - /* configure SPI mode */ - switch (conf) { - case SPI_CONF_FIRST_RISING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveHigh << 2) | (SPI_CONFIG_CPHA_Leading << 1); - break; - - case SPI_CONF_SECOND_RISING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveHigh << 2) | (SPI_CONFIG_CPHA_Trailing << 1); - break; - - case SPI_CONF_FIRST_FALLING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveLow << 2) | (SPI_CONFIG_CPHA_Leading << 1); - break; - - case SPI_CONF_SECOND_FALLING: - spi[dev]->CONFIG = (SPI_CONFIG_CPOL_ActiveLow << 2) | (SPI_CONFIG_CPHA_Trailing << 1); - break; - } - - /* select bus speed */ - switch (speed) { - case SPI_SPEED_100KHZ: /* 125 KHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_K125; - break; - - case SPI_SPEED_400KHZ: /* 500 KHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_K500; - break; - - case SPI_SPEED_1MHZ: /* 1 MHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M1; - break; - - case SPI_SPEED_5MHZ: /* 4 MHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M4; - break; - - case SPI_SPEED_10MHZ: /* 8 MHz for this device */ - spi[dev]->FREQUENCY = SPI_FREQUENCY_FREQUENCY_M8; - break; - } - - /* finally enable the device */ - spi[dev]->ENABLE = 1; - return 0; -} - -int spi_init_slave(spi_t dev, spi_conf_t conf, char (*cb)(char data)) -{ - /* This API is incompatible with nRF51 SPIS */ - return -1; -} - -int spi_conf_pins(spi_t dev) -{ - if (dev >= SPI_NUMOF) { - return -1; - } - - switch (dev) { -#if SPI_0_EN - - case SPI_0: - /* set pin direction */ - NRF_P0->DIRSET = (1 << SPI_0_PIN_MOSI) | (1 << SPI_0_PIN_SCK); - NRF_P0->DIRCLR = (1 << SPI_0_PIN_MISO); - /* select pins to be used by SPI */ - spi[dev]->PSELMOSI = SPI_0_PIN_MOSI; - spi[dev]->PSELMISO = SPI_0_PIN_MISO; - spi[dev]->PSELSCK = SPI_0_PIN_SCK; - break; -#endif -#if SPI_1_EN - - case SPI_1: - /* set pin direction */ - NRF_P0->DIRSET = (1 << SPI_1_PIN_MOSI) | (1 << SPI_1_PIN_SCK); - NRF_P0->DIRCLR = (1 << SPI_1_PIN_MISO); - /* select pins to be used by SPI */ - spi[dev]->PSELMOSI = SPI_1_PIN_MOSI; - spi[dev]->PSELMISO = SPI_1_PIN_MISO; - spi[dev]->PSELSCK = SPI_1_PIN_SCK; - break; -#endif - } - - return 0; -} - -int spi_acquire(spi_t dev) -{ - if (dev >= SPI_NUMOF) { - return -1; - } - - mutex_lock(&locks[dev]); - return 0; -} - -int spi_release(spi_t dev) -{ - if (dev >= SPI_NUMOF) { - return -1; - } - - mutex_unlock(&locks[dev]); - return 0; -} - -int spi_transfer_byte(spi_t dev, char out, char *in) -{ - return spi_transfer_bytes(dev, &out, in, 1); -} - -int spi_transfer_bytes(spi_t dev, char *out, char *in, unsigned int length) -{ - if (dev >= SPI_NUMOF) { - return -1; - } - - for (int i = 0; i < length; i++) { - char tmp = (out) ? out[i] : 0; - spi[dev]->EVENTS_READY = 0; - spi[dev]->TXD = (uint8_t)tmp; - - while (spi[dev]->EVENTS_READY != 1); - - tmp = (char)spi[dev]->RXD; - - if (in) { - in[i] = tmp; - } - } - - return length; -} - -int spi_transfer_reg(spi_t dev, uint8_t reg, char out, char *in) -{ - spi_transfer_byte(dev, reg, 0); - return spi_transfer_byte(dev, out, in); -} - -int spi_transfer_regs(spi_t dev, uint8_t reg, char *out, char *in, unsigned int length) -{ - spi_transfer_byte(dev, reg, 0); - return spi_transfer_bytes(dev, out, in, length); -} - -void spi_transmission_begin(spi_t dev, char reset_val) -{ - /* spi slave is not implemented */ -} - -void spi_poweron(spi_t dev) -{ - if (dev < SPI_NUMOF) { - spi[dev]->POWER = 1; - } -} - -void spi_poweroff(spi_t dev) -{ - if (dev < SPI_NUMOF) { - spi[dev]->POWER = 0; - } -} - -#endif /* SPI_NUMOF */ diff --git a/cpu/nrf5x_common/include/periph_cpu_common.h b/cpu/nrf5x_common/include/periph_cpu_common.h index b22de8f063..38a9ee0140 100644 --- a/cpu/nrf5x_common/include/periph_cpu_common.h +++ b/cpu/nrf5x_common/include/periph_cpu_common.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2015-2016 Freie Universität Berlin + * Copyright (C) 2015-2017 Freie Universität Berlin * * This file is subject to the terms and conditions of the GNU Lesser * General Public License v2.1. See the file LICENSE in the top level @@ -47,6 +47,21 @@ extern "C" { */ #define GPIO_MODE(oe, ic, pr) (oe | (ic << 1) | (pr << 2)) +/** + * @brief No support for HW chip select... + */ +#define SPI_HWCS(x) (SPI_CS_UNDEF) + +/** + * @brief Declare needed shared SPI functions + * @{ + */ +#define PERIPH_SPI_NEEDS_INIT_CS +#define PERIPH_SPI_NEEDS_TRANSFER_BYTE +#define PERIPH_SPI_NEEDS_TRANSFER_REG +#define PERIPH_SPI_NEEDS_TRANSFER_REGS +/** @} */ + #ifndef DOXYGEN /** * @brief Override GPIO modes @@ -106,6 +121,39 @@ typedef struct { uint8_t irqn; /**< IRQ number of the timer device */ } timer_conf_t; +/** + * @brief Override SPI mode values + */ +#define HAVE_SPI_MODE_T +typedef enum { + SPI_MODE_0 = 0, /**< CPOL=0, CPHA=0 */ + SPI_MODE_1 = SPI_CONFIG_CPHA_Msk, /**< CPOL=0, CPHA=1 */ + SPI_MODE_2 = SPI_CONFIG_CPOL_Msk, /**< CPOL=1, CPHA=0 */ + SPI_MODE_3 = (SPI_CONFIG_CPOL_Msk | SPI_CONFIG_CPHA_Msk) /**< CPOL=1, CPHA=1 */ +} spi_mode_t; + +/** + * @brief Override SPI clock values + */ +#define HAVE_SPI_CLK_T +typedef enum { + SPI_CLK_100KHZ = SPI_FREQUENCY_FREQUENCY_K125, /**< 100KHz */ + SPI_CLK_400KHZ = SPI_FREQUENCY_FREQUENCY_K500, /**< 400KHz */ + SPI_CLK_1MHZ = SPI_FREQUENCY_FREQUENCY_M1, /**< 1MHz */ + SPI_CLK_5MHZ = SPI_FREQUENCY_FREQUENCY_M4, /**< 5MHz */ + SPI_CLK_10MHZ = SPI_FREQUENCY_FREQUENCY_M8 /**< 10MHz */ +} spi_clk_t; + +/** + * @brief SPI configuration values + */ +typedef struct { + NRF_SPI_Type *dev; /**< SPI device used */ + uint8_t sclk; /**< CLK pin */ + uint8_t mosi; /**< MOSI pin */ + uint8_t miso; /**< MISO pin */ +} spi_conf_t; + #ifdef __cplusplus } #endif diff --git a/cpu/nrf5x_common/periph/spi.c b/cpu/nrf5x_common/periph/spi.c new file mode 100644 index 0000000000..913f56e957 --- /dev/null +++ b/cpu/nrf5x_common/periph/spi.c @@ -0,0 +1,118 @@ +/* + * Copyright (C) 2014-2016 Freie Universität Berlin + * + * This file is subject to the terms and conditions of the GNU Lesser + * General Public License v2.1. See the file LICENSE in the top level + * directory for more details. + */ + +/** + * @ingroup cpu_nrf5x_common + * @{ + * + * @file + * @brief Low-level SPI driver implementation + * + * @author Hauke Petersen + * @author Frank Holtz + * @author Jan Wagner + * + * @} + */ + +#include "cpu.h" +#include "mutex.h" +#include "assert.h" +#include "periph/spi.h" + +#ifdef SPI_NUMOF + +/** + * @brief array holding one pre-initialized mutex for each SPI device + */ +static mutex_t locks[SPI_NUMOF]; + +static inline NRF_SPI_Type *dev(spi_t bus) +{ + return spi_config[bus].dev; +} + +void spi_init(spi_t bus) +{ + assert(bus < SPI_NUMOF); + + /* initialize mutex */ + mutex_init(&locks[bus]); + /* initialize pins */ + spi_init_pins(bus); +} + +void spi_init_pins(spi_t bus) +{ + /* set pin direction */ + GPIO_BASE->DIRSET = ((1 << spi_config[bus].sclk) | + (1 << spi_config[bus].mosi)); + GPIO_BASE->DIRCLR = (1 << spi_config[bus].miso); + /* select pins for the SPI device */ + SPI_SCKSEL = spi_config[bus].sclk; + SPI_MOSISEL = spi_config[bus].mosi; + SPI_MISOSEL = spi_config[bus].miso; +} + +int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) +{ + mutex_lock(&locks[bus]); +#ifdef CPU_FAM_NRF51 + /* power on the bus (NRF51 only) */ + dev(bus)->POWER = 1; +#endif + /* configure bus */ + dev(bus)->CONFIG = mode; + dev(bus)->FREQUENCY = clk; + /* enable the bus */ + dev(bus)->ENABLE = 1; + + return SPI_OK; +} + +void spi_release(spi_t bus) +{ + /* power off everything */ + dev(bus)->ENABLE = 0; +#ifdef CPU_FAM_NRF51 + dev(bus)->POWER = 0; +#endif + mutex_unlock(&locks[bus]); +} + +void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, + const void *out, void *in, size_t len) +{ + uint8_t *in_buf = (uint8_t *)in; + uint8_t *out_buf = (uint8_t *)out; + + assert(out_buf || in_buf); + + if (cs != SPI_CS_UNDEF) { + gpio_clear((gpio_t)cs); + } + + for (int i = 0; i < (int)len; i++) { + uint8_t tmp = (out_buf) ? out_buf[i] : 0; + + dev(bus)->EVENTS_READY = 0; + dev(bus)->TXD = (uint8_t)tmp; + while (dev(bus)->EVENTS_READY != 1); + tmp = (uint8_t)dev(bus)->RXD; + + if (in_buf) { + in_buf[i] = tmp; + } + } + + if ((cs != SPI_CS_UNDEF) && (!cont)) { + gpio_set((gpio_t)cs); + } +} + +#endif /* SPI_NUMOF */