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)
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)
171 if (op.
type == OperationRW::OperationType::BLOCK)
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;
333 spi_handle_->Init.BaudRatePrescaler = hal_presc;
342 uint32_t need_read = read_data.
size_;
344 if (spi_handle_->State != HAL_SPI_STATE_READY)
352 ASSERT(rx.
size_ >= need_read + 1);
353 ASSERT(tx.
size_ >= need_read + 1);
355 if (need_read + 1 > dma_enable_min_size_)
359 if (op.
type == OperationRW::OperationType::BLOCK)
364 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
366 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
368 read_buff_ = read_data;
370 HAL_StatusTypeDef st =
371 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
372 static_cast<uint8_t*
>(rx.
addr_), need_read + 1);
376 if (op.
type == OperationRW::OperationType::BLOCK)
384 if (op.
type == OperationRW::OperationType::BLOCK)
392 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
394 txb[0] =
static_cast<uint8_t
>(reg | 0x80);
397 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
398 static_cast<uint8_t*
>(rx.
addr_), need_read + 1,
405 uint8_t* rxb =
reinterpret_cast<uint8_t*
>(rx.
addr_);
410 if (op.
type != OperationRW::OperationType::BLOCK)
420 uint32_t need_write = write_data.
size_;
422 if (spi_handle_->State != HAL_SPI_STATE_READY)
428 ASSERT(tx.
size_ >= need_write + 1);
430 if (need_write + 1 > dma_enable_min_size_)
434 if (op.
type == OperationRW::OperationType::BLOCK)
439 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
440 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
443 read_buff_ = {
nullptr, 0};
445 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
446 spi_handle_,
static_cast<uint8_t*
>(tx.
addr_), need_write + 1);
450 if (op.
type == OperationRW::OperationType::BLOCK)
458 if (op.
type == OperationRW::OperationType::BLOCK)
465 uint8_t* txb =
reinterpret_cast<uint8_t*
>(tx.
addr_);
466 txb[0] =
static_cast<uint8_t
>(reg & 0x7F);
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)
666 if (op.
type != OperationRW::OperationType::BLOCK)
676 const uint16_t xfer =
static_cast<uint16_t
>(size);
678 if (size > dma_enable_min_size_)
681 if (op.
type == OperationRW::OperationType::BLOCK)
689 HAL_StatusTypeDef st =
690 HAL_SPI_TransmitReceive_DMA(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
691 static_cast<uint8_t*
>(rx.
addr_), xfer);
695 if (op.
type == OperationRW::OperationType::BLOCK)
703 if (op.
type == OperationRW::OperationType::BLOCK)
711 (HAL_SPI_TransmitReceive(spi_handle_,
static_cast<uint8_t*
>(tx.
addr_),
712 static_cast<uint8_t*
>(rx.
addr_), xfer, 20) == HAL_OK)
720 if (op.
type != OperationRW::OperationType::BLOCK)
727extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
729 const auto spi_id = STM32_SPI_GetID(hspi->Instance);
730 STM32SPI* spi = (spi_id == STM32_SPI_ID_ERROR) ?
nullptr :
STM32SPI::map[spi_id];
735 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
740 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
750extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
752 const auto spi_id = STM32_SPI_GetID(hspi->Instance);
753 STM32SPI* spi = (spi_id == STM32_SPI_ID_ERROR) ?
nullptr :
STM32SPI::map[spi_id];
758 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
764 const bool has_user_read_copy = (spi->read_buff_.
size_ > 0);
766 if (has_user_read_copy)
776 uint8_t* rx_dma_buff =
reinterpret_cast<uint8_t*
>(rx.
addr_);
779 spi->read_buff_.
size_ = 0;
783 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
793extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
795 HAL_SPI_RxCpltCallback(hspi);
798extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
800 const auto spi_id = STM32_SPI_GetID(hspi->Instance);
801 STM32SPI* spi = (spi_id == STM32_SPI_ID_ERROR) ?
nullptr :
STM32SPI::map[spi_id];
806 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::NONE)
810 if (spi->rw_op_.
type == STM32SPI::OperationRW::OperationType::BLOCK)
bool TryPost(bool in_isr, ErrorCode ec)
尝试认领完成并唤醒调用者 / Try to claim completion and wake the caller.
void Start(Semaphore &sem)
绑定信号量并开始等待 / Bind a semaphore and start waiting.
ErrorCode Wait(uint32_t timeout)
等待完成或超时交接 / Wait for completion or a timeout handoff.
void Cancel()
清除等待状态,不发送通知 / Clear the wait state without posting.
只读原始数据视图 / 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
uint32_t timeout
等待超时值 / Wait timeout.
void UpdateStatus(bool in_isr, Status &&status)
按通知方式报告完成结果 / Report completion using the selected mode.
union LibXR::Operation::@6 data
完成通知对象,由 type 选择有效成员 / Notification target selected by type.
void MarkAsRunning()
标记轮询操作正在执行 / Mark a polling operation as running.
Semaphore * sem
借用的信号量 / Borrowed semaphore.
OperationType type
当前通知方式 / Current notification mode.
可写原始数据视图 / 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.
LibXR 命名空间 / LibXR namespace.
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
失效指定内存范围覆盖的 D-Cache cache line Invalidates D-Cache lines covering the specified memory range
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ NOT_SUPPORT
不支持 / Not supported
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
constexpr auto max(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最大值 / Computes the maximum of two numbers
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
清理指定内存范围覆盖的 D-Cache cache line 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.