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)
338 block_wait_.Start(*op.
data.sem_info.sem);
340 StartDmaDuplex(NEED);
343 if (op.
type == OperationRW::OperationType::BLOCK)
345 return block_wait_.Wait(op.
data.sem_info.timeout);
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)
424 block_wait_.Start(*op.
data.sem_info.sem);
426 StartDmaDuplex(TOTAL);
428 if (op.
type == OperationRW::OperationType::BLOCK)
430 return block_wait_.Wait(op.
data.sem_info.timeout);
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)
494 block_wait_.Start(*op.
data.sem_info.sem);
496 StartDmaDuplex(TOTAL);
499 if (op.
type == OperationRW::OperationType::BLOCK)
501 return block_wait_.Wait(op.
data.sem_info.timeout);
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)
667 block_wait_.Start(*op.
data.sem_info.sem);
669 StartDmaDuplex(
static_cast<uint32_t
>(size));
672 if (op.
type == OperationRW::OperationType::BLOCK)
674 return block_wait_.Wait(op.
data.sem_info.timeout);
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:
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.
常量原始数据封装类。 A class for encapsulating constant raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
const void * addr_
数据存储地址(常量)。 The storage address of the data (constant).
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
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
串行外设接口(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.
@ 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.