1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2025-12-17 02:23:49 +01:00

Merge pull request #9698 from smlng/pr/cc2538/spi

cpu/cc2538: refine periph/spi implementation
This commit is contained in:
Peter Kietzmann 2018-08-10 12:30:18 +02:00 committed by GitHub
commit 25a487e3a9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 107 additions and 163 deletions

View File

@ -103,11 +103,11 @@ static const i2c_conf_t i2c_config[] = {
*/ */
static const spi_conf_t spi_config[] = { static const spi_conf_t spi_config[] = {
{ {
.dev = SSI0, .num = 0,
.mosi_pin = GPIO_PA4, .mosi_pin = GPIO_PIN(0, 4),
.miso_pin = GPIO_PA5, .miso_pin = GPIO_PIN(0, 5),
.sck_pin = GPIO_PA2, .sck_pin = GPIO_PIN(0, 2),
.cs_pin = GPIO_PD0 .cs_pin = GPIO_PIN(3, 0)
} }
}; };

View File

@ -130,11 +130,11 @@ static const i2c_conf_t i2c_config[] = {
*/ */
static const spi_conf_t spi_config[] = { static const spi_conf_t spi_config[] = {
{ {
.dev = SSI0, .num = 0,
.mosi_pin = GPIO_PA5, .mosi_pin = GPIO_PIN(0, 5),
.miso_pin = GPIO_PA4, .miso_pin = GPIO_PIN(0, 4),
.sck_pin = GPIO_PA2, .sck_pin = GPIO_PIN(0, 2),
.cs_pin = GPIO_PA3, .cs_pin = GPIO_PIN(0, 3)
}, },
}; };

View File

@ -126,11 +126,11 @@ static const i2c_conf_t i2c_config[] = {
*/ */
static const spi_conf_t spi_config[] = { static const spi_conf_t spi_config[] = {
{ {
.dev = SSI0, .num = 0,
.mosi_pin = GPIO_PA5, .mosi_pin = GPIO_PIN(0, 5),
.miso_pin = GPIO_PA4, .miso_pin = GPIO_PIN(0, 4),
.sck_pin = GPIO_PA2, .sck_pin = GPIO_PIN(0, 2),
.cs_pin = GPIO_PA3, .cs_pin = GPIO_PIN(0, 3)
}, },
}; };

View File

@ -51,17 +51,17 @@ static const i2c_conf_t i2c_config[] = {
*/ */
static const spi_conf_t spi_config[] = { static const spi_conf_t spi_config[] = {
{ {
.dev = SSI0, .num = 0,
.mosi_pin = GPIO_PD0, .mosi_pin = GPIO_PIN(3, 0),
.miso_pin = GPIO_PC4, .miso_pin = GPIO_PIN(2, 4),
.sck_pin = GPIO_PD1, .sck_pin = GPIO_PIN(3, 1),
.cs_pin = GPIO_PD3 .cs_pin = GPIO_PIN(3, 3)
}, },
{ {
.dev = SSI1, .num = 1,
.mosi_pin = GPIO_PC7, .mosi_pin = GPIO_PIN(2, 7),
.miso_pin = GPIO_PA4, .miso_pin = GPIO_PIN(0, 4),
.sck_pin = GPIO_PB5, .sck_pin = GPIO_PIN(1 ,5),
.cs_pin = GPIO_UNDEF .cs_pin = GPIO_UNDEF
} }
}; };

View File

@ -51,18 +51,18 @@ static const i2c_conf_t i2c_config[] = {
*/ */
static const spi_conf_t spi_config[] = { static const spi_conf_t spi_config[] = {
{ {
.dev = SSI0, .num = 0,
.mosi_pin = GPIO_PB1, .mosi_pin = GPIO_PIN(1, 1),
.miso_pin = GPIO_PB3, .miso_pin = GPIO_PIN(1, 3),
.sck_pin = GPIO_PB2, .sck_pin = GPIO_PIN(1, 2),
.cs_pin = GPIO_PB5 .cs_pin = GPIO_PIN(1, 5)
}, },
{ {
.dev = SSI1, .num = 1,
.mosi_pin = GPIO_PC5, .mosi_pin = GPIO_PIN(2, 5),
.miso_pin = GPIO_PC6, .miso_pin = GPIO_PIN(2, 6),
.sck_pin = GPIO_PC4, .sck_pin = GPIO_PIN(2, 4),
.cs_pin = GPIO_PA7 .cs_pin = GPIO_PIN(0, 7)
} }
}; };

View File

@ -54,18 +54,18 @@ static const i2c_conf_t i2c_config[] = {
*/ */
static const spi_conf_t spi_config[] = { static const spi_conf_t spi_config[] = {
{ {
.dev = SSI0, .num = 0,
.mosi_pin = GPIO_PB1, .mosi_pin = GPIO_PIN(1, 1),
.miso_pin = GPIO_PB3, .miso_pin = GPIO_PIN(1, 3),
.sck_pin = GPIO_PB2, .sck_pin = GPIO_PIN(1, 2),
.cs_pin = GPIO_PB5 .cs_pin = GPIO_PIN(1, 5)
}, },
{ {
.dev = SSI1, .num = 1,
.mosi_pin = GPIO_PC5, .mosi_pin = GPIO_PIN(2, 5),
.miso_pin = GPIO_PC6, .miso_pin = GPIO_PIN(2, 6),
.sck_pin = GPIO_PC4, .sck_pin = GPIO_PIN(2, 4),
.cs_pin = GPIO_PA7 .cs_pin = GPIO_PIN(0, 7)
} }
}; };
#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0])) #define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0]))

View File

@ -14,6 +14,7 @@
* @brief CC2538 SSI interface * @brief CC2538 SSI interface
* *
* @author Ian Martin <ian@locicontrols.com> * @author Ian Martin <ian@locicontrols.com>
* @author Sebastian Meiling <s@mlng.net>
*/ */
#ifndef CC2538_SSI_H #ifndef CC2538_SSI_H
@ -29,92 +30,31 @@ extern "C" {
* @brief SSI component registers * @brief SSI component registers
*/ */
typedef struct { typedef struct {
union { cc2538_reg_t CR0; /**< SSI Control Register 0 */
cc2538_reg_t CR0; /**< SSI Control Register 0 */ cc2538_reg_t CR1; /**< SSI Control Register 1 */
struct { cc2538_reg_t DR; /**< SSI Data register */
cc2538_reg_t DSS : 4; /**< SSI data size select */ cc2538_reg_t SR; /**< SSI FIFO/busy Status Register */
cc2538_reg_t FRF : 2; /**< SSI frame format select */ cc2538_reg_t CPSR; /**< SSI Clock Register */
cc2538_reg_t SPO : 1; /**< SSI serial clock polarity */ cc2538_reg_t IM; /**< SSI Interrupt Mask register */
cc2538_reg_t SPH : 1; /**< SSI serial clock phase */ cc2538_reg_t RIS; /**< SSI Raw Interrupt Status register */
cc2538_reg_t SCR : 8; /**< SSI serial clock rate */ cc2538_reg_t MIS; /**< SSI Masked Interrupt Status register */
cc2538_reg_t RESERVED : 16; /**< Reserved bits */ cc2538_reg_t ICR; /**< SSI Interrupt Clear Register */
} CR0bits; cc2538_reg_t DMACTL; /**< SSI uDMA Control Register. */
}; cc2538_reg_t CC; /**< SSI clock configuration */
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_ssi_t; } 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_DSS(x) (x - 1)
#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)
/** @} */
/** /**
* @brief Define CC register bitfields * @brief Define CC register bitfields
* @{ * @{
*/ */
#define SSI_SS_PIOSC (1 << 0) #define SSI_CC_CS_SYSDIV (0x0)
#define SSI_SS_DSEN (1 << 2) #define SSI_CC_CS_IODIV (0x1)
#define SSI_SS_SYSDIV (0) #define SSI_CC_CS_DSEN (0x4)
#define SSI_SS_IODIV (SSI_SS_PIOSC)
/** @} */ /** @} */
#ifdef __cplusplus #ifdef __cplusplus

View File

@ -25,6 +25,7 @@
#include <stdio.h> #include <stdio.h>
#include "cpu.h" #include "cpu.h"
#include "vendor/hw_ssi.h"
#ifdef __cplusplus #ifdef __cplusplus
extern "C" { extern "C" {
@ -60,6 +61,10 @@ typedef uint32_t gpio_t;
*/ */
#define GPIO_UNDEF (0xffffffff) #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 * @brief Define a custom GPIO_PIN macro
* *
@ -217,7 +222,7 @@ static const spi_clk_conf_t spi_clk_config[] = {
* @{ * @{
*/ */
typedef struct { 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 mosi_pin; /**< pin used for MOSI */
gpio_t miso_pin; /**< pin used for MISO */ gpio_t miso_pin; /**< pin used for MISO */
gpio_t sck_pin; /**< pin used for SCK */ gpio_t sck_pin; /**< pin used for SCK */

View File

@ -264,13 +264,13 @@ void gpio_init_mux(gpio_t pin, uint8_t over, uint8_t sel, uint8_t func)
{ {
assert(pin != GPIO_UNDEF); assert(pin != GPIO_UNDEF);
/* configure pin function and multiplexing */ /* configure pin function and multiplexing */
if (over != MODE_NOTSUP) { if (over != GPIO_MUX_NONE) {
IOC->OVER[_pp_num(pin)] = over; IOC->OVER[_pp_num(pin)] = over;
} }
if (sel != MODE_NOTSUP) { if (sel != GPIO_MUX_NONE) {
IOC->SEL[_pp_num(pin)] = sel; IOC->SEL[_pp_num(pin)] = sel;
} }
if (func != MODE_NOTSUP) { if (func != GPIO_MUX_NONE) {
IOC->PINS[func] = _pp_num(pin); IOC->PINS[func] = _pp_num(pin);
} }
/* enable alternative function mode */ /* enable alternative function mode */

View File

@ -21,11 +21,17 @@
* @} * @}
*/ */
#include "vendor/hw_memmap.h"
#include "vendor/hw_ssi.h"
#include "cpu.h" #include "cpu.h"
#include "mutex.h" #include "mutex.h"
#include "assert.h" #include "assert.h"
#include "periph/spi.h" #include "periph/spi.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
/** /**
* @brief Array holding one pre-initialized mutex for each SPI device * @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) 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) static inline void poweron(spi_t bus)
{ {
SYS_CTRL_RCGCSSI |= (1 << bus); SYS_CTRL_RCGCSSI |= (1 << spi_config[bus].num);
SYS_CTRL_SCGCSSI |= (1 << bus); SYS_CTRL_SCGCSSI |= (1 << spi_config[bus].num);
SYS_CTRL_DCGCSSI |= (1 << bus); SYS_CTRL_DCGCSSI |= (1 << spi_config[bus].num);
} }
static inline void poweroff(spi_t bus) static inline void poweroff(spi_t bus)
{ {
SYS_CTRL_RCGCSSI &= ~(1 << bus); SYS_CTRL_RCGCSSI &= ~(1 << spi_config[bus].num);
SYS_CTRL_SCGCSSI &= ~(1 << bus); SYS_CTRL_SCGCSSI &= ~(1 << spi_config[bus].num);
SYS_CTRL_DCGCSSI &= ~(1 << bus); SYS_CTRL_DCGCSSI &= ~(1 << spi_config[bus].num);
} }
void spi_init(spi_t bus) 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 */ /* temporarily power on the device */
poweron(bus); poweron(bus);
/* configure device to be a master and disable SSI operation mode */ /* configure device to be a master and disable SSI operation mode */
dev(bus)->CR1 = 0; dev(bus)->CR1 = 0;
/* configure system clock as SSI clock source */ /* 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 */ /* and power off the bus again */
poweroff(bus); poweroff(bus);
@ -69,37 +80,22 @@ void spi_init(spi_t bus)
void spi_init_pins(spi_t bus) void spi_init_pins(spi_t bus)
{ {
switch ((uintptr_t)spi_config[bus].dev) { DEBUG("%s: bus=%u\n", __FUNCTION__, bus);
case (uintptr_t)SSI0: /* select values according to SPI device */
IOC_PXX_SEL[spi_config[bus].mosi_pin] = SSI0_TXD; cc2538_ioc_sel_t txd = spi_config[bus].num ? SSI1_TXD : SSI0_TXD;
IOC_PXX_SEL[spi_config[bus].sck_pin ] = SSI0_CLK_OUT; cc2538_ioc_sel_t clk = spi_config[bus].num ? SSI1_CLK_OUT : SSI0_CLK_OUT;
IOC_PXX_SEL[spi_config[bus].cs_pin ] = SSI0_FSS_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;
IOC_SSIRXD_SSI0 = spi_config[bus].miso_pin; /* init pin functions and multiplexing */
break; 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);
case (uintptr_t)SSI1: gpio_init_mux(spi_config[bus].cs_pin, OVERRIDE_ENABLE, fss, GPIO_MUX_NONE);
IOC_PXX_SEL[spi_config[bus].mosi_pin] = SSI1_TXD; gpio_init_mux(spi_config[bus].miso_pin, OVERRIDE_DISABLE, GPIO_MUX_NONE, rxd);
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);
} }
int spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk) 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; (void) cs;
/* lock the bus */ /* lock the bus */
mutex_lock(&locks[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) void spi_release(spi_t bus)
{ {
DEBUG("%s: bus=%u\n", __FUNCTION__, bus);
/* disable and power off device */ /* disable and power off device */
dev(bus)->CR1 = 0; dev(bus)->CR1 = 0;
poweroff(bus); 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, void spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
const void *out, void *in, size_t len) 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; const uint8_t *out_buf = out;
uint8_t *in_buf = in; 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)){} while (!(dev(bus)->SR & SSI_SR_RNE)){}
in_buf[i] = dev(bus)->DR; in_buf[i] = dev(bus)->DR;
} }
/* wait until no more busy */ /* wait until no more busy */
while ((dev(bus)->SR & SSI_SR_BSY)) {} while ((dev(bus)->SR & SSI_SR_BSY)) {}
} }
if ((!cont) && (cs != SPI_CS_UNDEF)) { if ((!cont) && (cs != SPI_CS_UNDEF)) {