1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +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[] = {
{
.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)
}
};

View File

@ -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)
},
};

View File

@ -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)
},
};

View File

@ -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
}
};

View File

@ -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)
}
};

View File

@ -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]))

View File

@ -14,6 +14,7 @@
* @brief CC2538 SSI interface
*
* @author Ian Martin <ian@locicontrols.com>
* @author Sebastian Meiling <s@mlng.net>
*/
#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

View File

@ -25,6 +25,7 @@
#include <stdio.h>
#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 */

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);
/* 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 */

View File

@ -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)) {