diff --git a/boards/cc2538dk/include/periph_conf.h b/boards/cc2538dk/include/periph_conf.h index 098df406f4..ecce1b51f3 100644 --- a/boards/cc2538dk/include/periph_conf.h +++ b/boards/cc2538dk/include/periph_conf.h @@ -103,11 +103,11 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = SSI0, - .mosi_pin = GPIO_PA4, - .miso_pin = GPIO_PA5, - .sck_pin = GPIO_PA2, - .cs_pin = GPIO_PD0 + .num = 0, + .mosi_pin = GPIO_PIN(0, 4), + .miso_pin = GPIO_PIN(0, 5), + .sck_pin = GPIO_PIN(0, 2), + .cs_pin = GPIO_PIN(3, 0) } }; diff --git a/boards/openmote-b/include/periph_conf.h b/boards/openmote-b/include/periph_conf.h index ec5a11bcf7..cadfc6b8ae 100644 --- a/boards/openmote-b/include/periph_conf.h +++ b/boards/openmote-b/include/periph_conf.h @@ -130,11 +130,11 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = SSI0, - .mosi_pin = GPIO_PA5, - .miso_pin = GPIO_PA4, - .sck_pin = GPIO_PA2, - .cs_pin = GPIO_PA3, + .num = 0, + .mosi_pin = GPIO_PIN(0, 5), + .miso_pin = GPIO_PIN(0, 4), + .sck_pin = GPIO_PIN(0, 2), + .cs_pin = GPIO_PIN(0, 3) }, }; diff --git a/boards/openmote-cc2538/include/periph_conf.h b/boards/openmote-cc2538/include/periph_conf.h index 2db19aae76..8cd35e4d50 100644 --- a/boards/openmote-cc2538/include/periph_conf.h +++ b/boards/openmote-cc2538/include/periph_conf.h @@ -126,11 +126,11 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = SSI0, - .mosi_pin = GPIO_PA5, - .miso_pin = GPIO_PA4, - .sck_pin = GPIO_PA2, - .cs_pin = GPIO_PA3, + .num = 0, + .mosi_pin = GPIO_PIN(0, 5), + .miso_pin = GPIO_PIN(0, 4), + .sck_pin = GPIO_PIN(0, 2), + .cs_pin = GPIO_PIN(0, 3) }, }; diff --git a/boards/remote-pa/include/periph_conf.h b/boards/remote-pa/include/periph_conf.h index a21e022c7c..e5049f9221 100644 --- a/boards/remote-pa/include/periph_conf.h +++ b/boards/remote-pa/include/periph_conf.h @@ -51,17 +51,17 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = SSI0, - .mosi_pin = GPIO_PD0, - .miso_pin = GPIO_PC4, - .sck_pin = GPIO_PD1, - .cs_pin = GPIO_PD3 + .num = 0, + .mosi_pin = GPIO_PIN(3, 0), + .miso_pin = GPIO_PIN(2, 4), + .sck_pin = GPIO_PIN(3, 1), + .cs_pin = GPIO_PIN(3, 3) }, { - .dev = SSI1, - .mosi_pin = GPIO_PC7, - .miso_pin = GPIO_PA4, - .sck_pin = GPIO_PB5, + .num = 1, + .mosi_pin = GPIO_PIN(2, 7), + .miso_pin = GPIO_PIN(0, 4), + .sck_pin = GPIO_PIN(1 ,5), .cs_pin = GPIO_UNDEF } }; diff --git a/boards/remote-reva/include/periph_conf.h b/boards/remote-reva/include/periph_conf.h index c2d713d2d9..e2044e77a1 100644 --- a/boards/remote-reva/include/periph_conf.h +++ b/boards/remote-reva/include/periph_conf.h @@ -51,18 +51,18 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = SSI0, - .mosi_pin = GPIO_PB1, - .miso_pin = GPIO_PB3, - .sck_pin = GPIO_PB2, - .cs_pin = GPIO_PB5 + .num = 0, + .mosi_pin = GPIO_PIN(1, 1), + .miso_pin = GPIO_PIN(1, 3), + .sck_pin = GPIO_PIN(1, 2), + .cs_pin = GPIO_PIN(1, 5) }, { - .dev = SSI1, - .mosi_pin = GPIO_PC5, - .miso_pin = GPIO_PC6, - .sck_pin = GPIO_PC4, - .cs_pin = GPIO_PA7 + .num = 1, + .mosi_pin = GPIO_PIN(2, 5), + .miso_pin = GPIO_PIN(2, 6), + .sck_pin = GPIO_PIN(2, 4), + .cs_pin = GPIO_PIN(0, 7) } }; diff --git a/boards/remote-revb/include/periph_conf.h b/boards/remote-revb/include/periph_conf.h index 8b7322a3fa..14139802b5 100644 --- a/boards/remote-revb/include/periph_conf.h +++ b/boards/remote-revb/include/periph_conf.h @@ -54,18 +54,18 @@ static const i2c_conf_t i2c_config[] = { */ static const spi_conf_t spi_config[] = { { - .dev = SSI0, - .mosi_pin = GPIO_PB1, - .miso_pin = GPIO_PB3, - .sck_pin = GPIO_PB2, - .cs_pin = GPIO_PB5 + .num = 0, + .mosi_pin = GPIO_PIN(1, 1), + .miso_pin = GPIO_PIN(1, 3), + .sck_pin = GPIO_PIN(1, 2), + .cs_pin = GPIO_PIN(1, 5) }, { - .dev = SSI1, - .mosi_pin = GPIO_PC5, - .miso_pin = GPIO_PC6, - .sck_pin = GPIO_PC4, - .cs_pin = GPIO_PA7 + .num = 1, + .mosi_pin = GPIO_PIN(2, 5), + .miso_pin = GPIO_PIN(2, 6), + .sck_pin = GPIO_PIN(2, 4), + .cs_pin = GPIO_PIN(0, 7) } }; #define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) diff --git a/cpu/cc2538/include/cc2538_ssi.h b/cpu/cc2538/include/cc2538_ssi.h index 5fbdc004db..8efd0f3ba6 100644 --- a/cpu/cc2538/include/cc2538_ssi.h +++ b/cpu/cc2538/include/cc2538_ssi.h @@ -14,6 +14,7 @@ * @brief CC2538 SSI interface * * @author Ian Martin + * @author Sebastian Meiling */ #ifndef CC2538_SSI_H @@ -29,92 +30,31 @@ extern "C" { * @brief SSI component registers */ typedef struct { - union { - cc2538_reg_t CR0; /**< SSI Control Register 0 */ - struct { - cc2538_reg_t DSS : 4; /**< SSI data size select */ - cc2538_reg_t FRF : 2; /**< SSI frame format select */ - cc2538_reg_t SPO : 1; /**< SSI serial clock polarity */ - cc2538_reg_t SPH : 1; /**< SSI serial clock phase */ - cc2538_reg_t SCR : 8; /**< SSI serial clock rate */ - cc2538_reg_t RESERVED : 16; /**< Reserved bits */ - } CR0bits; - }; - - union { - cc2538_reg_t CR1; /**< SSI Control Register 1 */ - struct { - cc2538_reg_t LBM : 1; /**< SSI loop-back mode */ - cc2538_reg_t SSE : 1; /**< SSI synchronous serial port enable */ - cc2538_reg_t MS : 1; /**< SSI master and slave select */ - cc2538_reg_t SOD : 1; /**< SSI slave mode output disable */ - cc2538_reg_t RESERVED : 28; /**< Reserved bits */ - } CR1bits; - }; - - cc2538_reg_t DR; /**< SSI Data register */ - - union { - cc2538_reg_t SR; /**< SSI FIFO/busy Status Register */ - struct { - cc2538_reg_t TFE : 1; /**< SSI transmit FIFO empty */ - cc2538_reg_t TNF : 1; /**< SSI transmit FIFO not full */ - cc2538_reg_t RNE : 1; /**< SSI receive FIFO not empty */ - cc2538_reg_t RFF : 1; /**< SSI receive FIFO full */ - cc2538_reg_t BSY : 1; /**< SSI busy bit */ - cc2538_reg_t RESERVED : 27; /**< Reserved bits */ - } SRbits; - }; - cc2538_reg_t CPSR; /**< SSI Clock Register */ - cc2538_reg_t IM; /**< SSI Interrupt Mask register */ - cc2538_reg_t RIS; /**< SSI Raw Interrupt Status register */ - cc2538_reg_t MIS; /**< SSI Masked Interrupt Status register */ - cc2538_reg_t ICR; /**< SSI Interrupt Clear Register */ - cc2538_reg_t DMACTL; /**< SSI uDMA Control Register. */ - cc2538_reg_t CC; /**< SSI clock configuration */ + cc2538_reg_t CR0; /**< SSI Control Register 0 */ + cc2538_reg_t CR1; /**< SSI Control Register 1 */ + cc2538_reg_t DR; /**< SSI Data register */ + cc2538_reg_t SR; /**< SSI FIFO/busy Status Register */ + cc2538_reg_t CPSR; /**< SSI Clock Register */ + cc2538_reg_t IM; /**< SSI Interrupt Mask register */ + cc2538_reg_t RIS; /**< SSI Raw Interrupt Status register */ + cc2538_reg_t MIS; /**< SSI Masked Interrupt Status register */ + cc2538_reg_t ICR; /**< SSI Interrupt Clear Register */ + cc2538_reg_t DMACTL; /**< SSI uDMA Control Register. */ + cc2538_reg_t CC; /**< SSI clock configuration */ } cc2538_ssi_t; -#define SSI0 ( (cc2538_ssi_t*)0x40008000 ) /**< SSI0 Instance */ -#define SSI1 ( (cc2538_ssi_t*)0x40009000 ) /**< SSI1 Instance */ - /** - * @brief Define CR0 register bitfields - * @{ + * @brief Set CR0 data size (bits) */ -#define SSI_CR0_DSS(x) ((x - 1) << 0) -#define SSI_CR0_SPO (1 << 6) -#define SSI_CR0_SPH (1 << 7) -/** @} */ - -/** - * @brief Define CR1 register bitfields - * @{ - */ -#define SSI_CR1_LBM (1 << 0) -#define SSI_CR1_SSE (1 << 1) -#define SSI_CR1_MS (1 << 2) -#define SSI_CR1_SOD (1 << 3) -/** @} */ - -/** - * @brief Define SR register bitfields - * @{ - */ -#define SSI_SR_TFE (1 << 0) -#define SSI_SR_TNF (1 << 1) -#define SSI_SR_RNE (1 << 2) -#define SSI_SR_RFF (1 << 3) -#define SSI_SR_BSY (1 << 4) -/** @} */ +#define SSI_CR0_DSS(x) (x - 1) /** * @brief Define CC register bitfields * @{ */ -#define SSI_SS_PIOSC (1 << 0) -#define SSI_SS_DSEN (1 << 2) -#define SSI_SS_SYSDIV (0) -#define SSI_SS_IODIV (SSI_SS_PIOSC) +#define SSI_CC_CS_SYSDIV (0x0) +#define SSI_CC_CS_IODIV (0x1) +#define SSI_CC_CS_DSEN (0x4) /** @} */ #ifdef __cplusplus diff --git a/cpu/cc2538/include/periph_cpu.h b/cpu/cc2538/include/periph_cpu.h index 6ebce4cc6f..807727e6dd 100644 --- a/cpu/cc2538/include/periph_cpu.h +++ b/cpu/cc2538/include/periph_cpu.h @@ -25,6 +25,7 @@ #include #include "cpu.h" +#include "vendor/hw_ssi.h" #ifdef __cplusplus extern "C" { @@ -60,6 +61,10 @@ typedef uint32_t gpio_t; */ #define GPIO_UNDEF (0xffffffff) +/** + * @brief Custom value to indicate unused parameter in gpio_init_mux + */ +#define GPIO_MUX_NONE (0xff) /** * @brief Define a custom GPIO_PIN macro * @@ -217,7 +222,7 @@ static const spi_clk_conf_t spi_clk_config[] = { * @{ */ typedef struct { - cc2538_ssi_t *dev; /**< SSI device */ + uint8_t num; /**< number of SSI device, i.e. 0 or 1 */ gpio_t mosi_pin; /**< pin used for MOSI */ gpio_t miso_pin; /**< pin used for MISO */ gpio_t sck_pin; /**< pin used for SCK */ diff --git a/cpu/cc2538/periph/gpio.c b/cpu/cc2538/periph/gpio.c index 0dc3f2ef9b..f9196ed0b6 100644 --- a/cpu/cc2538/periph/gpio.c +++ b/cpu/cc2538/periph/gpio.c @@ -264,13 +264,13 @@ void gpio_init_mux(gpio_t pin, uint8_t over, uint8_t sel, uint8_t func) { assert(pin != GPIO_UNDEF); /* configure pin function and multiplexing */ - if (over != MODE_NOTSUP) { + if (over != GPIO_MUX_NONE) { IOC->OVER[_pp_num(pin)] = over; } - if (sel != MODE_NOTSUP) { + if (sel != GPIO_MUX_NONE) { IOC->SEL[_pp_num(pin)] = sel; } - if (func != MODE_NOTSUP) { + if (func != GPIO_MUX_NONE) { IOC->PINS[func] = _pp_num(pin); } /* enable alternative function mode */ diff --git a/cpu/cc2538/periph/spi.c b/cpu/cc2538/periph/spi.c index af1b08a259..6f8a1aeb65 100644 --- a/cpu/cc2538/periph/spi.c +++ b/cpu/cc2538/periph/spi.c @@ -21,11 +21,17 @@ * @} */ +#include "vendor/hw_memmap.h" +#include "vendor/hw_ssi.h" + #include "cpu.h" #include "mutex.h" #include "assert.h" #include "periph/spi.h" +#define ENABLE_DEBUG (0) +#include "debug.h" + /** * @brief Array holding one pre-initialized mutex for each SPI device */ @@ -33,33 +39,38 @@ static mutex_t locks[SPI_NUMOF]; static inline cc2538_ssi_t *dev(spi_t bus) { - return spi_config[bus].dev; + /* .num is either 0 or 1, return respective base address */ + return (spi_config[bus].num) ? (cc2538_ssi_t *)SSI1_BASE : (cc2538_ssi_t *)SSI0_BASE; } static inline void poweron(spi_t bus) { - SYS_CTRL_RCGCSSI |= (1 << bus); - SYS_CTRL_SCGCSSI |= (1 << bus); - SYS_CTRL_DCGCSSI |= (1 << bus); + SYS_CTRL_RCGCSSI |= (1 << spi_config[bus].num); + SYS_CTRL_SCGCSSI |= (1 << spi_config[bus].num); + SYS_CTRL_DCGCSSI |= (1 << spi_config[bus].num); } static inline void poweroff(spi_t bus) { - SYS_CTRL_RCGCSSI &= ~(1 << bus); - SYS_CTRL_SCGCSSI &= ~(1 << bus); - SYS_CTRL_DCGCSSI &= ~(1 << bus); + SYS_CTRL_RCGCSSI &= ~(1 << spi_config[bus].num); + SYS_CTRL_SCGCSSI &= ~(1 << spi_config[bus].num); + SYS_CTRL_DCGCSSI &= ~(1 << spi_config[bus].num); } void spi_init(spi_t bus) { - assert(bus <= SPI_NUMOF); + DEBUG("%s: bus=%u\n", __FUNCTION__, bus); + assert(bus < SPI_NUMOF); + + /* init mutex for given bus */ + mutex_init(&locks[bus]); /* temporarily power on the device */ poweron(bus); /* configure device to be a master and disable SSI operation mode */ dev(bus)->CR1 = 0; /* configure system clock as SSI clock source */ - dev(bus)->CC = SSI_SS_IODIV; + dev(bus)->CC = SSI_CC_CS_IODIV; /* and power off the bus again */ poweroff(bus); @@ -69,37 +80,22 @@ void spi_init(spi_t bus) void spi_init_pins(spi_t bus) { - switch ((uintptr_t)spi_config[bus].dev) { - case (uintptr_t)SSI0: - IOC_PXX_SEL[spi_config[bus].mosi_pin] = SSI0_TXD; - IOC_PXX_SEL[spi_config[bus].sck_pin ] = SSI0_CLK_OUT; - IOC_PXX_SEL[spi_config[bus].cs_pin ] = SSI0_FSS_OUT; - - IOC_SSIRXD_SSI0 = spi_config[bus].miso_pin; - break; - - case (uintptr_t)SSI1: - IOC_PXX_SEL[spi_config[bus].mosi_pin] = SSI1_TXD; - IOC_PXX_SEL[spi_config[bus].sck_pin ] = SSI1_CLK_OUT; - IOC_PXX_SEL[spi_config[bus].cs_pin ] = SSI1_FSS_OUT; - - IOC_SSIRXD_SSI1 = spi_config[bus].miso_pin; - break; - } - - IOC_PXX_OVER[spi_config[bus].mosi_pin] = IOC_OVERRIDE_OE; - IOC_PXX_OVER[spi_config[bus].miso_pin] = IOC_OVERRIDE_DIS; - IOC_PXX_OVER[spi_config[bus].sck_pin ] = IOC_OVERRIDE_OE; - IOC_PXX_OVER[spi_config[bus].cs_pin ] = IOC_OVERRIDE_OE; - - gpio_hardware_control(spi_config[bus].mosi_pin); - gpio_hardware_control(spi_config[bus].miso_pin); - gpio_hardware_control(spi_config[bus].sck_pin); - gpio_hardware_control(spi_config[bus].cs_pin); + DEBUG("%s: bus=%u\n", __FUNCTION__, bus); + /* select values according to SPI device */ + cc2538_ioc_sel_t txd = spi_config[bus].num ? SSI1_TXD : SSI0_TXD; + cc2538_ioc_sel_t clk = spi_config[bus].num ? SSI1_CLK_OUT : SSI0_CLK_OUT; + cc2538_ioc_sel_t fss = spi_config[bus].num ? SSI1_FSS_OUT : SSI0_FSS_OUT; + cc2538_ioc_pin_t rxd = spi_config[bus].num ? SSI1_RXD : SSI0_RXD; + /* init pin functions and multiplexing */ + gpio_init_mux(spi_config[bus].mosi_pin, OVERRIDE_ENABLE, txd, GPIO_MUX_NONE); + gpio_init_mux(spi_config[bus].sck_pin, OVERRIDE_ENABLE, clk, GPIO_MUX_NONE); + gpio_init_mux(spi_config[bus].cs_pin, OVERRIDE_ENABLE, fss, GPIO_MUX_NONE); + gpio_init_mux(spi_config[bus].miso_pin, OVERRIDE_DISABLE, GPIO_MUX_NONE, rxd); } int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) { + DEBUG("%s: bus=%u\n", __FUNCTION__, bus); (void) cs; /* lock the bus */ mutex_lock(&locks[bus]); @@ -117,6 +113,7 @@ int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) void spi_release(spi_t bus) { + DEBUG("%s: bus=%u\n", __FUNCTION__, bus); /* disable and power off device */ dev(bus)->CR1 = 0; poweroff(bus); @@ -127,6 +124,8 @@ void spi_release(spi_t bus) void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, const void *out, void *in, size_t len) { + DEBUG("%s: bus=%u, len=%u\n", __FUNCTION__, bus, (unsigned)len); + const uint8_t *out_buf = out; uint8_t *in_buf = in; @@ -167,8 +166,8 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, while (!(dev(bus)->SR & SSI_SR_RNE)){} in_buf[i] = dev(bus)->DR; } - /* wait until no more busy */ - while ((dev(bus)->SR & SSI_SR_BSY)) {} + /* wait until no more busy */ + while ((dev(bus)->SR & SSI_SR_BSY)) {} } if ((!cont) && (cs != SPI_CS_UNDEF)) {