libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
LibXR::STM32SPI Class Reference

STM32 SPI 驱动实现 / STM32 SPI driver implementation. More...

#include <stm32_spi.hpp>

Inheritance diagram for LibXR::STM32SPI:
[legend]
Collaboration diagram for LibXR::STM32SPI:
[legend]

Public Member Functions

 STM32SPI (SPI_HandleTypeDef *spi_handle, RawData dma_buff_rx, RawData dma_buff_tx, uint32_t dma_enable_min_size=3)
 构造 SPI 对象 / Construct SPI object
 
ErrorCode ReadAndWrite (RawData read_data, ConstRawData write_data, OperationRW &op, bool in_isr) override
 进行 SPI 读写操作 / Performs SPI read and write operations.
 
ErrorCode SetConfig (SPI::Configuration config) override
 设置 SPI 配置参数 / Sets SPI configuration parameters.
 
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.
 
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.
 
uint32_t GetMaxBusSpeed () const override
 获取 SPI 设备的最大时钟速度 / Gets the maximum clock speed of the SPI device.
 
Prescaler GetMaxPrescaler () const override
 获取 SPI 设备的最大分频系数 / Gets the maximum prescaler 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).
 
- Public Member Functions inherited from LibXR::SPI
 SPI (RawData rx_buffer, RawData tx_buffer)
 构造函数 / Constructor.
 
virtual ErrorCode Read (RawData read_data, OperationRW &op, bool in_isr=false)
 进行 SPI 读取操作 / Performs SPI read operation.
 
virtual ErrorCode Write (ConstRawData write_data, OperationRW &op, bool in_isr=false)
 进行 SPI 写入操作 / Performs SPI write operation.
 
uint32_t GetBusSpeed () const
 获取 SPI 设备的当前总线速度 / Gets the current bus speed of the SPI device.
 
Prescaler CalcPrescaler (uint32_t target_max_bus_speed, uint32_t target_min_bus_speed, bool increase)
 计算 SPI 分频系数 / Calculates the SPI prescaler.
 
RawData GetRxBuffer ()
 获取接收数据的缓冲区 / Gets the buffer for storing received data.
 
RawData GetTxBuffer ()
 获取发送数据的缓冲区 / Gets the buffer for storing data to be sent.
 
void SwitchBuffer ()
 切换缓冲区 / Switches the buffer.
 
void SetActiveLength (size_t len)
 设置缓冲区的有效数据长度 / Sets the length of valid data in the buffer.
 
size_t GetActiveLength () const
 获取缓冲区的有效数据长度 / Gets the length of valid data in the buffer.
 
Configuration & GetConfig ()
 获取 SPI 配置参数 / Gets the SPI configuration parameters.
 
bool IsDoubleBuffer () const
 检查是否使用双缓冲区 / Checks if double buffering is enabled.
 

Public Attributes

SPI_HandleTypeDef * spi_handle_
 
stm32_spi_id_t id_ = STM32_SPI_ID_ERROR
 
uint32_t dma_enable_min_size_ = 3
 
OperationRW rw_op_
 
RawData read_buff_
 
bool mem_read_ = false
 
AsyncBlockWait block_wait_ {}
 

Static Public Attributes

static STM32SPI * map [STM32_SPI_NUMBER] = {nullptr}
 

Additional Inherited Members

- Public Types inherited from LibXR::SPI
enum class  ClockPolarity : uint8_t { LOW = 0 , HIGH = 1 }
 定义 SPI 时钟极性 / Defines the SPI clock polarity. More...
 
enum class  ClockPhase : uint8_t { EDGE_1 = 0 , EDGE_2 = 1 }
 定义 SPI 时钟相位 / Defines the SPI clock phase. More...
 
enum class  Prescaler : uint8_t {
  DIV_1 = 0 , DIV_2 = 1 , DIV_4 = 2 , DIV_8 = 3 ,
  DIV_16 = 4 , DIV_32 = 5 , DIV_64 = 6 , DIV_128 = 7 ,
  DIV_256 = 8 , DIV_512 = 9 , DIV_1024 = 10 , DIV_2048 = 11 ,
  DIV_4096 = 12 , DIV_8192 = 13 , DIV_16384 = 14 , DIV_32768 = 15 ,
  DIV_65536 = 16 , UNKNOWN = 0xFF
}
 
