From a0d188fd6b5e3433ed8b92267abd89fdb9eec136 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 31 Jan 2020 08:55:29 +0100 Subject: [PATCH 1/5] cpu/lpc2387: convert periph/spi to struct based operation --- cpu/lpc2387/include/vendor/lpc23xx.h | 18 ++++++++++++++++++ cpu/lpc2387/periph/spi.c | 20 ++++++++++---------- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/cpu/lpc2387/include/vendor/lpc23xx.h b/cpu/lpc2387/include/vendor/lpc23xx.h index 63f2e8c7d9c1..60dc70e1f63f 100644 --- a/cpu/lpc2387/include/vendor/lpc23xx.h +++ b/cpu/lpc2387/include/vendor/lpc23xx.h @@ -809,8 +809,25 @@ typedef struct { #define S0SPCCR (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x0C)) #define S0SPINT (*(volatile unsigned long *)(SPI0_BASE_ADDR + 0x1C)) +/** + * @brief Generic SPI register map + */ +typedef struct { + REG32 CR0; /**< Control Register 0 */ + REG32 CR1; /**< Control Register 1 */ + REG32 DR; /**< Data Register */ + REG32 SR; /**< Status Register */ + REG32 CPSR; /**< Clock Prescale Register */ + REG32 IMSC; /**< Interrupt Mask Set/Clear Register */ + REG32 RIS; /**< Raw Interrupt Status Register */ + REG32 MIS; /**< Masked Interrupt Status Register */ + REG32 ICR; /**< Interrupt Clear Register */ + REG32 DMACR; /**< DMA Control Register */ +} lpc23xx_spi_t; + /* SSP0 Controller */ #define SSP0_BASE_ADDR 0xE0068000 +#define SPI0 ((lpc23xx_spi_t *)SSP0_BASE_ADDR) #define SSP0CR0 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x00)) #define SSP0CR1 (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x04)) #define SSP0DR (*(volatile unsigned long *)(SSP0_BASE_ADDR + 0x08)) @@ -824,6 +841,7 @@ typedef struct { /* SSP1 Controller */ #define SSP1_BASE_ADDR 0xE0030000 +#define SPI1 ((lpc23xx_spi_t *)SSP1_BASE_ADDR) #define SSP1CR0 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x00)) #define SSP1CR1 (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x04)) #define SSP1DR (*(volatile unsigned long *)(SSP1_BASE_ADDR + 0x08)) diff --git a/cpu/lpc2387/periph/spi.c b/cpu/lpc2387/periph/spi.c index 3fe63bd95d8a..20c9722839db 100644 --- a/cpu/lpc2387/periph/spi.c +++ b/cpu/lpc2387/periph/spi.c @@ -34,9 +34,9 @@ #define ENABLE_DEBUG (0) #include "debug.h" -#define SPI_TX_EMPTY (SSP0SR & SSPSR_TFE) -#define SPI_BUSY (SSP0SR & SSPSR_BSY) -#define SPI_RX_AVAIL (SSP0SR & SSPSR_RNE) +#define SPI_TX_EMPTY (SPI0->SR & SSPSR_TFE) +#define SPI_BUSY (SPI0->SR & SSPSR_BSY) +#define SPI_RX_AVAIL (SPI0->SR & SSPSR_RNE) /** * @brief Array holding one pre-initialized mutex for each SPI device @@ -80,21 +80,21 @@ int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) /* power on */ PCONP |= (PCSSP0); /* interface setup */ - SSP0CR0 = 7; + SPI0->CR0 = 7; /* configure bus clock */ lpc2387_pclk_scale(CLOCK_CORECLOCK / 1000, (uint32_t)clk, &pclksel, &cpsr); PCLKSEL1 &= ~(BIT10 | BIT11); /* CCLK to PCLK divider*/ PCLKSEL1 |= pclksel << 10; - SSP0CPSR = cpsr; + SPI0->CPSR = cpsr; /* enable the bus */ - SSP0CR1 |= BIT1; + SPI0->CR1 |= BIT1; /* clear RxFIFO */ int dummy; while (SPI_RX_AVAIL) { /* while RNE (Receive FIFO Not Empty)...*/ - dummy = SSP0DR; /* read data*/ + dummy = SPI0->DR; /* read data*/ } (void) dummy; /* to suppress unused-but-set-variable */ @@ -105,7 +105,7 @@ void spi_release(spi_t bus) { (void) bus; /* disable, power off, and release the bus */ - SSP0CR1 &= ~(BIT1); + SPI0->CR1 &= ~(BIT1); PCONP &= ~(PCSSP0); mutex_unlock(&lock); } @@ -127,10 +127,10 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, for (size_t i = 0; i < len; i++) { uint8_t tmp = (out_buf) ? out_buf[i] : 0; while (!SPI_TX_EMPTY) {} - SSP0DR = tmp; + SPI0->DR = tmp; while (SPI_BUSY) {} while (!SPI_RX_AVAIL) {} - tmp = (uint8_t)SSP0DR; + tmp = (uint8_t)SPI0->DR; if (in_buf) { in_buf[i] = tmp; } From 3f01f4b1830c6f8280631a6cb8fdfcc64a82cd89 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 31 Jan 2020 09:22:05 +0100 Subject: [PATCH 2/5] cpu/lpc2387: make periph/spi configurable --- cpu/lpc2387/include/periph_cpu.h | 13 ++++ cpu/lpc2387/periph/spi.c | 115 ++++++++++++++++++++++--------- 2 files changed, 95 insertions(+), 33 deletions(-) diff --git a/cpu/lpc2387/include/periph_cpu.h b/cpu/lpc2387/include/periph_cpu.h index c8e4d1c21d01..6bc2d1b08f0d 100644 --- a/cpu/lpc2387/include/periph_cpu.h +++ b/cpu/lpc2387/include/periph_cpu.h @@ -110,6 +110,19 @@ typedef struct { uint32_t pinsel_msk_tx; /**< TX PINSEL Mask */ } uart_conf_t; +/** + * @brief SPI device configuration + */ +typedef struct { + lpc23xx_spi_t *dev; /**< pointer to the SPI device */ + uint8_t pinsel_mosi; /**< PINSEL# of the MOSI pin */ + uint8_t pinsel_miso; /**< PINSEL# of the MISO pin */ + uint8_t pinsel_clk; /**< PINSEL# of the CLK pin */ + uint32_t pinsel_msk_mosi; /**< MOSI PINSEL Mask */ + uint32_t pinsel_msk_miso; /**< MISO PINSEL Mask */ + uint32_t pinsel_msk_clk; /**< CLK PINSEL Mask */ +} spi_conf_t; + /** * @brief Number of available timer channels */ diff --git a/cpu/lpc2387/periph/spi.c b/cpu/lpc2387/periph/spi.c index 20c9722839db..1da169aeaab6 100644 --- a/cpu/lpc2387/periph/spi.c +++ b/cpu/lpc2387/periph/spi.c @@ -34,90 +34,137 @@ #define ENABLE_DEBUG (0) #include "debug.h" -#define SPI_TX_EMPTY (SPI0->SR & SSPSR_TFE) -#define SPI_BUSY (SPI0->SR & SSPSR_BSY) -#define SPI_RX_AVAIL (SPI0->SR & SSPSR_RNE) +/** + * @brief Get the pointer to the base register of the given SPI device + * + * @param[in] dev SPI device identifier + * + * @return base register address + */ +static inline lpc23xx_spi_t *get_dev(spi_t dev) +{ + return spi_config[dev].dev; +} /** * @brief Array holding one pre-initialized mutex for each SPI device */ -static mutex_t lock = MUTEX_INIT; +static mutex_t lock[SPI_NUMOF]; + +static void _power_off(spi_t bus) +{ + switch ((uint32_t) get_dev(bus)) { + case SSP0_BASE_ADDR: + PCONP &= ~PCSSP0; + break; + case SSP1_BASE_ADDR: + PCONP &= ~PCSSP1; + break; + } +} + +static void _power_on(spi_t bus) +{ + switch ((uint32_t) get_dev(bus)) { + case SSP0_BASE_ADDR: + PCONP |= PCSSP0; + break; + case SSP1_BASE_ADDR: + PCONP |= PCSSP1; + break; + } +} void spi_init(spi_t bus) { - assert(bus == SPI_DEV(0)); + assert(bus < SPI_NUMOF); /* configure pins */ spi_init_pins(bus); + /* power off the bus (default is on) */ - PCONP &= ~(PCSSP0); + _power_off(bus); } void spi_init_pins(spi_t bus) { - (void) bus; + const spi_conf_t *cfg = &spi_config[bus]; - PINSEL3 |= (BIT8 | BIT9); /* SCLK */ - PINSEL3 |= (BIT14 | BIT15); /* MISO */ - PINSEL3 |= (BIT16 | BIT17); /* MOSI */ + *(&PINSEL0 + cfg->pinsel_mosi) |= cfg->pinsel_msk_mosi; + *(&PINSEL0 + cfg->pinsel_miso) |= cfg->pinsel_msk_miso; + *(&PINSEL0 + cfg->pinsel_clk) |= cfg->pinsel_msk_clk; } int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) { - (void) bus; (void) cs; uint32_t pclksel; uint32_t cpsr; + lpc23xx_spi_t *dev = get_dev(bus); + /* only support for mode 0 at the moment */ if (mode != SPI_MODE_0) { return SPI_NOMODE; } /* lock bus */ - mutex_lock(&lock); + mutex_lock(&lock[bus]); + /* power on */ - PCONP |= (PCSSP0); + _power_on(bus); + /* interface setup */ - SPI0->CR0 = 7; + dev->CR0 = 7; /* configure bus clock */ lpc2387_pclk_scale(CLOCK_CORECLOCK / 1000, (uint32_t)clk, &pclksel, &cpsr); - PCLKSEL1 &= ~(BIT10 | BIT11); /* CCLK to PCLK divider*/ - PCLKSEL1 |= pclksel << 10; - SPI0->CPSR = cpsr; + + switch ((uint32_t)dev) { + case SSP0_BASE_ADDR: + PCLKSEL1 &= ~(BIT10 | BIT11); /* CCLK to PCLK divider*/ + PCLKSEL1 |= pclksel << 10; + break; + case SSP1_BASE_ADDR: + PCLKSEL0 &= ~(BIT20 | BIT21); /* CCLK to PCLK divider*/ + PCLKSEL0 |= pclksel << 20; + break; + } + + dev->CPSR = cpsr; /* enable the bus */ - SPI0->CR1 |= BIT1; + dev->CR1 |= BIT1; /* clear RxFIFO */ - int dummy; - while (SPI_RX_AVAIL) { /* while RNE (Receive FIFO Not Empty)...*/ - dummy = SPI0->DR; /* read data*/ + while (dev->SR & SSPSR_RNE) { /* while RNE (Receive FIFO Not Empty)...*/ + dev->DR; /* read data*/ } - (void) dummy; /* to suppress unused-but-set-variable */ return SPI_OK; } void spi_release(spi_t bus) { - (void) bus; + lpc23xx_spi_t *dev = get_dev(bus); + /* disable, power off, and release the bus */ - SPI0->CR1 &= ~(BIT1); - PCONP &= ~(PCSSP0); - mutex_unlock(&lock); + dev->CR1 &= ~BIT1; + + _power_off(bus); + + mutex_unlock(&lock[bus]); } void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, const void *out, void *in, size_t len) { - (void) bus; - const uint8_t *out_buf = out; uint8_t *in_buf = in; + lpc23xx_spi_t *dev = get_dev(bus); + assert(out_buf || in_buf); if (cs != SPI_CS_UNDEF) { @@ -126,11 +173,13 @@ void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont, for (size_t i = 0; i < len; i++) { uint8_t tmp = (out_buf) ? out_buf[i] : 0; - while (!SPI_TX_EMPTY) {} - SPI0->DR = tmp; - while (SPI_BUSY) {} - while (!SPI_RX_AVAIL) {} - tmp = (uint8_t)SPI0->DR; + /* wait for TX buffer empty */ + while (!(dev->SR & SSPSR_TFE)) {} + dev->DR = tmp; + while (dev->SR & SSPSR_BSY) {} + /* wait for RX not empty */ + while (!(dev->SR & SSPSR_RNE)) {} + tmp = (uint8_t)dev->DR; if (in_buf) { in_buf[i] = tmp; } From 3ae7bb425bc4ef1a2d5a475e352f33d00c61ff1d Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 31 Jan 2020 09:22:24 +0100 Subject: [PATCH 3/5] boards/msba2: update SPI configuration --- boards/msba2/include/periph_conf.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/boards/msba2/include/periph_conf.h b/boards/msba2/include/periph_conf.h index f92c6144d9b9..ccac661023da 100644 --- a/boards/msba2/include/periph_conf.h +++ b/boards/msba2/include/periph_conf.h @@ -113,11 +113,20 @@ static const uart_conf_t uart_config[] = { /** * @name SPI configuration - * - * The SPI implementation is very much fixed, so we don't need to configure - * anything besides the mandatory SPI_NUMOF. * @{ */ +static const spi_conf_t spi_config[] = { + { + .dev = SPI0, + .pinsel_mosi = 3, + .pinsel_miso = 3, + .pinsel_clk = 3, + .pinsel_msk_mosi = (BIT16 | BIT17), + .pinsel_msk_miso = (BIT14 | BIT15), + .pinsel_msk_clk = (BIT8 | BIT9), + }, +}; + #define SPI_NUMOF (1) /** @} */ From 985d3406212a5d424f9a0e7ae5382fdc1c7d4a25 Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Fri, 31 Jan 2020 11:57:57 +0100 Subject: [PATCH 4/5] boards/avsextrem: update SPI config --- boards/avsextrem/include/periph_conf.h | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/boards/avsextrem/include/periph_conf.h b/boards/avsextrem/include/periph_conf.h index f010903b671c..ace679fc996d 100644 --- a/boards/avsextrem/include/periph_conf.h +++ b/boards/avsextrem/include/periph_conf.h @@ -65,7 +65,19 @@ static const uart_conf_t uart_config[] = { * @name SPI configuration * @{ */ -#define SPI_NUMOF (1U) +static const spi_conf_t spi_config[] = { + { + .dev = SPI0, + .pinsel_mosi = 3, + .pinsel_miso = 3, + .pinsel_clk = 3, + .pinsel_msk_mosi = (BIT16 | BIT17), + .pinsel_msk_miso = (BIT14 | BIT15), + .pinsel_msk_clk = (BIT8 | BIT9), + }, +}; + +#define SPI_NUMOF (1) /** @} */ #ifdef __cplusplus From d675eb7cbb7f49b4b4d6254f974465081fbc10ac Mon Sep 17 00:00:00 2001 From: Benjamin Valentin Date: Mon, 10 Feb 2020 13:41:00 +0100 Subject: [PATCH 5/5] boards/mcb2388: update SPI configuration --- boards/mcb2388/include/periph_conf.h | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/boards/mcb2388/include/periph_conf.h b/boards/mcb2388/include/periph_conf.h index f6e5babfc229..7803a94739b7 100644 --- a/boards/mcb2388/include/periph_conf.h +++ b/boards/mcb2388/include/periph_conf.h @@ -71,11 +71,20 @@ static const uart_conf_t uart_config[] = { /** * @name SPI configuration - * - * The SPI implementation is very much fixed, so we don't need to configure - * anything besides the mandatory SPI_NUMOF. * @{ */ +static const spi_conf_t spi_config[] = { + { + .dev = SPI0, + .pinsel_mosi = 3, + .pinsel_miso = 3, + .pinsel_clk = 3, + .pinsel_msk_mosi = (BIT16 | BIT17), /* P1.24 */ + .pinsel_msk_miso = (BIT14 | BIT15), /* P1.23 */ + .pinsel_msk_clk = (BIT8 | BIT9), /* P1.20 */ + }, +}; + #define SPI_NUMOF (1) /** @} */