1#include "stm32_spi.hpp"
3#include "libxr_def.hpp"
5#ifdef HAL_SPI_MODULE_ENABLED
9STM32SPI* STM32SPI::map[STM32_SPI_NUMBER] = {
nullptr};
11stm32_spi_id_t STM32_SPI_GetID(SPI_TypeDef* addr)
15 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
18 else if (addr == SPI1)
20 return stm32_spi_id_t::STM32_SPI1;
24 else if (addr == SPI2)
26 return stm32_spi_id_t::STM32_SPI2;
30 else if (addr == SPI3)
32 return stm32_spi_id_t::STM32_SPI3;
36 else if (addr == SPI4)
38 return stm32_spi_id_t::STM32_SPI4;
42 else if (addr == SPI5)
44 return stm32_spi_id_t::STM32_SPI5;
48 else if (addr == SPI6)
50 return stm32_spi_id_t::STM32_SPI6;
54 else if (addr == SPI7)
56 return stm32_spi_id_t::STM32_SPI7;
60 else if (addr == SPI8)
62 return stm32_spi_id_t::STM32_SPI8;
67 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
72 uint32_t dma_enable_min_size)
74 spi_handle_(spi_handle),
75 id_(STM32_SPI_GetID(spi_handle_->Instance)),
76 dma_enable_min_size_(dma_enable_min_size)
78 ASSERT(id_ != STM32_SPI_ID_ERROR);
93 ASSERT(need_write <= rx.
size_);
97 ASSERT(need_write <= tx.
size_);
100 if (spi_handle_->State != HAL_SPI_STATE_READY)
102 return ErrorCode::BUSY;
107 if (need_write > dma_enable_min_size_)
111 HAL_StatusTypeDef st = HAL_OK;
113 if (write_data.
size_ > 0 && read_data.
size_ > 0)
116 if (write_data.
size_ < need_write)
119 need_write - write_data.
size_);
121#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
122 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
123 static_cast<int32_t
>(need_write));
125 read_buff_ = read_data;
127 st = HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
128 static_cast<uint8_t*
>(rx.
addr_), need_write);
130 else if (write_data.
size_ > 0)
133 if (write_data.
size_ < need_write)
136 need_write - write_data.
size_);
138#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
139 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
140 static_cast<int32_t
>(need_write));
142 read_buff_ = {
nullptr, 0};
144 st = HAL_SPI_Transmit_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_), need_write);
146 else if (read_data.
size_ > 0)
148 read_buff_ = read_data;
150 st = HAL_SPI_Receive_DMA(spi_handle_,
static_cast<uint8_t*
>(rx.
addr_),
155 if (op.
type != OperationRW::OperationType::BLOCK)
159 return ErrorCode::OK;
164 return ErrorCode::BUSY;
168 if (op.
type == OperationRW::OperationType::BLOCK)
170 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
172 return ErrorCode::OK;
175 ErrorCode ans = ErrorCode::OK;
177 if (write_data.
size_ > 0 && read_data.
size_ > 0)
180 if (write_data.
size_ < need_write)
183 need_write - write_data.
size_);
185#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
186 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
187 static_cast<int32_t
>(need_write));
189 ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
190 static_cast<uint8_t*
>(rx.
addr_), need_write,
195 if (ans == ErrorCode::OK)
201 else if (read_data.
size_ > 0)
203 ans = (HAL_SPI_Receive(spi_handle_,
static_cast<uint8_t*
>(rx.
addr_), read_data.
size_,
208 if (ans == ErrorCode::OK)
214 else if (write_data.
size_ > 0)
217#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
218 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
219 static_cast<int32_t
>(need_write));
221 ans = (HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
222 write_data.
size_, 20) == HAL_OK)
230 if (op.
type != OperationRW::OperationType::BLOCK)
234 return ErrorCode::OK;
237 if (op.
type != OperationRW::OperationType::BLOCK)
249 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
252 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
259 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
262 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
267 uint32_t hal_presc = 0;
271#ifdef SPI_BAUDRATEPRESCALER_1
273 hal_presc = SPI_BAUDRATEPRESCALER_1;
276#ifdef SPI_BAUDRATEPRESCALER_2
278 hal_presc = SPI_BAUDRATEPRESCALER_2;
281#ifdef SPI_BAUDRATEPRESCALER_4
283 hal_presc = SPI_BAUDRATEPRESCALER_4;
286#ifdef SPI_BAUDRATEPRESCALER_8
288 hal_presc = SPI_BAUDRATEPRESCALER_8;
291#ifdef SPI_BAUDRATEPRESCALER_16
293 hal_presc = SPI_BAUDRATEPRESCALER_16;
296#ifdef SPI_BAUDRATEPRESCALER_32
298 hal_presc = SPI_BAUDRATEPRESCALER_32;
301#ifdef SPI_BAUDRATEPRESCALER_64
303 hal_presc = SPI_BAUDRATEPRESCALER_64;
306#ifdef SPI_BAUDRATEPRESCALER_128
308 hal_presc = SPI_BAUDRATEPRESCALER_128;
311#ifdef SPI_BAUDRATEPRESCALER_256
313 hal_presc = SPI_BAUDRATEPRESCALER_256;
316#ifdef SPI_BAUDRATEPRESCALER_512
318 hal_presc = SPI_BAUDRATEPRESCALER_512;
321#ifdef SPI_BAUDRATEPRESCALER_1024
323 hal_presc = SPI_BAUDRATEPRESCALER_1024;
334 return ErrorCode::NOT_SUPPORT;
337 spi_handle_->Init.BaudRatePrescaler = hal_presc;
341 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
346 uint32_t need_read = read_data.
size_;
348 if (spi_handle_->State != HAL_SPI_STATE_READY)
350 return ErrorCode::BUSY;
356 ASSERT(rx.
size_ >= need_read + 1);
357 ASSERT(tx.
size_ >= need_read + 1);
359 if (need_read + 1 > dma_enable_min_size_)
364 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
366 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
367#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
368 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
369 static_cast<int32_t
>(need_read + 1));
371 read_buff_ = read_data;
373 HAL_StatusTypeDef st =
374 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
375 static_cast<uint8_t*
>(rx.
addr_), need_read + 1);
379 return ErrorCode::BUSY;
383 if (op.
type == OperationRW::OperationType::BLOCK)
385 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
387 return ErrorCode::OK;
391 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
393 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
394#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
395 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
396 static_cast<int32_t
>(need_read + 1));
399 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
400 static_cast<uint8_t*
>(rx.
addr_), need_read + 1,
405 if (ans == ErrorCode::OK)
407 uint8_t* rxb =
reinterpret_cast<uint8_t*
>(rx.
addr_);
412 if (op.
type != OperationRW::OperationType::BLOCK)
422 uint32_t need_write = write_data.
size_;
424 if (spi_handle_->State != HAL_SPI_STATE_READY)
426 return ErrorCode::BUSY;
430 ASSERT(tx.
size_ >= need_write + 1);
432 if (need_write + 1 > dma_enable_min_size_)
437 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
438 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
440#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
441 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
442 static_cast<int32_t
>(need_write + 1));
444 read_buff_ = {
nullptr, 0};
446 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
447 spi_handle_,
static_cast<uint8_t*
>(tx.
addr_), need_write + 1);
451 return ErrorCode::BUSY;
455 if (op.
type == OperationRW::OperationType::BLOCK)
457 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
459 return ErrorCode::OK;
462 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
463 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
465#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
466 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
467 static_cast<int32_t
>(need_write + 1));
470 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
471 need_write + 1, 20) == HAL_OK)
477 if (op.
type != OperationRW::OperationType::BLOCK)
486 SPI_TypeDef* inst = spi_handle_ ? spi_handle_->Instance :
nullptr;
492#if defined(HAL_RCC_MODULE_ENABLED)
496#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
497 defined(RCC_PERIPHCLK_SPI6)
511#ifdef RCC_PERIPHCLK_SPI123
512 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
525#ifdef RCC_PERIPHCLK_SPI45
526 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
533#ifdef RCC_PERIPHCLK_SPI6
534 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
541#if defined(RCC_PERIPHCLK_SPI1)
543 if (inst == SPI1)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
546#if defined(RCC_PERIPHCLK_SPI2)
548 if (inst == SPI2)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
551#if defined(RCC_PERIPHCLK_SPI3)
553 if (inst == SPI3)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
556#if defined(RCC_PERIPHCLK_SPI4)
558 if (inst == SPI4)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
561#if defined(RCC_PERIPHCLK_SPI5)
563 if (inst == SPI5)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
566#if defined(RCC_PERIPHCLK_SPI6)
568 if (inst == SPI6)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
575#if defined(STM32H7) && defined(SPI6)
578#if defined(HAL_RCC_GetPCLK4Freq)
579 return HAL_RCC_GetPCLK4Freq();
581 return HAL_RCC_GetHCLKFreq();
608#if defined(HAL_RCC_GetPCLK2Freq)
609 return HAL_RCC_GetPCLK2Freq();
610#elif defined(HAL_RCC_GetPCLK1Freq)
611 return HAL_RCC_GetPCLK1Freq();
613 return HAL_RCC_GetHCLKFreq();
618#if defined(HAL_RCC_GetPCLK1Freq)
619 return HAL_RCC_GetPCLK1Freq();
620#elif defined(HAL_RCC_GetPCLK2Freq)
621 return HAL_RCC_GetPCLK2Freq();
623 return HAL_RCC_GetHCLKFreq();
630#if defined(SPI_BAUDRATEPRESCALER_1024)
632#elif defined(SPI_BAUDRATEPRESCALER_512)
634#elif defined(SPI_BAUDRATEPRESCALER_256)
636#elif defined(SPI_BAUDRATEPRESCALER_128)
638#elif defined(SPI_BAUDRATEPRESCALER_64)
640#elif defined(SPI_BAUDRATEPRESCALER_32)
642#elif defined(SPI_BAUDRATEPRESCALER_16)
644#elif defined(SPI_BAUDRATEPRESCALER_8)
646#elif defined(SPI_BAUDRATEPRESCALER_4)
648#elif defined(SPI_BAUDRATEPRESCALER_2)
650#elif defined(SPI_BAUDRATEPRESCALER_1)
659 if (spi_handle_->State != HAL_SPI_STATE_READY)
661 return ErrorCode::BUSY;
666 if (op.
type != OperationRW::OperationType::BLOCK)
670 return ErrorCode::OK;
676 const uint16_t xfer =
static_cast<uint16_t
>(size);
678 if (size > dma_enable_min_size_)
682#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
683 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
static_cast<int32_t
>(xfer));
684 SCB_InvalidateDCache_by_Addr(
static_cast<uint32_t*
>(rx.
addr_),
685 static_cast<int32_t
>(xfer));
688 HAL_StatusTypeDef st =
689 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
690 static_cast<uint8_t*
>(rx.
addr_), xfer);
694 return ErrorCode::BUSY;
698 if (op.
type == OperationRW::OperationType::BLOCK)
700 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
702 return ErrorCode::OK;
706 (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
707 static_cast<uint8_t*
>(rx.
addr_), xfer, 20) == HAL_OK)
711#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
712 SCB_InvalidateDCache_by_Addr(
static_cast<uint32_t*
>(rx.
addr_),
713 static_cast<int32_t
>(xfer));
718 if (op.
type != OperationRW::OperationType::BLOCK)
725extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
727 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
732extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
734 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
738 if (spi->read_buff_.
size_ > 0)
742#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
743 SCB_InvalidateDCache_by_Addr(rx.
addr_, spi->read_buff_.
size_);
749#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
750 SCB_InvalidateDCache_by_Addr(rx.
addr_, spi->read_buff_.
size_ + 1);
752 uint8_t* rx_dma_buff =
reinterpret_cast<uint8_t*
>(rx.
addr_);
755 spi->read_buff_.
size_ = 0;
762extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
764 HAL_SPI_RxCpltCallback(hspi);
767extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
769 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
static void FastSet(void *dst, uint8_t value, size_t size)
快速内存填充 / Fast memory fill
static void FastCopy(void *dst, const void *src, size_t size)
快速内存拷贝 / Fast memory copy
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
串行外设接口(SPI)抽象类。Abstract class for Serial Peripheral Interface (SPI).
@ EDGE_2
在第二个时钟边沿采样数据。Data sampled on the second clock edge.
@ EDGE_1
在第一个时钟边沿采样数据。Data sampled on the first clock edge.
@ DIV_16
分频系数为 16。Division factor is 16.
@ DIV_2
分频系数为 2。Division factor is 2.
@ DIV_64
分频系数为 64。Division factor is 64.
@ DIV_1
分频系数为 1。Division factor is 1.
@ UNKNOWN
未知分频系数。Unknown prescaler.
@ DIV_256
分频系数为 256。Division factor is 256.
@ DIV_128
分频系数为 128。Division factor is 128.
@ DIV_4
分频系数为 4。Division factor is 4.
@ DIV_32
分频系数为 32。Division factor is 32.
@ DIV_512
分频系数为 512。Division factor is 512.
@ DIV_8
分频系数为 8。Division factor is 8.
@ DIV_1024
分频系数为 1024。Division factor is 1024.
RawData GetRxBuffer()
获取接收数据的缓冲区。Gets the buffer for storing received data.
void SwitchBuffer()
切换缓冲区。Switches the buffer.
RawData GetTxBuffer()
获取发送数据的缓冲区。Gets the buffer for storing data to be sent.
@ LOW
时钟空闲时为低电平。Clock idle low.
@ HIGH
时钟空闲时为高电平。Clock idle high.
Configuration & GetConfig()
获取 SPI 配置参数。Gets the SPI configuration parameters.
STM32 SPI 驱动实现 / STM32 SPI driver implementation.
ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op, bool in_isr) override
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op, bool in_isr) override
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
STM32SPI(SPI_HandleTypeDef *spi_handle, RawData dma_buff_rx, RawData dma_buff_tx, uint32_t dma_enable_min_size=3)
构造 SPI 对象 / Construct SPI object
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
ErrorCode Transfer(size_t size, OperationRW &op, bool in_isr) override
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数。Sets SPI configuration parameters.
Prescaler GetMaxPrescaler() const override
获取 SPI 设备的最大分频系数。Gets the maximum prescaler of the SPI device.
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op, bool in_isr) override
进行 SPI 读写操作。Performs SPI read and write operations.
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
constexpr auto max(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最大值
存储 SPI 配置参数的结构体。Structure for storing SPI configuration parameters.
ClockPhase clock_phase
SPI 时钟相位。SPI clock phase.
Prescaler prescaler
SPI 分频系数。SPI prescaler.
ClockPolarity clock_polarity
SPI 时钟极性。SPI clock polarity.