using OperationRW = WriteOperation
 定义读写操作类型的别名 / Defines an alias for the read/write operation type.
 
- Static Public Member Functions inherited from LibXR::SPI
static constexpr uint32_t PrescalerToDiv (Prescaler prescaler)
 将分频系数转换为除数 / Converts a prescaler to a divisor.
 

Detailed Description

STM32 SPI 驱动实现 / STM32 SPI driver implementation.

Definition at line 54 of file stm32_spi.hpp.

Constructor & Destructor Documentation

◆ STM32SPI()

STM32SPI::STM32SPI ( SPI_HandleTypeDef * spi_handle,
RawData dma_buff_rx,
RawData dma_buff_tx,
uint32_t dma_enable_min_size = 3 )

构造 SPI 对象 / Construct SPI object

Definition at line 72 of file stm32_spi.cpp.

74 : SPI(rx, tx),
75 spi_handle_(spi_handle),
76 id_(STM32_SPI_GetID(spi_handle_->Instance)),
77 dma_enable_min_size_(dma_enable_min_size)
78{
79 ASSERT(id_ != STM32_SPI_ID_ERROR);
80
81 map[id_] = this;
82}
SPI(RawData rx_buffer, RawData tx_buffer)
构造函数 / Constructor.
Definition spi.hpp:111

Member Function Documentation

◆ GetMaxBusSpeed()

uint32_t STM32SPI::GetMaxBusSpeed ( ) const
overridevirtual

获取 SPI 设备的最大时钟速度 / Gets the maximum clock speed of the SPI device.

Returns
SPI 设备的最大时钟速度(单位:Hz)。 The maximum clock speed of the SPI device (in Hz).

Implements LibXR::SPI.

Definition at line 484 of file stm32_spi.cpp.

485{
486 SPI_TypeDef* inst = spi_handle_ ? spi_handle_->Instance : nullptr;
487 if (!inst)
488 {
489 return 0u;
490 }
491
492#if defined(HAL_RCC_MODULE_ENABLED)
493// 1) 优先读取独立 SPI 内核时钟。
494// 1) Prefer dedicated SPI kernel clock when available.
495// H7: 分组宏 SPI123 / SPI45 / SPI6
496#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
497 defined(RCC_PERIPHCLK_SPI6)
498 // SPI1/2/3 → RCC_PERIPHCLK_SPI123
499 if (
500#ifdef SPI1
501 inst == SPI1 ||
502#endif
503#ifdef SPI2
504 inst == SPI2 ||
505#endif
506#ifdef SPI3
507 inst == SPI3 ||
508#endif
509 false)
510 {
511#ifdef RCC_PERIPHCLK_SPI123
512 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
513#endif
514 }
515 // SPI4/5 → RCC_PERIPHCLK_SPI45
516 if (
517#ifdef SPI4
518 inst == SPI4 ||
519#endif
520#ifdef SPI5
521 inst == SPI5 ||
522#endif
523 false)
524 {
525#ifdef RCC_PERIPHCLK_SPI45
526 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
527#endif
528 }
529// SPI6 → RCC_PERIPHCLK_SPI6
530#ifdef SPI6
531 if (inst == SPI6)
532 {
533#ifdef RCC_PERIPHCLK_SPI6
534 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
535#endif
536 }
537#endif
538#endif // H7 分组
539
540// 其它系列:通常是逐个 SPIx 宏
541#if defined(RCC_PERIPHCLK_SPI1)
542#ifdef SPI1
543 if (inst == SPI1) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
544#endif
545#endif
546#if defined(RCC_PERIPHCLK_SPI2)
547#ifdef SPI2
548 if (inst == SPI2) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
549#endif
550#endif
551#if defined(RCC_PERIPHCLK_SPI3)
552#ifdef SPI3
553 if (inst == SPI3) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
554#endif
555#endif
556#if defined(RCC_PERIPHCLK_SPI4)
557#ifdef SPI4
558 if (inst == SPI4) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
559#endif
560#endif
561#if defined(RCC_PERIPHCLK_SPI5)
562#ifdef SPI5
563 if (inst == SPI5) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
564#endif
565#endif
566#if defined(RCC_PERIPHCLK_SPI6)
567#ifdef SPI6
568 if (inst == SPI6) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
569#endif
570#endif
571#endif // HAL_RCC_MODULE_ENABLED
572
573 // 2) 回退到所在 APB 的 PCLK。
574 // 2) Fallback to APB PCLK if no dedicated kernel clock is available.
575#if defined(STM32H7) && defined(SPI6)
576 if (inst == SPI6)
577 {
578#if defined(HAL_RCC_GetPCLK4Freq)
579 return HAL_RCC_GetPCLK4Freq();
580#else
581 return HAL_RCC_GetHCLKFreq();
582#endif
583 }
584#endif
585
586 // 大多数系列:SPI1/4/5/6/7/8 → APB2; / SPI2/3 → APB1
587 if (
588#ifdef SPI1
589 inst == SPI1 ||
590#endif
591#ifdef SPI4
592 inst == SPI4 ||
593#endif
594#ifdef SPI5
595 inst == SPI5 ||
596#endif
597#ifdef SPI6
598 inst == SPI6 ||
599#endif
600#ifdef SPI7
601 inst == SPI7 ||
602#endif
603#ifdef SPI8
604 inst == SPI8 ||
605#endif
606 false)
607 {
608#if defined(HAL_RCC_GetPCLK2Freq)
609 return HAL_RCC_GetPCLK2Freq();
610#elif defined(HAL_RCC_GetPCLK1Freq)
611 return HAL_RCC_GetPCLK1Freq(); // 低端/单APB系列兜底
612#else
613 return HAL_RCC_GetHCLKFreq();
614#endif
615 }
616 else
617 {
618#if defined(HAL_RCC_GetPCLK1Freq)
619 return HAL_RCC_GetPCLK1Freq();
620#elif defined(HAL_RCC_GetPCLK2Freq)
621 return HAL_RCC_GetPCLK2Freq();
622#else
623 return HAL_RCC_GetHCLKFreq();
624#endif
625 }
626}

◆ GetMaxPrescaler()

STM32SPI::Prescaler STM32SPI::GetMaxPrescaler ( ) const
overridevirtual

获取 SPI 设备的最大分频系数 / Gets the maximum prescaler of the SPI device.

Returns
SPI 设备的最大分频系数 / The maximum prescaler of the SPI device.

Implements LibXR::SPI.

Definition at line 628 of file stm32_spi.cpp.

629{
630#if defined(SPI_BAUDRATEPRESCALER_1024)
631 return Prescaler::DIV_1024;
632#elif defined(SPI_BAUDRATEPRESCALER_512)
633 return Prescaler::DIV_512;
634#elif defined(SPI_BAUDRATEPRESCALER_256)
635 return Prescaler::DIV_256;
636#elif defined(SPI_BAUDRATEPRESCALER_128)
637 return Prescaler::DIV_128;
638#elif defined(SPI_BAUDRATEPRESCALER_64)
639 return Prescaler::DIV_64;
640#elif defined(SPI_BAUDRATEPRESCALER_32)
641 return Prescaler::DIV_32;
642#elif defined(SPI_BAUDRATEPRESCALER_16)
643 return Prescaler::DIV_16;
644#elif defined(SPI_BAUDRATEPRESCALER_8)
645 return Prescaler::DIV_8;
646#elif defined(SPI_BAUDRATEPRESCALER_4)
647 return Prescaler::DIV_4;
648#elif defined(SPI_BAUDRATEPRESCALER_2)
649 return Prescaler::DIV_2;
650#elif defined(SPI_BAUDRATEPRESCALER_1)
651 return Prescaler::DIV_1;
652#else
653 return Prescaler::UNKNOWN;
654#endif
655}
@ 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.

◆ MemRead()

ErrorCode STM32SPI::MemRead ( uint16_t reg,
RawData read_data,
OperationRW & op,
bool in_isr )
overridevirtual

从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.

Parameters
reg寄存器地址 / Register address.
read_data读取的数据缓冲区 / Buffer to store read data.
op操作类型(同步/异步) / Operation mode (sync/async).
in_isr是否在中断中进行操作 / Whether the operation is performed in an ISR.
Returns
操作结果的错误码 / Error code indicating success or failure.

Implements LibXR::SPI.

Definition at line 340 of file stm32_spi.cpp.

341{
342 uint32_t need_read = read_data.size_;
343
344 if (spi_handle_->State != HAL_SPI_STATE_READY)
345 {
346 return ErrorCode::BUSY;
347 }
348
349 RawData rx = GetRxBuffer();
350 RawData tx = GetTxBuffer();
351
352 ASSERT(rx.size_ >= need_read + 1);
353 ASSERT(tx.size_ >= need_read + 1);
354
355 if (need_read + 1 > dma_enable_min_size_)
356 {
357 mem_read_ = true;
358 rw_op_ = op;
359 if (op.type == OperationRW::OperationType::BLOCK)
360 {
361 block_wait_.Start(*op.data.sem_info.sem);
362 }
363
364 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
365 Memory::FastSet(txb, 0, need_read + 1);
366 txb[0] = static_cast<uint8_t>(reg | 0x80);
367 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
368 read_buff_ = read_data;
369
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);
373
374 if (st != HAL_OK)
375 {
376 if (op.type == OperationRW::OperationType::BLOCK)
377 {
378 block_wait_.Cancel();
379 }
380 return ErrorCode::BUSY;
381 }
382
383 op.MarkAsRunning();
384 if (op.type == OperationRW::OperationType::BLOCK)
385 {
386 return block_wait_.Wait(op.data.sem_info.timeout);
387 }
388 return ErrorCode::OK;
389 }
390
391 mem_read_ = false;
392 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
393 Memory::FastSet(txb, 0, need_read + 1);
394 txb[0] = static_cast<uint8_t>(reg | 0x80);
395 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
396
397 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
398 static_cast<uint8_t*>(rx.addr_), need_read + 1,
399 20) == HAL_OK)
401 : ErrorCode::BUSY;
402
403 if (ans == ErrorCode::OK)
404 {
405 uint8_t* rxb = reinterpret_cast<uint8_t*>(rx.addr_);
406 Memory::FastCopy(read_data.addr_, rxb + 1, need_read);
407 }
408 SwitchBuffer();
409
410 if (op.type != OperationRW::OperationType::BLOCK)
411 {
412 op.UpdateStatus(in_isr, ans);
413 }
414 return ans;
415}
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.
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
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
RawData GetRxBuffer()
获取接收数据的缓冲区 / Gets the buffer for storing received data.
Definition spi.hpp:307
void SwitchBuffer()
切换缓冲区 / Switches the buffer.
Definition spi.hpp:338
RawData GetTxBuffer()
获取发送数据的缓冲区 / Gets the buffer for storing data to be sent.
Definition spi.hpp:323
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ BUSY
忙碌 / Busy
@ OK
操作成功 / Operation successful
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
清理指定内存范围覆盖的 D-Cache cache line Cleans D-Cache lines covering the specified memory range

◆ MemWrite()

ErrorCode STM32SPI::MemWrite ( uint16_t reg,
ConstRawData write_data,
OperationRW & op,
bool in_isr )
overridevirtual

向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.

Parameters
reg寄存器地址 / Register address.
write_data写入的数据缓冲区 / Buffer containing data to write.
op操作类型(同步/异步) / Operation mode (sync/async).
in_isr是否在中断中进行操作 / Whether the operation is performed in an ISR.
Returns
操作结果的错误码 / Error code indicating success or failure.

Implements LibXR::SPI.

Definition at line 417 of file stm32_spi.cpp.

419{
420 uint32_t need_write = write_data.size_;
421
422 if (spi_handle_->State != HAL_SPI_STATE_READY)
423 {
424 return ErrorCode::BUSY;
425 }
426
427 RawData tx = GetTxBuffer();
428 ASSERT(tx.size_ >= need_write + 1);
429
430 if (need_write + 1 > dma_enable_min_size_)
431 {
432 mem_read_ = false;
433 rw_op_ = op;
434 if (op.type == OperationRW::OperationType::BLOCK)
435 {
436 block_wait_.Start(*op.data.sem_info.sem);
437 }
438
439 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
440 txb[0] = static_cast<uint8_t>(reg & 0x7F);
441 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
442 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
443 read_buff_ = {nullptr, 0};
444
445 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
446 spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write + 1);
447
448 if (st != HAL_OK)
449 {
450 if (op.type == OperationRW::OperationType::BLOCK)
451 {
452 block_wait_.Cancel();
453 }
454 return ErrorCode::BUSY;
455 }
456
457 op.MarkAsRunning();
458 if (op.type == OperationRW::OperationType::BLOCK)
459 {
460 return block_wait_.Wait(op.data.sem_info.timeout);
461 }
462 return ErrorCode::OK;
463 }
464
465 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
466 txb[0] = static_cast<uint8_t>(reg & 0x7F);
467 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
468 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
469
470 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
471 need_write + 1, 20) == HAL_OK)
473 : ErrorCode::BUSY;
474
475 SwitchBuffer();
476
477 if (op.type != OperationRW::OperationType::BLOCK)
478 {
479 op.UpdateStatus(in_isr, ans);
480 }
481 return ans;
482}
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address

