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
 

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

73 : SPI(rx, tx),
74 spi_handle_(spi_handle),
75 id_(STM32_SPI_GetID(spi_handle_->Instance)),
76 dma_enable_min_size_(dma_enable_min_size)
77{
78 ASSERT(id_ != STM32_SPI_ID_ERROR);
79
80 map[id_] = this;
81}
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 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 344 of file stm32_spi.cpp.

345{
346 uint32_t need_read = read_data.size_;
347
348 if (spi_handle_->State != HAL_SPI_STATE_READY)
349 {
350 return ErrorCode::BUSY;
351 }
352
353 RawData rx = GetRxBuffer();
354 RawData tx = GetTxBuffer();
355
356 ASSERT(rx.size_ >= need_read + 1);
357 ASSERT(tx.size_ >= need_read + 1);
358
359 if (need_read + 1 > dma_enable_min_size_)
360 {
361 mem_read_ = true;
362 rw_op_ = op;
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#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
368 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
369 static_cast<int32_t>(need_read + 1));
370#endif
371 read_buff_ = read_data;
372
373 HAL_StatusTypeDef st =
374 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
375 static_cast<uint8_t*>(rx.addr_), need_read + 1);
376
377 if (st != HAL_OK)
378 {
379 return ErrorCode::BUSY;
380 }
381
382 op.MarkAsRunning();
383 if (op.type == OperationRW::OperationType::BLOCK)
384 {
385 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
386 }
387 return ErrorCode::OK;
388 }
389
390 mem_read_ = false;
391 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
392 Memory::FastSet(txb, 0, need_read + 1);
393 txb[0] = static_cast<uint8_t>(reg | 0x80);
394#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
395 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
396 static_cast<int32_t>(need_read + 1));
397#endif
398
399 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
400 static_cast<uint8_t*>(rx.addr_), need_read + 1,
401 20) == HAL_OK)
402 ? ErrorCode::OK
403 : ErrorCode::BUSY;
404
405 if (ans == ErrorCode::OK)
406 {
407 uint8_t* rxb = reinterpret_cast<uint8_t*>(rx.addr_);
408 Memory::FastCopy(read_data.addr_, rxb + 1, need_read);
409 }
410 SwitchBuffer();
411
412 if (op.type != OperationRW::OperationType::BLOCK)
413 {
414 op.UpdateStatus(in_isr, ans);
415 }
416 return ans;
417}
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:3
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
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

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

421{
422 uint32_t need_write = write_data.size_;
423
424 if (spi_handle_->State != HAL_SPI_STATE_READY)
425 {
426 return ErrorCode::BUSY;
427 }
428
429 RawData tx = GetTxBuffer();
430 ASSERT(tx.size_ >= need_write + 1);
431
432 if (need_write + 1 > dma_enable_min_size_)
433 {
434 mem_read_ = false;
435 rw_op_ = op;
436
437 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
438 txb[0] = static_cast<uint8_t>(reg & 0x7F);
439 Memory::FastCopy(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));
443#endif
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 return ErrorCode::BUSY;
452 }
453
454 op.MarkAsRunning();
455 if (op.type == OperationRW::OperationType::BLOCK)
456 {
457 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
458 }
459 return ErrorCode::OK;
460 }
461
462 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
463 txb[0] = static_cast<uint8_t>(reg & 0x7F);
464 Memory::FastCopy(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));
468#endif
469
470 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
471 need_write + 1, 20) == HAL_OK)
472 ? ErrorCode::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_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).

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

