7#include "ch32_gpio.hpp"
11CH32SPI* CH32SPI::map_[CH32_SPI_NUMBER] = {
nullptr};
13bool CH32SPI::MapEnumToCH32Prescaler(
SPI::Prescaler p, uint16_t& out)
17#if defined(SPI_BaudRatePrescaler_2)
19 out = SPI_BaudRatePrescaler_2;
22#if defined(SPI_BaudRatePrescaler_4)
24 out = SPI_BaudRatePrescaler_4;
27#if defined(SPI_BaudRatePrescaler_8)
29 out = SPI_BaudRatePrescaler_8;
32#if defined(SPI_BaudRatePrescaler_16)
34 out = SPI_BaudRatePrescaler_16;
37#if defined(SPI_BaudRatePrescaler_32)
39 out = SPI_BaudRatePrescaler_32;
42#if defined(SPI_BaudRatePrescaler_64)
44 out = SPI_BaudRatePrescaler_64;
47#if defined(SPI_BaudRatePrescaler_128)
49 out = SPI_BaudRatePrescaler_128;
52#if defined(SPI_BaudRatePrescaler_256)
54 out = SPI_BaudRatePrescaler_256;
63 uint16_t sck_pin, GPIO_TypeDef* miso_port, uint16_t miso_pin,
64 GPIO_TypeDef* mosi_port, uint16_t mosi_pin, uint32_t pin_remap,
65 bool master_mode,
bool firstbit_msb, uint16_t prescaler,
67 :
SPI(dma_rx, dma_tx),
68 instance_(ch32_spi_get_instance_id(id)),
69 dma_rx_channel_(CH32_SPI_RX_DMA_CHANNEL_MAP[id]),
70 dma_tx_channel_(CH32_SPI_TX_DMA_CHANNEL_MAP[id]),
72 dma_enable_min_size_(dma_enable_min_size),
73 mode_(master_mode ? SPI_Mode_Master : SPI_Mode_Slave),
74 datasize_(SPI_DataSize_8b),
75 firstbit_(firstbit_msb ? SPI_FirstBit_MSB : SPI_FirstBit_LSB),
76 prescaler_(prescaler),
79 miso_port_(miso_port),
81 mosi_port_(mosi_port),
84 ASSERT(instance_ !=
nullptr);
90 if (CH32_SPI_APB_MAP[
id] == 1)
92 RCC_APB1PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[
id], ENABLE);
94 else if (CH32_SPI_APB_MAP[
id] == 2)
96 RCC_APB2PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[
id], ENABLE);
102 RCC_AHBPeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP_DMA[
id], ENABLE);
107 GPIO_InitTypeDef gpio = {};
108 gpio.GPIO_Speed = GPIO_Speed_50MHz;
112 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(
sck_port_), ENABLE);
113 if (
mode_ == SPI_Mode_Master)
115 gpio.GPIO_Pin = sck_pin_;
116 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
120 gpio.GPIO_Pin = sck_pin_;
121 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
127 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(miso_port_), ENABLE);
128 if (
mode_ == SPI_Mode_Master)
130 gpio.GPIO_Pin = miso_pin_;
131 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
135 gpio.GPIO_Pin = miso_pin_;
136 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
138 GPIO_Init(miso_port_, &gpio);
142 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(mosi_port_), ENABLE);
143 if (
mode_ == SPI_Mode_Master)
145 gpio.GPIO_Pin = mosi_pin_;
146 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
150 gpio.GPIO_Pin = mosi_pin_;
151 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
153 GPIO_Init(mosi_port_, &gpio);
157 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
158 GPIO_PinRemapConfig(pin_remap, ENABLE);
165 SPI_InitTypeDef init = {};
166 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
167 init.SPI_Mode =
mode_;
176 init.SPI_CRCPolynomial = 7;
178 SPI_Init(instance_, &init);
179 SPI_Cmd(instance_, ENABLE);
188 ch32_dma_callback_t cb = [](
void* arg)
190 ch32_dma_register_callback(ch32_dma_get_id(dma_rx_channel_), cb,
this);
192 DMA_InitTypeDef di = {};
193 DMA_DeInit(dma_rx_channel_);
194 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
195 di.DMA_MemoryBaseAddr = (uint32_t)dma_rx.
addr_;
196 di.DMA_DIR = DMA_DIR_PeripheralSRC;
197 di.DMA_BufferSize = 0;
198 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
199 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
200 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
201 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
202 di.DMA_Mode = DMA_Mode_Normal;
203 di.DMA_Priority = DMA_Priority_High;
204 di.DMA_M2M = DMA_M2M_Disable;
205 DMA_Init(dma_rx_channel_, &di);
206 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
207 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_rx_channel_)]);
212 ch32_dma_callback_t cb = [](
void* arg)
213 {
reinterpret_cast<CH32SPI*
>(arg)->TxDmaIRQHandler(); };
214 ch32_dma_register_callback(ch32_dma_get_id(dma_tx_channel_), cb,
this);
216 DMA_InitTypeDef di = {};
217 DMA_DeInit(dma_tx_channel_);
218 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
219 di.DMA_MemoryBaseAddr = 0;
220 di.DMA_DIR = DMA_DIR_PeripheralDST;
221 di.DMA_BufferSize = 0;
222 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
223 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
224 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
225 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
226 di.DMA_Mode = DMA_Mode_Normal;
227 di.DMA_Priority = DMA_Priority_VeryHigh;
228 di.DMA_M2M = DMA_M2M_Disable;
229 DMA_Init(dma_tx_channel_, &di);
230 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
231 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_tx_channel_)]);
246 uint16_t ch32_presc = 0;
247 if (!MapEnumToCH32Prescaler(config.
prescaler, ch32_presc))
253 SPI_Cmd(instance_, DISABLE);
254 SPI_I2S_DeInit(instance_);
256 SPI_InitTypeDef init = {};
257 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
258 init.SPI_Mode =
mode_;
265 init.SPI_BaudRatePrescaler = ch32_presc;
267 init.SPI_CRCPolynomial = 7;
269 SPI_Init(instance_, &init);
270 SPI_Cmd(instance_, ENABLE);
281 for (uint32_t i = 0; i < len; ++i)
283 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_TXE) == RESET)
286 SPI_I2S_SendData(instance_, tx ? tx[i] : 0x00);
288 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_RXNE) == RESET)
291 uint16_t d = SPI_I2S_ReceiveData(instance_);
294 rx[i] =
static_cast<uint8_t
>(d & 0xff);
303 const uint32_t RSZ = read_data.
size_;
304 const uint32_t WSZ = write_data.
size_;
305 const uint32_t NEED = (RSZ > WSZ) ? RSZ : WSZ;
309 if (op.
type != OperationRW::OperationType::BLOCK)
324 ASSERT(rx.
size_ >= NEED);
325 ASSERT(tx.
size_ >= NEED);
327 if (NEED > dma_enable_min_size_)
330 read_buff_ = read_data;
334 PrepareTxBuffer(write_data, NEED);
336 if (op.
type == OperationRW::OperationType::BLOCK)
340 StartDmaDuplex(NEED);
343 if (op.
type == OperationRW::OperationType::BLOCK)
352 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
353 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
378 if (op.
type != OperationRW::OperationType::BLOCK)
388 const uint32_t N = read_data.
size_;
391 if (op.
type != OperationRW::OperationType::BLOCK)
406 ASSERT(rx.
size_ >= N + 1);
407 ASSERT(tx.
size_ >= N + 1);
409 const uint32_t TOTAL = N + 1;
411 if (TOTAL > dma_enable_min_size_)
413 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
414 txp[0] =
static_cast<uint8_t
>(reg | 0x80);
418 read_buff_ = read_data;
422 if (op.
type == OperationRW::OperationType::BLOCK)
426 StartDmaDuplex(TOTAL);
428 if (op.
type == OperationRW::OperationType::BLOCK)
437 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
438 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
439 txp[0] =
static_cast<uint8_t
>(reg | 0x80);
447 if (op.
type != OperationRW::OperationType::BLOCK)
458 const uint32_t N = write_data.
size_;
461 if (op.
type != OperationRW::OperationType::BLOCK)
477 ASSERT(tx.
size_ >= N + 1);
479 const uint32_t TOTAL = N + 1;
481 if (TOTAL > dma_enable_min_size_)
483 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
484 txp[0] =
static_cast<uint8_t
>(reg & 0x7F);
488 read_buff_ = {
nullptr, 0};
492 if (op.
type == OperationRW::OperationType::BLOCK)
496 StartDmaDuplex(TOTAL);
499 if (op.
type == OperationRW::OperationType::BLOCK)
508 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
509 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
510 txp[0] =
static_cast<uint8_t
>(reg & 0x7F);
517 if (op.
type != OperationRW::OperationType::BLOCK)
525void CH32SPI::PrepareTxBuffer(
ConstRawData write_data, uint32_t need_len, uint32_t prefix,
529 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
531 if (write_data.
size_ > 0)
533 const uint32_t COPY =
534 (write_data.
size_ > need_len - prefix) ? (need_len - prefix) : write_data.
size_;
536 if (prefix + COPY < need_len)
547void CH32SPI::StartDmaDuplex(uint32_t count)
552 dma_rx_channel_->MADDR =
reinterpret_cast<uint32_t
>(rx.
addr_);
553 dma_rx_channel_->CNTR = count;
555 dma_tx_channel_->MADDR =
reinterpret_cast<uint32_t
>(tx.
addr_);
556 dma_tx_channel_->CNTR = count;
558 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, ENABLE);
559 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, ENABLE);
561 DMA_Cmd(dma_rx_channel_, ENABLE);
562 DMA_Cmd(dma_tx_channel_, ENABLE);
565void CH32SPI::StopDma()
567 DMA_Cmd(dma_tx_channel_, DISABLE);
568 DMA_Cmd(dma_rx_channel_, DISABLE);
573 if (DMA_GetITStatus(CH32_SPI_RX_DMA_IT_MAP[id_]) == RESET)
578 DMA_ClearITPendingBit(CH32_SPI_RX_DMA_IT_MAP[id_]);
580 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, DISABLE);
581 DMA_Cmd(dma_rx_channel_, DISABLE);
589 const bool has_user_read_copy = (read_buff_.
size_ > 0);
590 if (has_user_read_copy)
593 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
602 read_buff_.
size_ = 0;
608 if (
rw_op_.
type == OperationRW::OperationType::BLOCK)
618void CH32SPI::TxDmaIRQHandler()
620 if (DMA_GetITStatus(CH32_SPI_TX_DMA_IT_MAP[id_]) == RESET)
624 DMA_ClearITPendingBit(CH32_SPI_TX_DMA_IT_MAP[id_]);
626 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, DISABLE);
627 DMA_Cmd(dma_tx_channel_, DISABLE);
646 if (op.
type != OperationRW::OperationType::BLOCK)
655 ASSERT(rx.
size_ >= size);
656 ASSERT(tx.
size_ >= size);
658 if (size > dma_enable_min_size_)
661 read_buff_ = {
nullptr, 0};
665 if (op.
type == OperationRW::OperationType::BLOCK)
669 StartDmaDuplex(
static_cast<uint32_t
>(size));
672 if (op.
type == OperationRW::OperationType::BLOCK)
682 static_cast<const uint8_t*
>(tx.
addr_),
static_cast<uint32_t
>(size));
686 if (op.
type != OperationRW::OperationType::BLOCK)
697 RCC_ClocksTypeDef clocks{};
698 RCC_GetClocksFreq(&clocks);
700 if (CH32_SPI_APB_MAP[id_] == 2)
702 return clocks.PCLK2_Frequency;
704 else if (CH32_SPI_APB_MAP[id_] == 1)
706 return clocks.PCLK1_Frequency;
715#if defined(SPI_BaudRatePrescaler_1024)
717#elif defined(SPI_BaudRatePrescaler_512)
719#elif defined(SPI_BaudRatePrescaler_256)
721#elif defined(SPI_BaudRatePrescaler_128)
723#elif defined(SPI_BaudRatePrescaler_64)
725#elif defined(SPI_BaudRatePrescaler_32)
727#elif defined(SPI_BaudRatePrescaler_16)
729#elif defined(SPI_BaudRatePrescaler_8)
731#elif defined(SPI_BaudRatePrescaler_4)
733#elif defined(SPI_BaudRatePrescaler_2)
744#if defined(SPI_BaudRatePrescaler_2)
745 case SPI_BaudRatePrescaler_2:
748#if defined(SPI_BaudRatePrescaler_4)
749 case SPI_BaudRatePrescaler_4:
752#if defined(SPI_BaudRatePrescaler_8)
753 case SPI_BaudRatePrescaler_8:
756#if defined(SPI_BaudRatePrescaler_16)
757 case SPI_BaudRatePrescaler_16:
760#if defined(SPI_BaudRatePrescaler_32)
761 case SPI_BaudRatePrescaler_32:
764#if defined(SPI_BaudRatePrescaler_64)
765 case SPI_BaudRatePrescaler_64:
768#if defined(SPI_BaudRatePrescaler_128)
769 case SPI_BaudRatePrescaler_128:
772#if defined(SPI_BaudRatePrescaler_256)
773 case SPI_BaudRatePrescaler_256:
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.
CH32 SPI 驱动实现 / CH32 SPI driver implementation.
void RxDmaIRQHandler()
DMA 中断回调 / DMA interrupt callbacks.
ErrorCode PollingTransfer(uint8_t *rx, const uint8_t *tx, uint32_t len)
轮询传输辅助函数 / Polling transfer helper
OperationRW rw_op_
运行时状态 / Runtime state
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 SetConfig(SPI::Configuration config) override
设置 SPI 配置参数 / Sets SPI configuration parameters.
SPI::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 接口实现 / SPI interface overrides.
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.
uint16_t mode_
SPI 寄存器配置缓存 / Cached SPI register configuration.
uint16_t prescaler_
SPI_BaudRatePrescaler_x.
uint16_t datasize_
SPI_DataSize_8b by default.
uint16_t firstbit_
SPI_FirstBit_MSB / SPI_FirstBit_LSB.
CH32SPI(ch32_spi_id_t id, RawData dma_rx, RawData dma_tx, GPIO_TypeDef *sck_port, uint16_t sck_pin, GPIO_TypeDef *miso_port, uint16_t miso_pin, GPIO_TypeDef *mosi_port, uint16_t mosi_pin, uint32_t pin_remap=0, bool master_mode=true, bool firstbit_msb=true, uint16_t prescaler=SPI_BaudRatePrescaler_64, uint32_t dma_enable_min_size=3, SPI::Configuration config={SPI::ClockPolarity::LOW, SPI::ClockPhase::EDGE_1})
构造 SPI 对象 / Construct SPI object
ErrorCode Transfer(size_t size, OperationRW &op, bool in_isr) override
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
GPIO_TypeDef * sck_port_
GPIO 配置 / GPIO configuration.
只读原始数据视图 / 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_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.
@ 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.
Configuration & GetConfig()
获取 SPI 配置参数 / Gets the SPI configuration parameters.
LibXR 命名空间 / LibXR namespace.
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ NOT_SUPPORT
不支持 / Not supported
@ OK
操作成功 / Operation successful
存储 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.