◆ ReadAndWrite()

ErrorCode STM32SPI::ReadAndWrite ( RawData read_data,
ConstRawData write_data,
OperationRW & op,
bool in_isr )
overridevirtual

进行 SPI 读写操作 / Performs SPI read and write operations.

Parameters
read_data存储读取数据的缓冲区 / Buffer to store the read data.
write_data需要写入的数据缓冲区 / Buffer containing the data to be written.
op读写操作类型 / Type of read/write operation.
in_isr是否在中断中进行操作 / Whether the operation is performed in an ISR.
Returns
操作结果的错误码 / Error code indicating the result of the operation.

Implements LibXR::SPI.

Definition at line 84 of file stm32_spi.cpp.

86{
87 uint32_t need_write = max(write_data.size_, read_data.size_);
88
89 RawData rx = GetRxBuffer();
90 RawData tx = GetTxBuffer();
91
92 if (rx.size_ > 0)
93 {
94 ASSERT(need_write <= rx.size_);
95 }
96 if (tx.size_ > 0)
97 {
98 ASSERT(need_write <= tx.size_);
99 }
100
101 if (spi_handle_->State != HAL_SPI_STATE_READY)
102 {
103 return ErrorCode::BUSY;
104 }
105
106 mem_read_ = false;
107
108 if (need_write > dma_enable_min_size_)
109 {
110 rw_op_ = op;
111 if (op.type == OperationRW::OperationType::BLOCK)
112 {
113 block_wait_.Start(*op.data.sem_info.sem);
114 }
115
116 HAL_StatusTypeDef st = HAL_OK;
117
118 if (write_data.size_ > 0 && read_data.size_ > 0)
119 {
120 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
121 if (write_data.size_ < need_write)
122 {
123 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
124 need_write - write_data.size_);
125 }
126 STM32_CleanDCacheByAddr(tx.addr_, need_write);
127 read_buff_ = read_data;
128
129 st = HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
130 static_cast<uint8_t*>(rx.addr_), need_write);
131 }
132 else if (write_data.size_ > 0)
133 {
134 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
135 if (write_data.size_ < need_write)
136 {
137 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
138 need_write - write_data.size_);
139 }
140 STM32_CleanDCacheByAddr(tx.addr_, need_write);
141 read_buff_ = {nullptr, 0};
142
143 st = HAL_SPI_Transmit_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write);
144 }
145 else if (read_data.size_ > 0)
146 {
147 read_buff_ = read_data;
148
149 st = HAL_SPI_Receive_DMA(spi_handle_, static_cast<uint8_t*>(rx.addr_),
150 read_data.size_);
151 }
152 else
153 {
154 if (op.type != OperationRW::OperationType::BLOCK)
155 {
156 op.UpdateStatus(in_isr, ErrorCode::OK);
157 }
158 return ErrorCode::OK;
159 }
160
161 if (st != HAL_OK)
162 {
163 if (op.type == OperationRW::OperationType::BLOCK)
164 {
165 block_wait_.Cancel();
166 }
167 return ErrorCode::BUSY;
168 }
169
170 op.MarkAsRunning();
171 if (op.type == OperationRW::OperationType::BLOCK)
172 {
173 return block_wait_.Wait(op.data.sem_info.timeout);
174 }
175 return ErrorCode::OK;
176 }
177
179
180 if (write_data.size_ > 0 && read_data.size_ > 0)
181 {
182 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
183 if (write_data.size_ < need_write)
184 {
185 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
186 need_write - write_data.size_);
187 }
188 STM32_CleanDCacheByAddr(tx.addr_, need_write);
189 ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
190 static_cast<uint8_t*>(rx.addr_), need_write,
191 20) == HAL_OK)
193 : ErrorCode::BUSY;
194
195 if (ans == ErrorCode::OK)
196 {
197 Memory::FastCopy(read_data.addr_, rx.addr_, read_data.size_);
198 }
199 SwitchBuffer();
200 }
201 else if (read_data.size_ > 0)
202 {
203 ans = (HAL_SPI_Receive(spi_handle_, static_cast<uint8_t*>(rx.addr_), read_data.size_,
204 20) == HAL_OK)
206 : ErrorCode::BUSY;
207
208 if (ans == ErrorCode::OK)
209 {
210 Memory::FastCopy(read_data.addr_, rx.addr_, read_data.size_);
211 }
212 SwitchBuffer();
213 }
214 else if (write_data.size_ > 0)
215 {
216 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
217 STM32_CleanDCacheByAddr(tx.addr_, need_write);
218 ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
219 write_data.size_, 20) == HAL_OK)
221 : ErrorCode::BUSY;
222
223 SwitchBuffer();
224 }
225 else
226 {
227 if (op.type != OperationRW::OperationType::BLOCK)
228 {
229 op.UpdateStatus(in_isr, ErrorCode::OK);
230 }
231 return ErrorCode::OK;
232 }
233
234 if (op.type != OperationRW::OperationType::BLOCK)
235 {
236 op.UpdateStatus(in_isr, ans);
237 }
238 return ans;
239}
void MarkAsRunning()
标记轮询操作正在执行 / Mark a polling operation as running.
constexpr auto max(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最大值 / Computes the maximum of two numbers

◆ SetConfig()

ErrorCode STM32SPI::SetConfig ( SPI::Configuration config)
overridevirtual

设置 SPI 配置参数 / Sets SPI configuration parameters.

Parameters
config需要应用的 SPI 配置 / The SPI configuration to apply.
Returns
操作结果的错误码 / Error code indicating the result of the operation.

Implements LibXR::SPI.

Definition at line 241 of file stm32_spi.cpp.

242{
243 switch (config.clock_polarity)
244 {
246 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
247 break;
249 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
250 break;
251 }
252
253 switch (config.clock_phase)
254 {
256 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
257 break;
259 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
260 break;
261 }
262
263 bool ok = true;
264 uint32_t hal_presc = 0;
265
266 switch (config.prescaler)
267 {
268#ifdef SPI_BAUDRATEPRESCALER_1
269 case Prescaler::DIV_1:
270 hal_presc = SPI_BAUDRATEPRESCALER_1;
271 break;
272#endif
273#ifdef SPI_BAUDRATEPRESCALER_2
274 case Prescaler::DIV_2:
275 hal_presc = SPI_BAUDRATEPRESCALER_2;
276 break;
277#endif
278#ifdef SPI_BAUDRATEPRESCALER_4
279 case Prescaler::DIV_4:
280 hal_presc = SPI_BAUDRATEPRESCALER_4;
281 break;
282#endif
283#ifdef SPI_BAUDRATEPRESCALER_8
284 case Prescaler::DIV_8:
285 hal_presc = SPI_BAUDRATEPRESCALER_8;
286 break;
287#endif
288#ifdef SPI_BAUDRATEPRESCALER_16
290 hal_presc = SPI_BAUDRATEPRESCALER_16;
291 break;
292#endif
293#ifdef SPI_BAUDRATEPRESCALER_32
295 hal_presc = SPI_BAUDRATEPRESCALER_32;
296 break;
297#endif
298#ifdef SPI_BAUDRATEPRESCALER_64
300 hal_presc = SPI_BAUDRATEPRESCALER_64;
301 break;
302#endif
303#ifdef SPI_BAUDRATEPRESCALER_128
305 hal_presc = SPI_BAUDRATEPRESCALER_128;
306 break;
307#endif
308#ifdef SPI_BAUDRATEPRESCALER_256
310 hal_presc = SPI_BAUDRATEPRESCALER_256;
311 break;
312#endif
313#ifdef SPI_BAUDRATEPRESCALER_512
315 hal_presc = SPI_BAUDRATEPRESCALER_512;
316 break;
317#endif
318#ifdef SPI_BAUDRATEPRESCALER_1024
320 hal_presc = SPI_BAUDRATEPRESCALER_1024;
321 break;
322#endif
323 default:
324 ok = false;
325 break;
326 }
327
328 if (!ok)
329 {
331 }
332
333 spi_handle_->Init.BaudRatePrescaler = hal_presc;
334
335 GetConfig() = config;
336
337 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
338}
@ EDGE_2
在第二个时钟边沿采样数据 / Data sampled on the second clock edge.
@ EDGE_1
在第一个时钟边沿采样数据 / Data sampled on the first clock edge.
@ LOW
时钟空闲时为低电平 / Clock idle low.
@ HIGH
时钟空闲时为高电平 / Clock idle high.
Configuration & GetConfig()
获取 SPI 配置参数 / Gets the SPI configuration parameters.
Definition spi.hpp:397
@ NOT_SUPPORT
不支持 / Not supported
ClockPhase clock_phase
SPI 时钟相位 / SPI clock phase.
Definition spi.hpp:89
Prescaler prescaler
SPI 分频系数 / SPI prescaler.
Definition spi.hpp:90
ClockPolarity clock_polarity
SPI 时钟极性 / SPI clock polarity.
Definition spi.hpp:87

◆ Transfer()

ErrorCode STM32SPI::Transfer ( size_t size,
OperationRW & op,
bool in_isr )
overridevirtual

进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).

Parameters
size需要传输的数据大小 / The size of the data to be transferred.
op读写操作类型 / Type of read/write operation.
in_isr是否在中断中进行操作 / Whether the operation is performed in an ISR.
Returns
操作结果的错误码 / Error code indicating the result of the operation.

Implements LibXR::SPI.

Definition at line 657 of file stm32_spi.cpp.

658{
659 if (spi_handle_->State != HAL_SPI_STATE_READY)
660 {
661 return ErrorCode::BUSY;
662 }
663
664 if (size == 0)
665 {
666 if (op.type != OperationRW::OperationType::BLOCK)
667 {
668 op.UpdateStatus(in_isr, ErrorCode::OK);
669 }
670 return ErrorCode::OK;
671 }
672
673 RawData rx = GetRxBuffer();
674 RawData tx = GetTxBuffer();
675
676 const uint16_t xfer = static_cast<uint16_t>(size);
677
678 if (size > dma_enable_min_size_)
679 {
680 rw_op_ = op;
681 if (op.type == OperationRW::OperationType::BLOCK)
682 {
683 block_wait_.Start(*op.data.sem_info.sem);
684 }
685
688
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);
692
693 if (st != HAL_OK)
694 {
695 if (op.type == OperationRW::OperationType::BLOCK)
696 {
697 block_wait_.Cancel();
698 }
699 return ErrorCode::BUSY;
700 }
701
702 op.MarkAsRunning();
703 if (op.type == OperationRW::OperationType::BLOCK)
704 {
705 return block_wait_.Wait(op.data.sem_info.timeout);
706 }
707 return ErrorCode::OK;
708 }
709
710 ErrorCode ans =
711 (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
712 static_cast<uint8_t*>(rx.addr_), xfer, 20) == HAL_OK)
714 : ErrorCode::BUSY;
715
717
718 SwitchBuffer();
719
720 if (op.type != OperationRW::OperationType::BLOCK)
721 {
722 op.UpdateStatus(in_isr, ans);
723 }
724 return ans;
725}
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
失效指定内存范围覆盖的 D-Cache cache line Invalidates D-Cache lines covering the specified memory range

Member Data Documentation

◆ block_wait_

AsyncBlockWait LibXR::STM32SPI::block_wait_ {}

Definition at line 91 of file stm32_spi.hpp.

91{};

◆ dma_enable_min_size_

uint32_t LibXR::STM32SPI::dma_enable_min_size_ = 3

Definition at line 84 of file stm32_spi.hpp.

◆ id_

stm32_spi_id_t LibXR::STM32SPI::id_ = STM32_SPI_ID_ERROR

Definition at line 82 of file stm32_spi.hpp.

◆ map

STM32SPI * STM32SPI::map = {nullptr}
static

Definition at line 93 of file stm32_spi.hpp.

◆ mem_read_

bool LibXR::STM32SPI::mem_read_ = false

Definition at line 90 of file stm32_spi.hpp.

◆ read_buff_

RawData LibXR::STM32SPI::read_buff_

Definition at line 88 of file stm32_spi.hpp.

◆ rw_op_

OperationRW LibXR::STM32SPI::rw_op_

Definition at line 86 of file stm32_spi.hpp.

◆ spi_handle_

SPI_HandleTypeDef* LibXR::STM32SPI::spi_handle_

Definition at line 80 of file stm32_spi.hpp.


The documentation for this class was generated from the following files: