40 #error "ChibiOS operates only in SPI_MASTER mode (Slave is TODO)"
44 #error "ChibiOS architectures don't have SPI0"
48 #ifndef SPI_THREAD_STACK_SIZE
49 #define SPI_THREAD_STACK_SIZE 512
53 #ifndef SPI_DMA_BUF_LEN
54 #define SPI_DMA_BUF_LEN 512
59 #if defined(STM32F7XX) || defined(STM32H7XX)
110 return SPI_SELECT_SLAVE6_PORT;
115 return SPI_SELECT_SLAVE7_PORT;
120 return SPI_SELECT_SLAVE8_PORT;
172 return SPI_SELECT_SLAVE6_PIN;
177 return SPI_SELECT_SLAVE7_PIN;
182 return SPI_SELECT_SLAVE8_PIN;
206 #if defined(STM32F1XX) || defined(STM32F4XX)
211 #if defined(STM32F1XX) || defined(STM32F4XX) || defined(STM32F7XX)
213 CR1 |= SPI_CR1_LSBFIRST;
232 CR1 |= SPI_CR1_BR_1 | SPI_CR1_BR_0;
238 CR1 |= SPI_CR1_BR_2 | SPI_CR1_BR_0;
241 CR1 |= SPI_CR1_BR_2 | SPI_CR1_BR_1;
250 #if defined(STM32H7XX)
252 CR1 |= SPI_CFG1_DSIZE_VALUE(15);
254 CR1 |= SPI_CFG1_DSIZE_VALUE(7);
256 CR1 |= SPI_CFG1_MBR_VALUE(t->cdiv);
276 #if defined(STM32F7XX)
278 CR2 |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2 | SPI_CR2_DS_3;
280 CR2 |= SPI_CR2_DS_0 | SPI_CR2_DS_1 | SPI_CR2_DS_2;
283 #if defined(STM32H7XX)
285 CR2 |= SPI_CFG2_LSBFRST;
288 CR2 |= SPI_CFG2_CPHA;
291 CR2 |= SPI_CFG2_CPOL;
309 if ((
p->trans_insert_idx ==
p->trans_extract_idx) ||
p->suspend) {
320 SPIConfig spi_cfg = {
322 #if defined(HAL_LLD_SELECT_SPI_V2)
334 static size_t t_length;
342 spiStart((SPIDriver *)
p->reg_addr, &spi_cfg);
345 spiSelect((SPIDriver *)
p->reg_addr);
355 #if defined(STM32F7XX) || defined(STM32H7XX)
359 spiExchange((SPIDriver *)
p->reg_addr, t_length, i->dma_buf_out, i->dma_buf_in);
368 spiUnselect((SPIDriver *)
p->reg_addr);
373 p->trans_extract_idx++;
375 p->trans_extract_idx = 0;
399 static __attribute__((noreturn))
void thd_spi(
void *arg)
403 chRegSetThreadName(init_s->
name);
418 .sem = __SEMAPHORE_DATA(spi1_init_s.sem, 0),
425 spi1.reg_addr = &SPID1;
426 spi1.init_struct = &spi1_init_s;
428 chThdCreateStatic(wa_thd_spi1,
sizeof(wa_thd_spi1),
437 .sem = __SEMAPHORE_DATA(spi2_init_s.sem, 0),
444 spi2.reg_addr = &SPID2;
445 spi2.init_struct = &spi2_init_s;
447 chThdCreateStatic(wa_thd_spi2,
sizeof(wa_thd_spi2),
456 .sem = __SEMAPHORE_DATA(spi3_init_s.sem, 0),
461 void spi3_arch_init(
void)
463 spi3.reg_addr = &SPID3;
464 spi3.init_struct = &spi3_init_s;
466 chThdCreateStatic(wa_thd_spi3,
sizeof(wa_thd_spi3),
467 NORMALPRIO + 1,
thd_spi, (
void *)&spi3);
475 .sem = __SEMAPHORE_DATA(spi4_init_s.sem, 0),
480 void spi4_arch_init(
void)
482 spi4.reg_addr = &SPID4;
483 spi4.init_struct = &spi4_init_s;
485 chThdCreateStatic(wa_thd_spi4,
sizeof(wa_thd_spi4),
486 NORMALPRIO + 1,
thd_spi, (
void *)&spi4);
514 idx =
p->trans_insert_idx + 1;
526 p->trans[
p->trans_insert_idx] = t;
527 p->trans_insert_idx =
idx;
530 chSemSignal(&((
struct spi_init *)
p->init_struct)->sem);
576 gpio_clear(SPI_SELECT_SLAVE6_PORT, SPI_SELECT_SLAVE6_PIN);
581 gpio_clear(SPI_SELECT_SLAVE7_PORT, SPI_SELECT_SLAVE7_PIN);
586 gpio_clear(SPI_SELECT_SLAVE8_PORT, SPI_SELECT_SLAVE8_PIN);
633 gpio_set(SPI_SELECT_SLAVE6_PORT, SPI_SELECT_SLAVE6_PIN);
638 gpio_set(SPI_SELECT_SLAVE7_PORT, SPI_SELECT_SLAVE7_PIN);
643 gpio_set(SPI_SELECT_SLAVE8_PORT, SPI_SELECT_SLAVE8_PIN);
658 if (slave < 254 && p->suspend == 0) {
659 p->suspend = slave + 1;
672 if (
p->suspend == slave + 1) {
#define SPI_SELECT_SLAVE3_PIN
#define SPI_SELECT_SLAVE0_PORT
#define SPI_SELECT_SLAVE1_PIN
#define SPI_SELECT_SLAVE4_PORT
#define SPI_SELECT_SLAVE0_PIN
#define SPI_SELECT_SLAVE4_PIN
#define SPI_SELECT_SLAVE3_PORT
#define SPI_SELECT_SLAVE1_PORT
#define SPI_SELECT_SLAVE2_PORT
#define SPI_SELECT_SLAVE2_PIN
void gpio_setup_output(ioportid_t port, uint16_t gpios)
Setup one or more pins of the given GPIO port as outputs.
static void gpio_set(ioportid_t port, uint16_t pin)
Set a gpio output to high level.
static void gpio_clear(ioportid_t port, uint16_t pin)
Clear a gpio output to low level.
#define SPI_THREAD_STACK_SIZE
static void thd_spi(void *arg)
Default spi thread.
static uint32_t spi_resolve_CR1(struct spi_transaction *t)
Resolve CR1 (or CFG1)
static void handle_spi_thd(struct spi_periph *p)
main thread function
static THD_WORKING_AREA(wa_thd_spi1, SPI_THREAD_STACK_SIZE)
static uint32_t spi_resolve_CR2(struct spi_transaction *t)
Resolve CR2 (or CFG2)
static ioportid_t spi_resolve_slave_port(uint8_t slave)
Resolve slave port.
static uint16_t spi_resolve_slave_pin(uint8_t slave)
Resolve slave pin.
static IN_DMA_SECTION(struct spi_init spi1_init_s)
Configure SPI peripherals.
#define SPI_SELECT_SLAVE5_PIN
#define SPI_SELECT_SLAVE5_PORT
Some architecture independent helper functions for GPIOs.
enum SPISlaveSelect select
slave selection behavior
SPICallback before_cb
NULL or function called before the transaction.
SPICallback after_cb
NULL or function called after the transaction.
volatile uint8_t * output_buf
pointer to transmit buffer for DMA
uint16_t input_length
number of data words to read
volatile uint8_t * input_buf
pointer to receive buffer for DMA
uint8_t slave_idx
slave id: SPI_SLAVE0 to SPI_SLAVE4
uint16_t output_length
number of data words to write
enum SPITransactionStatus status
bool spi_submit(struct spi_periph *p, struct spi_transaction *t)
Submit SPI transaction.
bool spi_lock(struct spi_periph *p, uint8_t slave)
spi_lock() function
#define SPI_TRANSACTION_QUEUE_LEN
SPI transaction queue length.
void spi_slave_unselect(uint8_t slave)
spi_slave_unselect() function
void spi1_arch_init(void)
Architecture dependent SPI1 initialization.
process_rx_dma_interrupt & spi2
receive transferred over DMA
void spi_slave_select(uint8_t slave)
spi_slave_select() function
void spi2_arch_init(void)
Architecture dependent SPI2 initialization.
process_rx_dma_interrupt & spi1
receive transferred over DMA
bool spi_resume(struct spi_periph *p, uint8_t slave)
spi_resume() function
void spi_init_slaves(void)
spi_init_slaves() function
@ SPICpolIdleHigh
CPOL = 1.
@ SPISelect
slave is selected before transaction but not unselected
@ SPISelectUnselect
slave is selected before transaction and unselected after
@ SPIUnselect
slave is not selected but unselected after transaction
SPI peripheral structure.
SPI transaction structure.
Specific RAM section for DMA usage on F7.
Architecture independent SPI (Serial Peripheral Interface) API.
unsigned short uint16_t
Typedef defining 16 bit unsigned short type.
unsigned int uint32_t
Typedef defining 32 bit unsigned int type.
unsigned char uint8_t
Typedef defining 8 bit unsigned char type.