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);
492 #if defined(STM32H7XX)
500 .sem = __SEMAPHORE_DATA(spi6_init_s.sem, 0),
505 void spi6_arch_init(
void)
507 spi6.reg_addr = &SPID6;
508 spi6.init_struct = &spi6_init_s;
510 chThdCreateStatic(wa_thd_spi6,
sizeof(wa_thd_spi6),
511 NORMALPRIO + 1,
thd_spi, (
void *)&spi6);
539 idx =
p->trans_insert_idx + 1;
551 p->trans[
p->trans_insert_idx] = t;
552 p->trans_insert_idx =
idx;
555 chSemSignal(&((
struct spi_init *)
p->init_struct)->sem);
601 gpio_clear(SPI_SELECT_SLAVE6_PORT, SPI_SELECT_SLAVE6_PIN);
606 gpio_clear(SPI_SELECT_SLAVE7_PORT, SPI_SELECT_SLAVE7_PIN);
611 gpio_clear(SPI_SELECT_SLAVE8_PORT, SPI_SELECT_SLAVE8_PIN);
658 gpio_set(SPI_SELECT_SLAVE6_PORT, SPI_SELECT_SLAVE6_PIN);
663 gpio_set(SPI_SELECT_SLAVE7_PORT, SPI_SELECT_SLAVE7_PIN);
668 gpio_set(SPI_SELECT_SLAVE8_PORT, SPI_SELECT_SLAVE8_PIN);
683 if (slave < 254 && p->suspend == 0) {
684 p->suspend = slave + 1;
697 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.
#define IN_BDMA_SECTION(var)
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.