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;
71STM32SPI::STM32SPI(SPI_HandleTypeDef *spi_handle,
RawData rx,
RawData tx,
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)
118 memset(
reinterpret_cast<uint8_t *
>(tx.
addr_) + write_data.
size_, 0,
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)
135 memset(
reinterpret_cast<uint8_t *
>(tx.
addr_) + write_data.
size_, 0,
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};
145 HAL_SPI_Transmit_DMA(spi_handle_,
static_cast<uint8_t *
>(tx.
addr_), need_write);
147 else if (read_data.
size_ > 0)
149 read_buff_ = read_data;
151 st = HAL_SPI_Receive_DMA(spi_handle_,
static_cast<uint8_t *
>(rx.
addr_),
156 if (op.
type != OperationRW::OperationType::BLOCK)
160 return ErrorCode::OK;
165 return ErrorCode::BUSY;
169 if (op.
type == OperationRW::OperationType::BLOCK)
171 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
173 return ErrorCode::OK;
176 ErrorCode ans = ErrorCode::OK;
178 if (write_data.
size_ > 0 && read_data.
size_ > 0)
181 if (write_data.
size_ < need_write)
183 memset(
reinterpret_cast<uint8_t *
>(tx.
addr_) + write_data.
size_, 0,
184 need_write - write_data.
size_);
186#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
187 SCB_CleanDCache_by_Addr(
static_cast<uint32_t *
>(tx.
addr_),
188 static_cast<int32_t
>(need_write));
190 ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t *
>(tx.
addr_),
191 static_cast<uint8_t *
>(rx.
addr_), need_write,
196 if (ans == ErrorCode::OK)
202 else if (read_data.
size_ > 0)
204 ans = (HAL_SPI_Receive(spi_handle_,
static_cast<uint8_t *
>(rx.
addr_), read_data.
size_,
209 if (ans == ErrorCode::OK)
215 else if (write_data.
size_ > 0)
218#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
219 SCB_CleanDCache_by_Addr(
static_cast<uint32_t *
>(tx.
addr_),
220 static_cast<int32_t
>(need_write));
222 ans = (HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t *
>(tx.
addr_),
223 write_data.
size_, 20) == HAL_OK)
231 if (op.
type != OperationRW::OperationType::BLOCK)
235 return ErrorCode::OK;
238 if (op.
type != OperationRW::OperationType::BLOCK)
250 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
253 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
260 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
263 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
268 uint32_t hal_presc = 0;
272#ifdef SPI_BAUDRATEPRESCALER_1
274 hal_presc = SPI_BAUDRATEPRESCALER_1;
277#ifdef SPI_BAUDRATEPRESCALER_2
279 hal_presc = SPI_BAUDRATEPRESCALER_2;
282#ifdef SPI_BAUDRATEPRESCALER_4
284 hal_presc = SPI_BAUDRATEPRESCALER_4;
287#ifdef SPI_BAUDRATEPRESCALER_8
289 hal_presc = SPI_BAUDRATEPRESCALER_8;
292#ifdef SPI_BAUDRATEPRESCALER_16
294 hal_presc = SPI_BAUDRATEPRESCALER_16;
297#ifdef SPI_BAUDRATEPRESCALER_32
299 hal_presc = SPI_BAUDRATEPRESCALER_32;
302#ifdef SPI_BAUDRATEPRESCALER_64
304 hal_presc = SPI_BAUDRATEPRESCALER_64;
307#ifdef SPI_BAUDRATEPRESCALER_128
309 hal_presc = SPI_BAUDRATEPRESCALER_128;
312#ifdef SPI_BAUDRATEPRESCALER_256
314 hal_presc = SPI_BAUDRATEPRESCALER_256;
317#ifdef SPI_BAUDRATEPRESCALER_512
319 hal_presc = SPI_BAUDRATEPRESCALER_512;
322#ifdef SPI_BAUDRATEPRESCALER_1024
324 hal_presc = SPI_BAUDRATEPRESCALER_1024;
335 return ErrorCode::NOT_SUPPORT;
338 spi_handle_->Init.BaudRatePrescaler = hal_presc;
342 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
347 uint32_t need_read = read_data.
size_;
349 if (spi_handle_->State != HAL_SPI_STATE_READY)
351 return ErrorCode::BUSY;
357 ASSERT(rx.
size_ >= need_read + 1);
358 ASSERT(tx.
size_ >= need_read + 1);
360 if (need_read + 1 > dma_enable_min_size_)
365 uint8_t *txb =
reinterpret_cast<uint8_t *
>(tx.
addr_);
366 memset(txb, 0, need_read + 1);
367 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
368#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
369 SCB_CleanDCache_by_Addr(
static_cast<uint32_t *
>(tx.
addr_),
370 static_cast<int32_t
>(need_read + 1));
372 read_buff_ = read_data;
374 HAL_StatusTypeDef st =
375 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t *
>(tx.
addr_),
376 static_cast<uint8_t *
>(rx.
addr_), need_read + 1);
380 return ErrorCode::BUSY;
384 if (op.
type == OperationRW::OperationType::BLOCK)
386 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
388 return ErrorCode::OK;
392 uint8_t *txb =
reinterpret_cast<uint8_t *
>(tx.
addr_);
393 memset(txb, 0, need_read + 1);
394 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
395#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
396 SCB_CleanDCache_by_Addr(
static_cast<uint32_t *
>(tx.
addr_),
397 static_cast<int32_t
>(need_read + 1));
400 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t *
>(tx.
addr_),
401 static_cast<uint8_t *
>(rx.
addr_),
402 need_read + 1, 20) == HAL_OK)
406 if (ans == ErrorCode::OK)
408 uint8_t *rxb =
reinterpret_cast<uint8_t *
>(rx.
addr_);
409 memcpy(read_data.
addr_, rxb + 1, need_read);
413 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);
439 memcpy(txb + 1, write_data.
addr_, need_write);
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);
464 memcpy(txb + 1, write_data.
addr_, need_write);
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)
495#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
496 defined(RCC_PERIPHCLK_SPI6)
510#ifdef RCC_PERIPHCLK_SPI123
511 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
524#ifdef RCC_PERIPHCLK_SPI45
525 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
532#ifdef RCC_PERIPHCLK_SPI6
533 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
540#if defined(RCC_PERIPHCLK_SPI1)
542 if (inst == SPI1)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
545#if defined(RCC_PERIPHCLK_SPI2)
547 if (inst == SPI2)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
550#if defined(RCC_PERIPHCLK_SPI3)
552 if (inst == SPI3)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
555#if defined(RCC_PERIPHCLK_SPI4)
557 if (inst == SPI4)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
560#if defined(RCC_PERIPHCLK_SPI5)
562 if (inst == SPI5)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
565#if defined(RCC_PERIPHCLK_SPI6)
567 if (inst == SPI6)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
573#if defined(STM32H7) && defined(SPI6)
576#if defined(HAL_RCC_GetPCLK4Freq)
577 return HAL_RCC_GetPCLK4Freq();
579 return HAL_RCC_GetHCLKFreq();
606#if defined(HAL_RCC_GetPCLK2Freq)
607 return HAL_RCC_GetPCLK2Freq();
608#elif defined(HAL_RCC_GetPCLK1Freq)
609 return HAL_RCC_GetPCLK1Freq();
611 return HAL_RCC_GetHCLKFreq();
616#if defined(HAL_RCC_GetPCLK1Freq)
617 return HAL_RCC_GetPCLK1Freq();
618#elif defined(HAL_RCC_GetPCLK2Freq)
619 return HAL_RCC_GetPCLK2Freq();
621 return HAL_RCC_GetHCLKFreq();
628#if defined(SPI_BAUDRATEPRESCALER_1024)
630#elif defined(SPI_BAUDRATEPRESCALER_512)
632#elif defined(SPI_BAUDRATEPRESCALER_256)
634#elif defined(SPI_BAUDRATEPRESCALER_128)
636#elif defined(SPI_BAUDRATEPRESCALER_64)
638#elif defined(SPI_BAUDRATEPRESCALER_32)
640#elif defined(SPI_BAUDRATEPRESCALER_16)
642#elif defined(SPI_BAUDRATEPRESCALER_8)
644#elif defined(SPI_BAUDRATEPRESCALER_4)
646#elif defined(SPI_BAUDRATEPRESCALER_2)
648#elif defined(SPI_BAUDRATEPRESCALER_1)
657 if (spi_handle_->State != HAL_SPI_STATE_READY)
659 return ErrorCode::BUSY;
664 if (op.
type != OperationRW::OperationType::BLOCK)
668 return ErrorCode::OK;
674 const uint16_t xfer =
static_cast<uint16_t
>(size);
676 if (size > dma_enable_min_size_)
680#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
681 SCB_CleanDCache_by_Addr(
static_cast<uint32_t *
>(tx.
addr_),
682 static_cast<int32_t
>(xfer));
683 SCB_InvalidateDCache_by_Addr(
static_cast<uint32_t *
>(rx.
addr_),
684 static_cast<int32_t
>(xfer));
687 HAL_StatusTypeDef st =
688 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t *
>(tx.
addr_),
689 static_cast<uint8_t *
>(rx.
addr_), xfer);
693 return ErrorCode::BUSY;
697 if (op.
type == OperationRW::OperationType::BLOCK)
699 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
701 return ErrorCode::OK;
705 (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t *
>(tx.
addr_),
706 static_cast<uint8_t *
>(rx.
addr_), xfer, 20) == HAL_OK)
710#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
711 SCB_InvalidateDCache_by_Addr(
static_cast<uint32_t *
>(rx.
addr_),
712 static_cast<int32_t
>(xfer));
717 if (op.
type != OperationRW::OperationType::BLOCK)
724extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
726 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
731extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
733 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
737 if (spi->read_buff_.
size_ > 0)
741#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
742 SCB_InvalidateDCache_by_Addr(rx.
addr_, spi->read_buff_.
size_);
748#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
749 SCB_InvalidateDCache_by_Addr(rx.
addr_, spi->read_buff_.
size_ + 1);
751 uint8_t *rx_dma_buff =
reinterpret_cast<uint8_t *
>(rx.
addr_);
752 memcpy(spi->read_buff_.
addr_, rx_dma_buff + 1, spi->read_buff_.
size_);
754 spi->read_buff_.
size_ = 0;
761extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
763 HAL_SPI_RxCpltCallback(hspi);
766extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
768 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).
union LibXR::Operation::@5 data
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
原始数据封装类。 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.
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op) override
进行 SPI 读写操作。Performs SPI read and write operations.
ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) override
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) override
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
ErrorCode Transfer(size_t size, OperationRW &op) 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 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.