Skip to content

Commit

Permalink
Merge pull request #11293 from gschorcht/cpu/esp32/periph/conf/spi
Browse files Browse the repository at this point in the history
boards/esp32: changes the approach for configurations of SPI interfaces in board definitions
  • Loading branch information
leandrolanzieri authored May 14, 2019
2 parents 171058d + 23cc987 commit 44d9819
Show file tree
Hide file tree
Showing 3 changed files with 84 additions and 62 deletions.
26 changes: 25 additions & 1 deletion boards/common/esp32/include/periph_conf_common.h
Original file line number Diff line number Diff line change
Expand Up @@ -171,6 +171,30 @@ static const gpio_t pwm1_channels[] = PWM1_GPIOS;
* @name SPI configuration
*/

/**
* @brief Static array with configuration for declared I2C devices
*/
static const spi_conf_t spi_config[] = {
#ifdef SPI0_CTRL
{
.ctrl = SPI0_CTRL,
.sck = SPI0_SCK,
.mosi = SPI0_MOSI,
.miso = SPI0_MISO,
.cs = SPI0_CS0,
},
#endif
#ifdef SPI1_CTRL
{
.ctrl = SPI1_CTRL,
.sck = SPI1_SCK,
.mosi = SPI1_MOSI,
.miso = SPI1_MISO,
.cs = SPI1_CS0,
},
#endif
};

/**
* @brief Number of SPI interfaces
*
Expand All @@ -179,7 +203,7 @@ static const gpio_t pwm1_channels[] = PWM1_GPIOS;
*
* @note SPI_NUMOF definition must not be changed.
*/
#define SPI_NUMOF (spi_bus_num)
#define SPI_NUMOF (sizeof(spi_config) / sizeof(spi_config[0]))

/** @} */

Expand Down
30 changes: 22 additions & 8 deletions cpu/esp32/include/periph_cpu.h
Original file line number Diff line number Diff line change
Expand Up @@ -374,8 +374,8 @@ typedef struct {
*
* ESP32 has four SPI controllers:
*
* - controller SPI0 is reserved for caching the flash memory
* - controller SPI1 is reserved for external memories like flash and PSRAM
* - controller SPI0 is reserved for caching the flash memory (CPSI)
* - controller SPI1 is reserved for external memories like flash and PSRAM (FSPI)
* - controller SPI2 realizes interface HSPI that can be used for peripherals
* - controller SPI3 realizes interface VSPI that can be used for peripherals
*
Expand All @@ -397,17 +397,31 @@ typedef struct {
* - SPIn_CS0, the GPIO used as CS signal when the cs parameter in spi_aquire
* is GPIO_UNDEF,
*
* where n can be 0 or 1.
*
* @note The configuration of the SPI interfaces SPI_DEV(n) should be in
* continuous ascending order of n.
* where n can be 0 or 1. If they are not defined, the according SPI interface
* SPI_DEV(n) is not used.
*
* SPI_NUMOF is determined automatically from the board-specific peripheral
* definitions of SPIn_*.
*/

/** Number of SPI interfaces determined from SPI_* definitions */
extern const unsigned spi_bus_num;
/**
* @brief SPI controllers that can be used for peripheral interfaces
*/
typedef enum {
HSPI = 2, /**< HSPI interface controller */
VSPI = 3, /**< VSPI interface controller */
} spi_ctrl_t;

/**
* @brief SPI configuration structure type
*/
typedef struct {
spi_ctrl_t ctrl; /**< SPI controller used for the interface */
gpio_t sck; /**< GPIO used as SCK pin */
gpio_t mosi; /**< GPIO used as MOSI pin */
gpio_t miso; /**< GPIO used as MISO pin */
gpio_t cs; /**< GPIO used as CS0 pin */
} spi_conf_t;

#define PERIPH_SPI_NEEDS_TRANSFER_BYTE /**< requires function spi_transfer_byte */
#define PERIPH_SPI_NEEDS_TRANSFER_REG /**< requires function spi_transfer_reg */
Expand Down
90 changes: 37 additions & 53 deletions cpu/esp32/periph/spi.c
Original file line number Diff line number Diff line change
Expand Up @@ -40,12 +40,9 @@

#include "gpio_arch.h"

#define SPI_BLOCK_SIZE 64 /* number of bytes per SPI transfer */
#if defined(SPI0_CTRL) || defined(SPI1_CTRL)

#define CSPI (0) /* controller SPI0 realizes interface CSPI */
#define FSPI (1) /* controller SPI1 realizes interface FSPI */
#define HSPI (2) /* controller SPI2 realizes interface HSPI */
#define VSPI (3) /* controller SPI3 realizes interface VSPI */
#define SPI_BLOCK_SIZE 64 /* number of bytes per SPI transfer */

/* pins of FSI are fixed */
#define FSPI_SCK GPIO6
Expand All @@ -55,13 +52,8 @@
/** stucture which decribes all properties of one SPI bus */
struct _spi_bus_t {
spi_dev_t* regs; /* pointer to register data struct of the SPI device */
uint8_t controller; /* number of the controller used */
uint8_t mod; /* peripheral hardware module of the SPI interface */
uint8_t int_src; /* peripheral interrupt source used by the SPI device */
uint8_t pin_sck; /* SCK pin */
uint8_t pin_mosi; /* MOSI pin */
uint8_t pin_miso; /* MISO pin */
uint8_t pin_cs; /* CS pin */
uint8_t signal_sck; /* SCK signal from the controller */
uint8_t signal_mosi; /* MOSI signal from the controller */
uint8_t signal_miso; /* MISO signal to the controller */
Expand All @@ -73,48 +65,36 @@ struct _spi_bus_t {
static struct _spi_bus_t _spi[] = {
#ifdef SPI0_CTRL
{
.controller = SPI0_CTRL,
.pin_cs = SPI0_CS0,
.pin_sck = SPI0_SCK,
.pin_mosi = SPI0_MOSI,
.pin_miso = SPI0_MISO,
.initialized = false,
.pins_initialized = false,
.lock = MUTEX_INIT
},
#endif
#ifdef SPI1_CTRL
{
.controller = SPI1_CTRL,
.pin_cs = SPI1_CS0,
.pin_sck = SPI1_SCK,
.pin_mosi = SPI1_MOSI,
.pin_miso = SPI1_MISO,
.initialized = false,
.pins_initialized = false,
.lock = MUTEX_INIT
},
#endif
};

/* the number of SPI bus devices used */
const unsigned spi_bus_num = sizeof(_spi) / sizeof(_spi[0]);

#define CHECK_SPI_DEV(bus) { \
CHECK_PARAM(bus < spi_bus_num); \
CHECK_PARAM(bus < SPI_NUMOF); \
if (_spi[bus].regs == NULL) { \
LOG_TAG_ERROR("spi", "SPI_DEV(%d) is not available\n", bus); \
return; \
} \
}

#define CHECK_SPI_DEV_RET(bus,error) { \
CHECK_PARAM_RET(bus < spi_bus_num, error); \
CHECK_PARAM_RET(bus < SPI_NUMOF, error); \
if (_spi[bus].regs == NULL) { \
LOG_TAG_ERROR("spi", "SPI_DEV(%d) is not available\n", bus); \
return error; \
} \
}

/*
* GPIOs that were once initialized as SPI interface pins can not be used
* afterwards for anything else. Therefore, SPI interfaces are not initialized
Expand All @@ -127,9 +107,9 @@ const unsigned spi_bus_num = sizeof(_spi) / sizeof(_spi[0]);

void IRAM_ATTR spi_init (spi_t bus)
{
CHECK_PARAM(bus < spi_bus_num);
CHECK_PARAM(bus < SPI_NUMOF);

switch (_spi[bus].controller) {
switch (spi_config[bus].ctrl) {
case HSPI: _spi[bus].regs = &SPI2;
_spi[bus].mod = PERIPH_HSPI_MODULE;
_spi[bus].int_src = ETS_SPI2_INTR_SOURCE;
Expand All @@ -144,7 +124,9 @@ void IRAM_ATTR spi_init (spi_t bus)
_spi[bus].signal_mosi = VSPID_OUT_IDX;
_spi[bus].signal_miso = VSPIQ_IN_IDX;
break;
default: break;
default: LOG_TAG_ERROR("spi", "invalid SPI interface controller "
"used for SPI_DEV(%d)\n");
break;
}
return;
}
Expand All @@ -166,10 +148,10 @@ static void _spi_init_internal (spi_t bus)
spi_init_pins(bus);

/* check whether pins could be initialized, otherwise return */
if (gpio_get_pin_usage(_spi[bus].pin_sck) != _SPI &&
gpio_get_pin_usage(_spi[bus].pin_miso) != _SPI &&
gpio_get_pin_usage(_spi[bus].pin_mosi) != _SPI &&
gpio_get_pin_usage(_spi[bus].pin_cs) != _SPI) {
if (gpio_get_pin_usage(spi_config[bus].sck) != _SPI &&
gpio_get_pin_usage(spi_config[bus].miso) != _SPI &&
gpio_get_pin_usage(spi_config[bus].mosi) != _SPI &&
gpio_get_pin_usage(spi_config[bus].cs) != _SPI) {
return;
}

Expand Down Expand Up @@ -224,31 +206,31 @@ void spi_init_pins(spi_t bus)
as SPI pins */
if (bus != SPI_DEV(2)) {
/* if not already initialized as SPI, try to initialize the pins */
if (gpio_init (_spi[bus].pin_sck, GPIO_OUT) ||
gpio_init (_spi[bus].pin_mosi, GPIO_OUT) ||
gpio_init (_spi[bus].pin_miso, GPIO_IN)) {
if (gpio_init (spi_config[bus].sck, GPIO_OUT) ||
gpio_init (spi_config[bus].mosi, GPIO_OUT) ||
gpio_init (spi_config[bus].miso, GPIO_IN)) {
LOG_TAG_ERROR("spi",
"SPI_DEV(%d) pins could not be initialized\n", bus);
return;
}
if (spi_init_cs(bus, _spi[bus].pin_cs) != SPI_OK) {
if (spi_init_cs(bus, spi_config[bus].cs) != SPI_OK) {
LOG_TAG_ERROR("spi",
"SPI_DEV(%d) CS signal could not be initialized\n",
bus);
return;
}
/* store the usage type in GPIO table */
gpio_set_pin_usage(_spi[bus].pin_sck, _SPI);
gpio_set_pin_usage(_spi[bus].pin_mosi, _SPI);
gpio_set_pin_usage(_spi[bus].pin_miso, _SPI);
gpio_set_pin_usage(spi_config[bus].sck, _SPI);
gpio_set_pin_usage(spi_config[bus].mosi, _SPI);
gpio_set_pin_usage(spi_config[bus].miso, _SPI);

/* connect SCK and MOSI pins to the output signal through the GPIO matrix */
GPIO.func_out_sel_cfg[_spi[bus].pin_sck].func_sel = _spi[bus].signal_sck;
GPIO.func_out_sel_cfg[_spi[bus].pin_mosi].func_sel = _spi[bus].signal_mosi;
GPIO.func_out_sel_cfg[spi_config[bus].sck].func_sel = _spi[bus].signal_sck;
GPIO.func_out_sel_cfg[spi_config[bus].mosi].func_sel = _spi[bus].signal_mosi;
/* connect MISO input signal to the MISO pin through the GPIO matrix */
GPIO.func_in_sel_cfg[_spi[bus].signal_miso].sig_in_sel = 1;
GPIO.func_in_sel_cfg[_spi[bus].signal_miso].sig_in_inv = 0;
GPIO.func_in_sel_cfg[_spi[bus].signal_miso].func_sel = _spi[bus].pin_miso;
GPIO.func_in_sel_cfg[_spi[bus].signal_miso].func_sel = spi_config[bus].miso;
}
else {
LOG_TAG_WARNING("spi", "Using SPI_DEV(2) is dangerous\n");
Expand Down Expand Up @@ -298,7 +280,7 @@ int IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk
}

/* if parameter cs is GPIO_UNDEF, the default CS pin is used */
cs = (cs == GPIO_UNDEF) ? _spi[bus].pin_cs : cs;
cs = (cs == GPIO_UNDEF) ? spi_config[bus].cs : cs;

/* if the CS pin used is not yet initialized, we do it now */
if (gpio_get_pin_usage(cs) != _SPI && spi_init_cs(bus, cs) != SPI_OK) {
Expand Down Expand Up @@ -354,7 +336,7 @@ int IRAM_ATTR spi_acquire(spi_t bus, spi_cs_t cs, spi_mode_t mode, spi_clk_t clk
/* SPI clock is derived from APB clock by dividers */
_spi[bus].regs->clock.clk_equ_sysclk = 0;

/* set SPI clock deviders */
/* set SPI clock dividers */
_spi[bus].regs->clock.clkdiv_pre = spi_clkdiv_pre;
_spi[bus].regs->clock.clkcnt_n = spi_clkcnt_N;
_spi[bus].regs->clock.clkcnt_h = (spi_clkcnt_N+1)/2-1;
Expand All @@ -378,12 +360,12 @@ static const char* _spi_names[] = { "CSPI", "FSPI", "HSPI", "VSPI" };

void spi_print_config(void)
{
for (unsigned bus = 0; bus < spi_bus_num; bus++) {
ets_printf("\tSPI_DEV(%d)\t%s ", bus, _spi_names[_spi[bus].controller]);
ets_printf("sck=%d " , _spi[bus].pin_sck);
ets_printf("miso=%d ", _spi[bus].pin_miso);
ets_printf("mosi=%d ", _spi[bus].pin_mosi);
ets_printf("cs=%d\n" , _spi[bus].pin_cs);
for (unsigned bus = 0; bus < SPI_NUMOF; bus++) {
ets_printf("\tSPI_DEV(%d)\t%s ", bus, _spi_names[spi_config[bus].ctrl]);
ets_printf("sck=%d " , spi_config[bus].sck);
ets_printf("miso=%d ", spi_config[bus].miso);
ets_printf("mosi=%d ", spi_config[bus].mosi);
ets_printf("cs=%d\n" , spi_config[bus].cs);
}
}

Expand Down Expand Up @@ -453,7 +435,7 @@ static void IRAM_ATTR _spi_buf_transfer(uint8_t bus, const void *out, void *in,
}

void IRAM_ATTR 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)
{
CHECK_SPI_DEV(bus);

Expand All @@ -474,7 +456,7 @@ void IRAM_ATTR spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
}
#endif

gpio_clear (cs != SPI_CS_UNDEF ? cs : _spi[bus].pin_cs);
gpio_clear (cs != SPI_CS_UNDEF ? cs : spi_config[bus].cs);

size_t blocks = len / SPI_BLOCK_SIZE;
uint8_t tail = len % SPI_BLOCK_SIZE;
Expand All @@ -493,7 +475,7 @@ void IRAM_ATTR spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
in ? (uint8_t *)in + blocks * SPI_BLOCK_SIZE : NULL, tail);
}
if (!cont) {
gpio_set (cs != SPI_CS_UNDEF ? cs : _spi[bus].pin_cs);
gpio_set (cs != SPI_CS_UNDEF ? cs : spi_config[bus].cs);
}

#if ENABLE_DEBUG
Expand All @@ -506,3 +488,5 @@ void IRAM_ATTR spi_transfer_bytes(spi_t bus, spi_cs_t cs, bool cont,
}
#endif
}

#endif /* defined(SPI0_CTRL) || defined(SPI1_CTRL) */

0 comments on commit 44d9819

Please sign in to comment.