libxr  1.0
Want to be the best embedded framework
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.
 
ConfigurationGetConfig ()
 获取 SPI 配置参数。Gets the SPI configuration parameters.
 
bool IsDoubleBuffer () const
 检查是否使用双缓冲区。Checks if double buffering is enabled.
 

Data Fields

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 STM32SPImap [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:110

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 485 of file stm32_spi.cpp.

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

◆ 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 629 of file stm32_spi.cpp.

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

342{
343 uint32_t need_read = read_data.size_;
344
345 if (spi_handle_->State != HAL_SPI_STATE_READY)
346 {
347 return ErrorCode::BUSY;
348 }
349
350 RawData rx = GetRxBuffer();
351 RawData tx = GetTxBuffer();
352
353 ASSERT(rx.size_ >= need_read + 1);
354 ASSERT(tx.size_ >= need_read + 1);
355
356 if (need_read + 1 > dma_enable_min_size_)
357 {
358 mem_read_ = true;
359 rw_op_ = op;
360 if (op.type == OperationRW::OperationType::BLOCK)
361 {
362 block_wait_.Start(*op.data.sem_info.sem);
363 }
364
365 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
366 Memory::FastSet(txb, 0, need_read + 1);
367 txb[0] = static_cast<uint8_t>(reg | 0x80);
368 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
369 read_buff_ = read_data;
370
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);
374
375 if (st != HAL_OK)
376 {
377 if (op.type == OperationRW::OperationType::BLOCK)
378 {
379 block_wait_.Cancel();
380 }
381 return ErrorCode::BUSY;
382 }
383
384 op.MarkAsRunning();
385 if (op.type == OperationRW::OperationType::BLOCK)
386 {
387 return block_wait_.Wait(op.data.sem_info.timeout);
388 }
389 return ErrorCode::OK;
390 }
391
392 mem_read_ = false;
393 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
394 Memory::FastSet(txb, 0, need_read + 1);
395 txb[0] = static_cast<uint8_t>(reg | 0x80);
396 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
397
398 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
399 static_cast<uint8_t*>(rx.addr_), need_read + 1,
400 20) == HAL_OK)
402 : ErrorCode::BUSY;
403
404 if (ans == ErrorCode::OK)
405 {
406 uint8_t* rxb = reinterpret_cast<uint8_t*>(rx.addr_);
407 Memory::FastCopy(read_data.addr_, rxb + 1, need_read);
408 }
409 SwitchBuffer();
410
411 if (op.type != OperationRW::OperationType::BLOCK)
412 {
413 op.UpdateStatus(in_isr, ans);
414 }
415 return ans;
416}
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
Definition libxr_mem.cpp:5
可写原始数据视图 / 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:306
void SwitchBuffer()
切换缓冲区。Switches the buffer.
Definition spi.hpp:337
RawData GetTxBuffer()
获取发送数据的缓冲区。Gets the buffer for storing data to be sent.
Definition spi.hpp:322
ErrorCode
定义错误码枚举
@ BUSY
忙碌 | Busy
@ OK
操作成功 | Operation successful
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
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 418 of file stm32_spi.cpp.

420{
421 uint32_t need_write = write_data.size_;
422
423 if (spi_handle_->State != HAL_SPI_STATE_READY)
424 {
425 return ErrorCode::BUSY;
426 }
427
428 RawData tx = GetTxBuffer();
429 ASSERT(tx.size_ >= need_write + 1);
430
431 if (need_write + 1 > dma_enable_min_size_)
432 {
433 mem_read_ = false;
434 rw_op_ = op;
435 if (op.type == OperationRW::OperationType::BLOCK)
436 {
437 block_wait_.Start(*op.data.sem_info.sem);
438 }
439
440 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
441 txb[0] = static_cast<uint8_t>(reg & 0x7F);
442 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
443 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
444 read_buff_ = {nullptr, 0};
445
446 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
447 spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write + 1);
448
449 if (st != HAL_OK)
450 {
451 if (op.type == OperationRW::OperationType::BLOCK)
452 {
453 block_wait_.Cancel();
454 }
455 return ErrorCode::BUSY;
456 }
457
458 op.MarkAsRunning();
459 if (op.type == OperationRW::OperationType::BLOCK)
460 {
461 return block_wait_.Wait(op.data.sem_info.timeout);
462 }
463 return ErrorCode::OK;
464 }
465
466 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
467 txb[0] = static_cast<uint8_t>(reg & 0x7F);
468 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
469 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
470
471 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
472 need_write + 1, 20) == HAL_OK)
474 : ErrorCode::BUSY;
475
476 SwitchBuffer();
477
478 if (op.type != OperationRW::OperationType::BLOCK)
479 {
480 op.UpdateStatus(in_isr, ans);
481 }
482 return ans;
483}
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()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:208
constexpr auto max(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最大值

◆ 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 ASSERT(ok);
329 if (!ok)
330 {
332 }
333
334 spi_handle_->Init.BaudRatePrescaler = hal_presc;
335
336 GetConfig() = config;
337
338 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
339}
@ 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:396
@ NOT_SUPPORT
不支持 | Not supported
ClockPhase clock_phase
SPI 时钟相位。SPI clock phase.
Definition spi.hpp:88
Prescaler prescaler
SPI 分频系数。SPI prescaler.
Definition spi.hpp:89
ClockPolarity clock_polarity
SPI 时钟极性。SPI clock polarity.
Definition spi.hpp:86

◆ 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 658 of file stm32_spi.cpp.

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

Field 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: