24#include "px_stm32cube.h"
31typedef struct px_spi_per_s
56static void px_spi_init_per(SPI_TypeDef * spi_base_adr,
66 LL_APB2_GRP1_EnableClock(LL_APB2_GRP1_PERIPH_SPI1);
67 LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
69 LL_DMA_SetPeriphAddress(DMA1, 2, (uint32_t)&SPI1->DR);
70 DMA1_Channel2->CCR = DMA_CCR_MINC;
71#if defined(STM32L0) || defined(STM32G0)
72 LL_DMA_SetPeriphRequest(DMA1, 2, LL_DMA_REQUEST_1);
75 LL_DMA_SetPeriphAddress(DMA1, 3, (uint32_t)&SPI1->DR);
76 DMA1_Channel3->CCR = DMA_CCR_MINC | DMA_CCR_DIR;
77#if defined(STM32L0) || defined(STM32G0)
78 LL_DMA_SetPeriphRequest(DMA1, 3, LL_DMA_REQUEST_1);
85 LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_SPI2);
86 LL_AHB1_GRP1_EnableClock(LL_AHB1_GRP1_PERIPH_DMA1);
88 LL_DMA_SetPeriphAddress(DMA1, 4, (uint32_t)&SPI2->DR);
89 DMA1_Channel4->CCR = DMA_CCR_MINC;
90#if defined(STM32L0) || defined(STM32G0)
91 LL_DMA_SetPeriphRequest(DMA1, 4, LL_DMA_REQUEST_2);
94 LL_DMA_SetPeriphAddress(DMA1, 5, (uint32_t)&SPI2->DR);
95 DMA1_Channel5->CCR = DMA_CCR_MINC | DMA_CCR_DIR;
96#if defined(STM32L0) || defined(STM32G0)
97 LL_DMA_SetPeriphRequest(DMA1, 5, LL_DMA_REQUEST_2);
107 LL_SPI_Disable(spi_base_adr);
111 spi_base_adr->CR1 = spi_cr1_val;
114 LL_SPI_Enable(spi_base_adr);
117static void px_spi_update_cfg(SPI_TypeDef * spi_base_adr, uint32_t spi_cr1_val)
120 if((spi_base_adr->CR1 & (~SPI_CR1_SPE_Msk)) != spi_cr1_val)
123 LL_SPI_Disable(spi_base_adr);
125 spi_base_adr->CR1 = spi_cr1_val;
127 LL_SPI_Enable(spi_base_adr);
131static void px_spi_init_per_data(
px_spi_nr_t spi_nr,
139#if PX_SPI_CFG_SPI1_EN
146#if PX_SPI_CFG_SPI2_EN
165#if PX_SPI_CFG_SPI1_EN
166 px_spi_init_per_data(PX_SPI_NR_1, &px_spi_per_1);
168#if PX_SPI_CFG_SPI2_EN
169 px_spi_init_per_data(PX_SPI_NR_2, &px_spi_per_2);
178 uint32_t spi_cr1_val = 0;
198#if PX_SPI_CFG_SPI1_EN
200 spi_per = &px_spi_per_1;
203#if PX_SPI_CFG_SPI2_EN
205 spi_per = &px_spi_per_2;
209 PX_LOG_E(
"Invalid peripheral specified");
228 spi_cr1_val |= SPI_CR1_MSTR;
230 spi_cr1_val |= SPI_CR1_SSM | SPI_CR1_SSI;
234 handle->
cs_id = cs_id;
241 px_spi_init_per(spi_per->
spi_base_adr, spi_nr, spi_cr1_val);
258 uint8_t mo_dummy_byte)
261 uint32_t spi_cr1_val = 0;
281#if PX_SPI_CFG_SPI1_EN
283 spi_per = &px_spi_per_1;
286#if PX_SPI_CFG_SPI2_EN
288 spi_per = &px_spi_per_2;
292 PX_LOG_E(
"Invalid peripheral specified");
307 spi_cr1_val |= SPI_CR1_LSBFIRST;
310 spi_cr1_val |= baud << SPI_CR1_BR_Pos;
312 spi_cr1_val |= mode << SPI_CR1_CPHA_Pos;
314 spi_cr1_val |= SPI_CR1_MSTR;
316 spi_cr1_val |= SPI_CR1_SSM | SPI_CR1_SSI;
320 handle->
cs_id = cs_id;
327 px_spi_init_per(spi_per->
spi_base_adr, spi_nr, spi_cr1_val);
341 SPI_TypeDef * spi_base_adr;
348 ||(handle->
spi_per->open_counter == 0 ) )
372 LL_SPI_Disable(spi_base_adr);
376#if PX_SPI_CFG_SPI1_EN
378 LL_APB2_GRP1_DisableClock(LL_APB2_GRP1_PERIPH_SPI1);
381#if PX_SPI_CFG_SPI2_EN
383 LL_APB1_GRP1_DisableClock(LL_APB1_GRP1_PERIPH_SPI2);
402 SPI_TypeDef * spi_base_adr;
403 const uint8_t * data_wr_u8 = (
const uint8_t *)data;
410 ||(handle->
spi_per->open_counter == 0 ) )
434 px_spi_update_cfg(spi_base_adr, handle->
spi_cr1_val);
440 LL_SPI_EnableDMAReq_TX(spi_base_adr);
444 #if PX_SPI_CFG_SPI1_EN
446 while(!LL_DMA_IsActiveFlag_TC3(DMA1)) {;}
447 LL_DMA_ClearFlag_TC3(DMA1);
450 #if PX_SPI_CFG_SPI2_EN
452 while(!LL_DMA_IsActiveFlag_TC5(DMA1)) {;}
453 LL_DMA_ClearFlag_TC5(DMA1);
461 while(!LL_SPI_IsActiveFlag_TXE(spi_base_adr)) {;}
462 while(LL_SPI_IsActiveFlag_BSY(spi_base_adr)) {;}
464 LL_SPI_ClearFlag_OVR(spi_base_adr);
468 spi_base_adr->CR2 = 0;
485 SPI_TypeDef * spi_base_adr;
486 uint8_t * data_rd_u8 = (uint8_t *)data;
493 ||(handle->
spi_per->open_counter == 0 ) )
517 px_spi_update_cfg(spi_base_adr, handle->
spi_cr1_val);
519 LL_SPI_EnableDMAReq_RX(spi_base_adr);
530 LL_SPI_EnableDMAReq_TX(spi_base_adr);
534 #if PX_SPI_CFG_SPI1_EN
536 while(!LL_DMA_IsActiveFlag_TC2(DMA1)) {;}
537 LL_DMA_ClearFlag_TC2(DMA1);
540 #if PX_SPI_CFG_SPI2_EN
542 while(!LL_DMA_IsActiveFlag_TC4(DMA1)) {;}
543 LL_DMA_ClearFlag_TC4(DMA1);
557 spi_base_adr->CR2 = 0;
569 const void * data_wr,
575 SPI_TypeDef * spi_base_adr;
576 const uint8_t * data_wr_u8 = (
const uint8_t *)data_wr;
577 uint8_t * data_rd_u8 = (uint8_t *)data_rd;
584 ||(handle->
spi_per->open_counter == 0 ) )
605 px_spi_update_cfg(spi_base_adr, handle->
spi_cr1_val);
611 LL_SPI_EnableDMAReq_RX(spi_base_adr);
621 LL_SPI_EnableDMAReq_TX(spi_base_adr);
625 #if PX_SPI_CFG_SPI1_EN
627 while(!LL_DMA_IsActiveFlag_TC2(DMA1)) {;}
628 LL_DMA_ClearFlag_TC2(DMA1);
631 #if PX_SPI_CFG_SPI2_EN
633 while(!LL_DMA_IsActiveFlag_TC4(DMA1)) {;}
634 LL_DMA_ClearFlag_TC4(DMA1);
646 spi_base_adr->CR2 = 0;
661 SPI_TypeDef * spi_base_adr;
662 uint32_t spi_cr1_val;
669 ||(handle->
spi_per->open_counter == 0 ) )
683 LL_SPI_Disable(spi_base_adr);
687 spi_cr1_val &= ~SPI_CR1_BR_Msk;
688 spi_cr1_val |= baud << SPI_CR1_BR_Pos;
692 spi_base_adr->CR1 = spi_cr1_val;
695 LL_SPI_Enable(spi_base_adr);
700 uint32_t actual_baud_hz;
707 while(actual_baud_hz > baud_hz)
710 actual_baud_hz >>= 1;
@ PX_SPI_DATA_ORDER_LSB
Data order is Least Significant Bit first (D0, D1, ..., D7)
@ PX_SPI_BAUD_CLK_DIV_256
F_PCLK / 256.
@ PX_SPI_BAUD_CLK_DIV_2
F_PCLK / 2.
#define PX_BOARD_PER_CLK_HZ
Peripheral clock frequency in Hz.
#define NULL
NULL pointer.
#define PX_LOG_NAME(name)
Macro to declare a log name string once for each file to reduce code size.
#define PX_LOG_W(format,...)
Macro to display a formatted WARNING message.
#define PX_LOG_E(format,...)
Macro to display a formatted ERROR message.
#define PX_LOG_ASSERT(expression)
Macro that will test an expression, and block indefinitely if false.
uint8_t cs_id
Chip Select GPIO ID.
uint8_t mo_dummy_byte
Master Out dummy byte when data is read from Master In.
uint32_t spi_cr1_val
SPI Control Register 1 value (SPI_CR1)
struct px_spi_per_s * spi_per
SPI peripheral.
bool px_spi_close(px_spi_handle_t *handle)
Close specified device.
#define PX_SPI_CFG_CS_HI(cs_id)
Map PX_SPI_CFG_CS_HI() macro to px_board_spi_cs_hi() function.
px_spi_mode_t
Specify SPI Clock polarity / Clock phase.
void px_spi_init(void)
Initialise SPI driver.
bool px_spi_open2(px_spi_handle_t *handle, px_spi_nr_t spi_nr, uint8_t cs_id, px_spi_baud_t baud, px_spi_mode_t mode, px_spi_dord_t data_order, uint8_t mo_dummy_byte)
Open SPI peripheral using specified parameters.
#define PX_SPI_CFG_DEFAULT_DATA_ORDER
Specify default SPI data order.
#define PX_SPI_CFG_DEFAULT_MODE
Specify default SPI mode (clock phase and polarity)
#define PX_SPI_CFG_CS_LO(cs_id)
Map PX_SPI_CFG_CS_LO() macro to px_board_spi_cs_lo() function.
px_spi_dord_t
Specify SPI Data order.
#define PX_SPI_FLAG_START
Begin SPI transaction (take SPI slave's Chip Select line low)
void px_spi_xc(px_spi_handle_t *handle, const void *data_wr, void *data_rd, size_t nr_of_bytes, uint8_t flags)
Perform an SPI exchange (write and read) transaction with an SPI slave.
void px_spi_wr(px_spi_handle_t *handle, const void *data, size_t nr_of_bytes, uint8_t flags)
Perform an SPI write transaction with an SPI slave.
void px_spi_rd(px_spi_handle_t *handle, void *data, size_t nr_of_bytes, uint8_t flags)
Perform an SPI read transaction with an SPI slave.
px_spi_nr_t
Specify SPI peripheral number.
void px_spi_change_baud(px_spi_handle_t *handle, px_spi_baud_t baud)
Change SPI peripheral baud.
uint32_t px_spi_util_clk_div_to_baud_hz(px_spi_baud_t baud)
Calculate the actual BAUD (in Hz) from the specified division.
#define PX_SPI_CFG_DEFAULT_BAUD
Specify default baud rate.
bool px_spi_open(px_spi_handle_t *handle, px_spi_nr_t spi_nr, uint8_t cs_id)
Open SPI peripheral using predefined (default) parameters.
#define PX_SPI_FLAG_STOP
Finish SPI transaction (take SPI slave's Chip Select line high)
px_spi_baud_t
Specify SPI baud rate as a ratio of the peripheral clock.
px_spi_baud_t px_spi_util_baud_hz_to_clk_div(uint32_t baud_hz)
Calculate clock divisor that will yield closest frequency equal to or less than specified baud rate (...
Internal data for each SPI peripheral.
DMA_Channel_TypeDef * dma_rx_base_adr
DMA RX channel base register address.
uint8_t open_counter
Number of open handles referencing peripheral.
SPI_TypeDef * spi_base_adr
SPI peripheral base register address.
DMA_Channel_TypeDef * dma_tx_base_adr
DMA TX channel base register address.
px_spi_nr_t spi_nr
Peripheral number.