1#include "stm32_spi.hpp"
3#include "libxr_def.hpp"
4#include "stm32_dcache.hpp"
6#ifdef HAL_SPI_MODULE_ENABLED
10STM32SPI* STM32SPI::map[STM32_SPI_NUMBER] = {
nullptr};
12stm32_spi_id_t STM32_SPI_GetID(SPI_TypeDef* addr)
16 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
19 else if (addr == SPI1)
21 return stm32_spi_id_t::STM32_SPI1;
25 else if (addr == SPI2)
27 return stm32_spi_id_t::STM32_SPI2;
31 else if (addr == SPI3)
33 return stm32_spi_id_t::STM32_SPI3;
37 else if (addr == SPI4)
39 return stm32_spi_id_t::STM32_SPI4;
43 else if (addr == SPI5)
45 return stm32_spi_id_t::STM32_SPI5;
49 else if (addr == SPI6)
51 return stm32_spi_id_t::STM32_SPI6;
55 else if (addr == SPI7)
57 return stm32_spi_id_t::STM32_SPI7;
61 else if (addr == SPI8)
63 return stm32_spi_id_t::STM32_SPI8;
68 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
73 uint32_t dma_enable_min_size)
75 spi_handle_(spi_handle),
76 id_(STM32_SPI_GetID(spi_handle_->Instance)),
77 dma_enable_min_size_(dma_enable_min_size)
79 ASSERT(id_ != STM32_SPI_ID_ERROR);
94 ASSERT(need_write <= rx.
size_);
98 ASSERT(need_write <= tx.
size_);
101 if (spi_handle_->State != HAL_SPI_STATE_READY)
108 if (need_write > dma_enable_min_size_)
111 if (op.
type == OperationRW::OperationType::BLOCK)
113 block_wait_.Start(*op.
data.sem_info.sem);
116 HAL_StatusTypeDef st = HAL_OK;
118 if (write_data.
size_ > 0 && read_data.
size_ > 0)
121 if (write_data.
size_ < need_write)
124 need_write - write_data.
size_);
127 read_buff_ = read_data;
129 st = HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
130 static_cast<uint8_t*
>(rx.
addr_), need_write);
132 else if (write_data.
size_ > 0)
135 if (write_data.
size_ < need_write)
138 need_write - write_data.
size_);
141 read_buff_ = {
nullptr, 0};
143 st = HAL_SPI_Transmit_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_), need_write);
145 else if (read_data.
size_ > 0)
147 read_buff_ = read_data;
149 st = HAL_SPI_Receive_DMA(spi_handle_,
static_cast<uint8_t*
>(rx.
addr_),
154 if (op.
type != OperationRW::OperationType::BLOCK)
163 if (op.
type == OperationRW::OperationType::BLOCK)
165 block_wait_.Cancel();
171 if (op.
type == OperationRW::OperationType::BLOCK)
173 return block_wait_.Wait(op.
data.sem_info.timeout);
180 if (write_data.
size_ > 0 && read_data.
size_ > 0)
183 if (write_data.
size_ < need_write)
186 need_write - write_data.
size_);
189 ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
190 static_cast<uint8_t*
>(rx.
addr_), need_write,
201 else if (read_data.
size_ > 0)
203 ans = (HAL_SPI_Receive(spi_handle_,
static_cast<uint8_t*
>(rx.
addr_), read_data.
size_,
214 else if (write_data.
size_ > 0)
218 ans = (HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
219 write_data.
size_, 20) == HAL_OK)
227 if (op.
type != OperationRW::OperationType::BLOCK)
234 if (op.
type != OperationRW::OperationType::BLOCK)
246 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
249 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
256 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
259 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
264 uint32_t hal_presc = 0;
268#ifdef SPI_BAUDRATEPRESCALER_1
270 hal_presc = SPI_BAUDRATEPRESCALER_1;
273#ifdef SPI_BAUDRATEPRESCALER_2
275 hal_presc = SPI_BAUDRATEPRESCALER_2;
278#ifdef SPI_BAUDRATEPRESCALER_4
280 hal_presc = SPI_BAUDRATEPRESCALER_4;
283#ifdef SPI_BAUDRATEPRESCALER_8
285 hal_presc = SPI_BAUDRATEPRESCALER_8;
288#ifdef SPI_BAUDRATEPRESCALER_16
290 hal_presc = SPI_BAUDRATEPRESCALER_16;
293#ifdef SPI_BAUDRATEPRESCALER_32
295 hal_presc = SPI_BAUDRATEPRESCALER_32;
298#ifdef SPI_BAUDRATEPRESCALER_64
300 hal_presc = SPI_BAUDRATEPRESCALER_64;
303#ifdef SPI_BAUDRATEPRESCALER_128
305 hal_presc = SPI_BAUDRATEPRESCALER_128;
308#ifdef SPI_BAUDRATEPRESCALER_256
310 hal_presc = SPI_BAUDRATEPRESCALER_256;
313#ifdef SPI_BAUDRATEPRESCALER_512
315 hal_presc = SPI_BAUDRATEPRESCALER_512;
318#ifdef SPI_BAUDRATEPRESCALER_1024
320 hal_presc = SPI_BAUDRATEPRESCALER_1024;
334 spi_handle_->Init.BaudRatePrescaler = hal_presc;
343 uint32_t need_read = read_data.
size_;
345 if (spi_handle_->State != HAL_SPI_STATE_READY)
353 ASSERT(rx.
size_ >= need_read + 1);
354 ASSERT(tx.
size_ >= need_read + 1);
356 if (need_read + 1 > dma_enable_min_size_)
360 if (op.
type == OperationRW::OperationType::BLOCK)
362 block_wait_.Start(*op.
data.sem_info.sem);
365 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
367 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
369 read_buff_ = read_data;
371 HAL_StatusTypeDef st =
372 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
373 static_cast<uint8_t*
>(rx.
addr_), need_read + 1);
377 if (op.
type == OperationRW::OperationType::BLOCK)
379 block_wait_.Cancel();
385 if (op.
type == OperationRW::OperationType::BLOCK)
387 return block_wait_.Wait(op.
data.sem_info.timeout);
393 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
395 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
398 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
399 static_cast<uint8_t*
>(rx.
addr_), need_read + 1,
406 uint8_t* rxb =
reinterpret_cast<uint8_t*
>(rx.
addr_);
411 if (op.
type != OperationRW::OperationType::BLOCK)
421 uint32_t need_write = write_data.
size_;
423 if (spi_handle_->State != HAL_SPI_STATE_READY)
429 ASSERT(tx.
size_ >= need_write + 1);
431 if (need_write + 1 > dma_enable_min_size_)
435 if (op.
type == OperationRW::OperationType::BLOCK)
437 block_wait_.Start(*op.
data.sem_info.sem);
440 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
441 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
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 if (op.
type == OperationRW::OperationType::BLOCK)
453 block_wait_.Cancel();
459 if (op.
type == OperationRW::OperationType::BLOCK)
461 return block_wait_.Wait(op.
data.sem_info.timeout);
466 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
467 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
471 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
472 need_write + 1, 20) == HAL_OK)
478 if (op.
type != OperationRW::OperationType::BLOCK)
487 SPI_TypeDef* inst = spi_handle_ ? spi_handle_->Instance :
nullptr;
493#if defined(HAL_RCC_MODULE_ENABLED)
497#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
498 defined(RCC_PERIPHCLK_SPI6)
512#ifdef RCC_PERIPHCLK_SPI123
513 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
526#ifdef RCC_PERIPHCLK_SPI45
527 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
534#ifdef RCC_PERIPHCLK_SPI6
535 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
542#if defined(RCC_PERIPHCLK_SPI1)
544 if (inst == SPI1)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
547#if defined(RCC_PERIPHCLK_SPI2)
549 if (inst == SPI2)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
552#if defined(RCC_PERIPHCLK_SPI3)
554 if (inst == SPI3)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
557#if defined(RCC_PERIPHCLK_SPI4)
559 if (inst == SPI4)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
562#if defined(RCC_PERIPHCLK_SPI5)
564 if (inst == SPI5)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
567#if defined(RCC_PERIPHCLK_SPI6)
569 if (inst == SPI6)
return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
576#if defined(STM32H7) && defined(SPI6)
579#if defined(HAL_RCC_GetPCLK4Freq)
580 return HAL_RCC_GetPCLK4Freq();
582 return HAL_RCC_GetHCLKFreq();
609#if defined(HAL_RCC_GetPCLK2Freq)
610 return HAL_RCC_GetPCLK2Freq();
611#elif defined(HAL_RCC_GetPCLK1Freq)
612 return HAL_RCC_GetPCLK1Freq();
614 return HAL_RCC_GetHCLKFreq();
619#if defined(HAL_RCC_GetPCLK1Freq)
620 return HAL_RCC_GetPCLK1Freq();
621#elif defined(HAL_RCC_GetPCLK2Freq)
622 return HAL_RCC_GetPCLK2Freq();
624 return HAL_RCC_GetHCLKFreq();
631#if defined(SPI_BAUDRATEPRESCALER_1024)
633#elif defined(SPI_BAUDRATEPRESCALER_512)
635#elif defined(SPI_BAUDRATEPRESCALER_256)
637#elif defined(SPI_BAUDRATEPRESCALER_128)
639#elif defined(SPI_BAUDRATEPRESCALER_64)
641#elif defined(SPI_BAUDRATEPRESCALER_32)
643#elif defined(SPI_BAUDRATEPRESCALER_16)
645#elif defined(SPI_BAUDRATEPRESCALER_8)
647#elif defined(SPI_BAUDRATEPRESCALER_4)
649#elif defined(SPI_BAUDRATEPRESCALER_2)
651#elif defined(SPI_BAUDRATEPRESCALER_1)
660 if (spi_handle_->State != HAL_SPI_STATE_READY)
667 if (op.
type != OperationRW::OperationType::BLOCK)
677 const uint16_t xfer =
static_cast<uint16_t
>(size);
679 if (size > dma_enable_min_size_)
682 if (op.
type == OperationRW::OperationType::BLOCK)
684 block_wait_.Start(*op.
data.sem_info.sem);
690 HAL_StatusTypeDef st =
691 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
692 static_cast<uint8_t*
>(rx.
addr_), xfer);
696 if (op.
type == OperationRW::OperationType::BLOCK)
698 block_wait_.Cancel();
704 if (op.
type == OperationRW::OperationType::BLOCK)
706 return block_wait_.Wait(op.
data.sem_info.timeout);
712 (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
713 static_cast<uint8_t*
>(rx.
addr_), xfer, 20) == HAL_OK)
721 if (op.
type != OperationRW::OperationType::BLOCK)
728extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
730 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
731 ASSERT(spi !=
nullptr);
732 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
737 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
747extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
749 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
750 ASSERT(spi !=
nullptr);
751 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
757 const bool has_user_read_copy = (spi->read_buff_.
size_ > 0);
759 if (has_user_read_copy)
769 uint8_t* rx_dma_buff =
reinterpret_cast<uint8_t*
>(rx.
addr_);
772 spi->read_buff_.
size_ = 0;
776 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
786extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
788 HAL_SPI_RxCpltCallback(hspi);
791extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
793 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
794 ASSERT(spi !=
nullptr);
795 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
799 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
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.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
串行外设接口(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.
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
Invalidates D-Cache lines covering the specified memory range.
@ NOT_SUPPORT
不支持 | Not supported
@ FAILED
操作失败 | Operation failed
@ OK
操作成功 | Operation successful
constexpr auto max(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最大值
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
Cleans D-Cache lines covering the specified memory range.
存储 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.