85{
86 uint32_t need_write = max(write_data.size_, read_data.size_);
87
88 RawData rx = GetRxBuffer();
89 RawData tx = GetTxBuffer();
90
91 if (rx.size_ > 0)
92 {
93 ASSERT(need_write <= rx.size_);
94 }
95 if (tx.size_ > 0)
96 {
97 ASSERT(need_write <= tx.size_);
98 }
99
100 if (spi_handle_->State != HAL_SPI_STATE_READY)
101 {
102 return ErrorCode::BUSY;
103 }
104
105 mem_read_ = false;
106
107 if (need_write > dma_enable_min_size_)
108 {
109 rw_op_ = op;
110
111 HAL_StatusTypeDef st = HAL_OK;
112
113 if (write_data.size_ > 0 && read_data.size_ > 0)
114 {
115 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
116 if (write_data.size_ < need_write)
117 {
118 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
119 need_write - write_data.size_);
120 }
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));
124#endif
125 read_buff_ = read_data;
126
127 st = HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
128 static_cast<uint8_t*>(rx.addr_), need_write);
129 }
130 else if (write_data.size_ > 0)
131 {
132 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
133 if (write_data.size_ < need_write)
134 {
135 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
136 need_write - write_data.size_);
137 }
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));
141#endif
142 read_buff_ = {nullptr, 0};
143
144 st = HAL_SPI_Transmit_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write);
145 }
146 else if (read_data.size_ > 0)
147 {
148 read_buff_ = read_data;
149
150 st = HAL_SPI_Receive_DMA(spi_handle_, static_cast<uint8_t*>(rx.addr_),
151 read_data.size_);
152 }
153 else
154 {
155 if (op.type != OperationRW::OperationType::BLOCK)
156 {
157 op.UpdateStatus(in_isr, ErrorCode::OK);
158 }
159 return ErrorCode::OK;
160 }
161
162 if (st != HAL_OK)
163 {
164 return ErrorCode::BUSY;
165 }
166
167 op.MarkAsRunning();
168 if (op.type == OperationRW::OperationType::BLOCK)
169 {
170 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
171 }
172 return ErrorCode::OK;
173 }
174
175 ErrorCode ans = ErrorCode::OK;
176
177 if (write_data.size_ > 0 && read_data.size_ > 0)
178 {
179 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
180 if (write_data.size_ < need_write)
181 {
182 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
183 need_write - write_data.size_);
184 }
185#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
186 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
187 static_cast<int32_t>(need_write));
188#endif
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)
192 ? ErrorCode::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)
205 ? ErrorCode::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#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
218 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
219 static_cast<int32_t>(need_write));
220#endif
221 ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
222 write_data.size_, 20) == HAL_OK)
223 ? ErrorCode::OK
224 : ErrorCode::BUSY;
225
226 SwitchBuffer();
227 }
228 else
229 {
230 if (op.type != OperationRW::OperationType::BLOCK)
231 {
232 op.UpdateStatus(in_isr, ErrorCode::OK);
233 }
234 return ErrorCode::OK;
235 }
236
237 if (op.type != OperationRW::OperationType::BLOCK)
238 {
239 op.UpdateStatus(in_isr, ans);
240 }
241 return ans;
242}
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:212
constexpr auto max(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最大值

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

245{
246 switch (config.clock_polarity)
247 {
249 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
250 break;
252 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
253 break;
254 }
255
256 switch (config.clock_phase)
257 {
259 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
260 break;
262 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
263 break;
264 }
265
266 bool ok = true;
267 uint32_t hal_presc = 0;
268
269 switch (config.prescaler)
270 {
271#ifdef SPI_BAUDRATEPRESCALER_1
272 case Prescaler::DIV_1:
273 hal_presc = SPI_BAUDRATEPRESCALER_1;
274 break;
275#endif
276#ifdef SPI_BAUDRATEPRESCALER_2
277 case Prescaler::DIV_2:
278 hal_presc = SPI_BAUDRATEPRESCALER_2;
279 break;
280#endif
281#ifdef SPI_BAUDRATEPRESCALER_4
282 case Prescaler::DIV_4:
283 hal_presc = SPI_BAUDRATEPRESCALER_4;
284 break;
285#endif
286#ifdef SPI_BAUDRATEPRESCALER_8
287 case Prescaler::DIV_8:
288 hal_presc = SPI_BAUDRATEPRESCALER_8;
289 break;
290#endif
291#ifdef SPI_BAUDRATEPRESCALER_16
293 hal_presc = SPI_BAUDRATEPRESCALER_16;
294 break;
295#endif
296#ifdef SPI_BAUDRATEPRESCALER_32
298 hal_presc = SPI_BAUDRATEPRESCALER_32;
299 break;
300#endif
301#ifdef SPI_BAUDRATEPRESCALER_64
303 hal_presc = SPI_BAUDRATEPRESCALER_64;
304 break;
305#endif
306#ifdef SPI_BAUDRATEPRESCALER_128
308 hal_presc = SPI_BAUDRATEPRESCALER_128;
309 break;
310#endif
311#ifdef SPI_BAUDRATEPRESCALER_256
313 hal_presc = SPI_BAUDRATEPRESCALER_256;
314 break;
315#endif
316#ifdef SPI_BAUDRATEPRESCALER_512
318 hal_presc = SPI_BAUDRATEPRESCALER_512;
319 break;
320#endif
321#ifdef SPI_BAUDRATEPRESCALER_1024
323 hal_presc = SPI_BAUDRATEPRESCALER_1024;
324 break;
325#endif
326 default:
327 ok = false;
328 break;
329 }
330
331 ASSERT(ok);
332 if (!ok)
333 {
334 return ErrorCode::NOT_SUPPORT;
335 }
336
337 spi_handle_->Init.BaudRatePrescaler = hal_presc;
338
339 GetConfig() = config;
340
341 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
342}
@ 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
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 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
682#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
683 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_), static_cast<int32_t>(xfer));
684 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t*>(rx.addr_),
685 static_cast<int32_t>(xfer));
686#endif
687
688 HAL_StatusTypeDef st =
689 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
690 static_cast<uint8_t*>(rx.addr_), xfer);
691
692 if (st != HAL_OK)
693 {
694 return ErrorCode::BUSY;
695 }
696
697 op.MarkAsRunning();
698 if (op.type == OperationRW::OperationType::BLOCK)
699 {
700 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
701 }
702 return ErrorCode::OK;
703 }
704
705 ErrorCode ans =
706 (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
707 static_cast<uint8_t*>(rx.addr_), xfer, 20) == HAL_OK)
708 ? ErrorCode::OK
709 : ErrorCode::BUSY;
710
711#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
712 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t*>(rx.addr_),
713 static_cast<int32_t>(xfer));
714#endif
715
716 SwitchBuffer();
717
718 if (op.type != OperationRW::OperationType::BLOCK)
719 {
720 op.UpdateStatus(in_isr, ans);
721 }
722 return ans;
723}

Field Documentation

◆ 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 92 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: