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)
107 if (need_write > dma_enable_min_size_)
110 if (op.
type == OperationRW::OperationType::BLOCK)
112 block_wait_.Start(*op.
data.sem_info.sem);
115 HAL_StatusTypeDef st = HAL_OK;
117 if (write_data.
size_ > 0 && read_data.
size_ > 0)
120 if (write_data.
size_ < need_write)
123 need_write - write_data.
size_);
125#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
126 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
127 static_cast<int32_t
>(need_write));
129 read_buff_ = read_data;
131 st = HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
132 static_cast<uint8_t*
>(rx.
addr_), need_write);
134 else if (write_data.
size_ > 0)
137 if (write_data.
size_ < need_write)
140 need_write - write_data.
size_);
142#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
143 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
144 static_cast<int32_t
>(need_write));
146 read_buff_ = {
nullptr, 0};
148 st = HAL_SPI_Transmit_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_), need_write);
150 else if (read_data.
size_ > 0)
152 read_buff_ = read_data;
154 st = HAL_SPI_Receive_DMA(spi_handle_,
static_cast<uint8_t*
>(rx.
addr_),
159 if (op.
type != OperationRW::OperationType::BLOCK)
168 if (op.
type == OperationRW::OperationType::BLOCK)
170 block_wait_.Cancel();
176 if (op.
type == OperationRW::OperationType::BLOCK)
178 return block_wait_.Wait(op.
data.sem_info.timeout);
185 if (write_data.
size_ > 0 && read_data.
size_ > 0)
188 if (write_data.
size_ < need_write)
191 need_write - write_data.
size_);
193#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
194 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
195 static_cast<int32_t
>(need_write));
197 ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
198 static_cast<uint8_t*
>(rx.
addr_), need_write,
209 else if (read_data.
size_ > 0)
211 ans = (HAL_SPI_Receive(spi_handle_,
static_cast<uint8_t*
>(rx.
addr_), read_data.
size_,
222 else if (write_data.
size_ > 0)
225#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
226 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
227 static_cast<int32_t
>(need_write));
229 ans = (HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
230 write_data.
size_, 20) == HAL_OK)
238 if (op.
type != OperationRW::OperationType::BLOCK)
245 if (op.
type != OperationRW::OperationType::BLOCK)
257 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
260 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
267 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
270 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
275 uint32_t hal_presc = 0;
279#ifdef SPI_BAUDRATEPRESCALER_1
281 hal_presc = SPI_BAUDRATEPRESCALER_1;
284#ifdef SPI_BAUDRATEPRESCALER_2
286 hal_presc = SPI_BAUDRATEPRESCALER_2;
289#ifdef SPI_BAUDRATEPRESCALER_4
291 hal_presc = SPI_BAUDRATEPRESCALER_4;
294#ifdef SPI_BAUDRATEPRESCALER_8
296 hal_presc = SPI_BAUDRATEPRESCALER_8;
299#ifdef SPI_BAUDRATEPRESCALER_16
301 hal_presc = SPI_BAUDRATEPRESCALER_16;
304#ifdef SPI_BAUDRATEPRESCALER_32
306 hal_presc = SPI_BAUDRATEPRESCALER_32;
309#ifdef SPI_BAUDRATEPRESCALER_64
311 hal_presc = SPI_BAUDRATEPRESCALER_64;
314#ifdef SPI_BAUDRATEPRESCALER_128
316 hal_presc = SPI_BAUDRATEPRESCALER_128;
319#ifdef SPI_BAUDRATEPRESCALER_256
321 hal_presc = SPI_BAUDRATEPRESCALER_256;
324#ifdef SPI_BAUDRATEPRESCALER_512
326 hal_presc = SPI_BAUDRATEPRESCALER_512;
329#ifdef SPI_BAUDRATEPRESCALER_1024
331 hal_presc = SPI_BAUDRATEPRESCALER_1024;
345 spi_handle_->Init.BaudRatePrescaler = hal_presc;
354 uint32_t need_read = read_data.
size_;
356 if (spi_handle_->State != HAL_SPI_STATE_READY)
364 ASSERT(rx.
size_ >= need_read + 1);
365 ASSERT(tx.
size_ >= need_read + 1);
367 if (need_read + 1 > dma_enable_min_size_)
371 if (op.
type == OperationRW::OperationType::BLOCK)
373 block_wait_.Start(*op.
data.sem_info.sem);
376 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
378 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
379#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
380 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
381 static_cast<int32_t
>(need_read + 1));
383 read_buff_ = read_data;
385 HAL_StatusTypeDef st =
386 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
387 static_cast<uint8_t*
>(rx.
addr_), need_read + 1);
391 if (op.
type == OperationRW::OperationType::BLOCK)
393 block_wait_.Cancel();
399 if (op.
type == OperationRW::OperationType::BLOCK)
401 return block_wait_.Wait(op.
data.sem_info.timeout);
407 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
409 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
410#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
411 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
412 static_cast<int32_t
>(need_read + 1));
415 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
416 static_cast<uint8_t*
>(rx.
addr_), need_read + 1,
423 uint8_t* rxb =
reinterpret_cast<uint8_t*
>(rx.
addr_);
428 if (op.
type != OperationRW::OperationType::BLOCK)
438 uint32_t need_write = write_data.
size_;
440 if (spi_handle_->State != HAL_SPI_STATE_READY)
446 ASSERT(tx.
size_ >= need_write + 1);
448 if (need_write + 1 > dma_enable_min_size_)
452 if (op.
type == OperationRW::OperationType::BLOCK)
454 block_wait_.Start(*op.
data.sem_info.sem);
457 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
458 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
460#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
461 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
462 static_cast<int32_t
>(need_write + 1));
464 read_buff_ = {
nullptr, 0};
466 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
467 spi_handle_,
static_cast<uint8_t*
>(tx.
addr_), need_write + 1);
471 if (op.
type == OperationRW::OperationType::BLOCK)
473 block_wait_.Cancel();
479 if (op.
type == OperationRW::OperationType::BLOCK)
481 return block_wait_.Wait(op.
data.sem_info.timeout);
486 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
487 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
489#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
490 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
491 static_cast<int32_t
>(need_write + 1));
494 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
495 need_write + 1, 20) == HAL_OK)
501 if (op.
type != OperationRW::OperationType::BLOCK)
510 SPI_TypeDef* inst = spi_handle_ ? spi_handle_->Instance :
nullptr;
516#if defined(HAL_RCC_MODULE_ENABLED)
520#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
521 defined(RCC_PERIPHCLK_SPI6)
535#ifdef RCC_PERIPHCLK_SPI123
536 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
549#ifdef RCC_PERIPHCLK_SPI45
550 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
557#ifdef RCC_PERIPHCLK_SPI6
558 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
565#if defined(RCC_PERIPHCLK_SPI1)
567 if (inst == SPI1)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
570#if defined(RCC_PERIPHCLK_SPI2)
572 if (inst == SPI2)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
575#if defined(RCC_PERIPHCLK_SPI3)
577 if (inst == SPI3)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
580#if defined(RCC_PERIPHCLK_SPI4)
582 if (inst == SPI4)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
585#if defined(RCC_PERIPHCLK_SPI5)
587 if (inst == SPI5)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
590#if defined(RCC_PERIPHCLK_SPI6)
592 if (inst == SPI6)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
599#if defined(STM32H7) && defined(SPI6)
602#if defined(HAL_RCC_GetPCLK4Freq)
603 return HAL_RCC_GetPCLK4Freq();
605 return HAL_RCC_GetHCLKFreq();
632#if defined(HAL_RCC_GetPCLK2Freq)
633 return HAL_RCC_GetPCLK2Freq();
634#elif defined(HAL_RCC_GetPCLK1Freq)
635 return HAL_RCC_GetPCLK1Freq();
637 return HAL_RCC_GetHCLKFreq();
642#if defined(HAL_RCC_GetPCLK1Freq)
643 return HAL_RCC_GetPCLK1Freq();
644#elif defined(HAL_RCC_GetPCLK2Freq)
645 return HAL_RCC_GetPCLK2Freq();
647 return HAL_RCC_GetHCLKFreq();
654#if defined(SPI_BAUDRATEPRESCALER_1024)
656#elif defined(SPI_BAUDRATEPRESCALER_512)
658#elif defined(SPI_BAUDRATEPRESCALER_256)
660#elif defined(SPI_BAUDRATEPRESCALER_128)
662#elif defined(SPI_BAUDRATEPRESCALER_64)
664#elif defined(SPI_BAUDRATEPRESCALER_32)
666#elif defined(SPI_BAUDRATEPRESCALER_16)
668#elif defined(SPI_BAUDRATEPRESCALER_8)
670#elif defined(SPI_BAUDRATEPRESCALER_4)
672#elif defined(SPI_BAUDRATEPRESCALER_2)
674#elif defined(SPI_BAUDRATEPRESCALER_1)
683 if (spi_handle_->State != HAL_SPI_STATE_READY)
690 if (op.
type != OperationRW::OperationType::BLOCK)
700 const uint16_t xfer =
static_cast<uint16_t
>(size);
702 if (size > dma_enable_min_size_)
705 if (op.
type == OperationRW::OperationType::BLOCK)
707 block_wait_.Start(*op.
data.sem_info.sem);
710#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
711 SCB_CleanDCache_by_Addr(
static_cast<uint32_t*
>(tx.
addr_),
static_cast<int32_t
>(xfer));
712 SCB_InvalidateDCache_by_Addr(
static_cast<uint32_t*
>(rx.
addr_),
713 static_cast<int32_t
>(xfer));
716 HAL_StatusTypeDef st =
717 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
718 static_cast<uint8_t*
>(rx.
addr_), xfer);
722 if (op.
type == OperationRW::OperationType::BLOCK)
724 block_wait_.Cancel();
730 if (op.
type == OperationRW::OperationType::BLOCK)
732 return block_wait_.Wait(op.
data.sem_info.timeout);
738 (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
739 static_cast<uint8_t*
>(rx.
addr_), xfer, 20) == HAL_OK)
743#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
744 SCB_InvalidateDCache_by_Addr(
static_cast<uint32_t*
>(rx.
addr_),
745 static_cast<int32_t
>(xfer));
750 if (op.
type != OperationRW::OperationType::BLOCK)
757extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
759 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
760 ASSERT(spi !=
nullptr);
761 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
766 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
776extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
778 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
779 ASSERT(spi !=
nullptr);
780 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
786 const bool has_user_read_copy = (spi->read_buff_.
size_ > 0);
788 if (has_user_read_copy)
792#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
793 SCB_InvalidateDCache_by_Addr(rx.
addr_, spi->read_buff_.
size_);
799#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
800 SCB_InvalidateDCache_by_Addr(rx.
addr_, spi->read_buff_.
size_ + 1);
802 uint8_t* rx_dma_buff =
reinterpret_cast<uint8_t*
>(rx.
addr_);
805 spi->read_buff_.
size_ = 0;
809 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
819extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
821 HAL_SPI_RxCpltCallback(hspi);
824extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
826 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
827 ASSERT(spi !=
nullptr);
828 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
832 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
常量原始数据封装类。 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.
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
constexpr auto max(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最大值
存储 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.