diff --git a/boards/airfy-beacon/Makefile.features b/boards/airfy-beacon/Makefile.features index f7dc503f5c86b409e0db7616cefd740ef3c182fa..7444aa391088b5d37a94c18bfcd09da86db9b781 100644 --- a/boards/airfy-beacon/Makefile.features +++ b/boards/airfy-beacon/Makefile.features @@ -1,3 +1,4 @@ FEATURES_PROVIDED += cpp -FEATURES_PROVIDED += periph_uart periph_gpio periph_random periph_rtt periph_cpuid +FEATURES_PROVIDED += periph_uart periph_gpio periph_random periph_rtt \ + periph_cpuid periph_spi FEATURES_MCU_GROUP = cortex_m0 diff --git a/boards/airfy-beacon/include/periph_conf.h b/boards/airfy-beacon/include/periph_conf.h index e9dd02ebc4bfbbc587ced5335fba5a143cfc8b86..198b85e99b9590360927876c8f8ba103e8465b68 100644 --- a/boards/airfy-beacon/include/periph_conf.h +++ b/boards/airfy-beacon/include/periph_conf.h @@ -108,6 +108,21 @@ #define RANDOM_NUMOF (1U) /** @} */ +/** + * @name SPI configuration + * @{ + */ +#define SPI_NUMOF (1U) +#define SPI_0_EN 1 +#define SPI_IRQ_PRIO 1 + +/* 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 +/** @} */ + /** * @name GPIO configuration * @{ diff --git a/boards/pca10005/Makefile.features b/boards/pca10005/Makefile.features index f7dc503f5c86b409e0db7616cefd740ef3c182fa..7444aa391088b5d37a94c18bfcd09da86db9b781 100644 --- a/boards/pca10005/Makefile.features +++ b/boards/pca10005/Makefile.features @@ -1,3 +1,4 @@ FEATURES_PROVIDED += cpp -FEATURES_PROVIDED += periph_uart periph_gpio periph_random periph_rtt periph_cpuid +FEATURES_PROVIDED += periph_uart periph_gpio periph_random periph_rtt \ + periph_cpuid periph_spi FEATURES_MCU_GROUP = cortex_m0 diff --git a/boards/pca10005/include/periph_conf.h b/boards/pca10005/include/periph_conf.h index 32bfa62a551ad632c6dd8d1223536e87d56f1098..3548e0a964301af74bb772489d6365a3e1590f8b 100644 --- a/boards/pca10005/include/periph_conf.h +++ b/boards/pca10005/include/periph_conf.h @@ -108,6 +108,28 @@ extern "C" { #define RANDOM_NUMOF (1U) /** @} */ +/** + * @name SPI configuration + * @{ + */ +#define SPI_NUMOF (2U) +#define SPI_0_EN 1 +#define SPI_1_EN 1 +#define SPI_IRQ_PRIO 1 + +/* 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 +/** @} */ + /** * @name GPIO configuration * @{ diff --git a/boards/yunjia-nrf51822/Makefile.features b/boards/yunjia-nrf51822/Makefile.features index f7dc503f5c86b409e0db7616cefd740ef3c182fa..7444aa391088b5d37a94c18bfcd09da86db9b781 100644 --- a/boards/yunjia-nrf51822/Makefile.features +++ b/boards/yunjia-nrf51822/Makefile.features @@ -1,3 +1,4 @@ FEATURES_PROVIDED += cpp -FEATURES_PROVIDED += periph_uart periph_gpio periph_random periph_rtt periph_cpuid +FEATURES_PROVIDED += periph_uart periph_gpio periph_random periph_rtt \ + periph_cpuid periph_spi FEATURES_MCU_GROUP = cortex_m0 diff --git a/boards/yunjia-nrf51822/include/periph_conf.h b/boards/yunjia-nrf51822/include/periph_conf.h index 19bb6b83e5593e905790a8b78713dc436f60f58b..f37ef58e5706c83d90a48b67b08049339856bb0c 100644 --- a/boards/yunjia-nrf51822/include/periph_conf.h +++ b/boards/yunjia-nrf51822/include/periph_conf.h @@ -106,6 +106,29 @@ extern "C" { #define RANDOM_NUMOF (1U) /** @} */ +/** + * @name SPI configuration + * @{ + */ +#define SPI_NUMOF (2U) +#define SPI_0_EN 1 +#define SPI_1_EN 1 +#define SPI_IRQ_PRIO 1 + +/* 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 +/** @} */ + + /** * @name GPIO configuration * @{ diff --git a/cpu/nrf51822/periph/spi.c b/cpu/nrf51822/periph/spi.c new file mode 100644 index 0000000000000000000000000000000000000000..f97c3058788a1330edb8eadec4416f0c9106bcbf --- /dev/null +++ b/cpu/nrf51822/periph/spi.c @@ -0,0 +1,235 @@ +/* + * 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 gpio.c + * @brief Low-level SPI driver implementation + * + * @author Hauke Petersen <hauke.petersen@fu-berlin.de> + * @author Frank Holtz <frank-riot2015@holtznet.de> + * + * @} + */ + +#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_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 + } + return 0; +} + +int spi_transfer_byte(spi_t dev, char out, char *in) +{ + return spi_transfer_bytes(dev, &out, in, 1); +} + +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_bytes(spi_t dev, char *out, char *in, unsigned int length) +{ + if (dev >= SPI_NUMOF) { + return -1; + } + + for (int i = 0; i < length; i++) { + spi[dev]->EVENTS_READY = 0; + spi[dev]->TXD = (uint8_t)out[i]; + while (spi[dev]->EVENTS_READY != 1); + if (in) { + in[i] = (char)spi[dev]->RXD; + } + } + + 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 */