6#include "ch32_gpio.hpp"
10CH32SPI* CH32SPI::map[CH32_SPI_NUMBER] = {
nullptr};
12bool CH32SPI::MapEnumToCH32Prescaler(
SPI::Prescaler p, uint16_t& out)
16#if defined(SPI_BaudRatePrescaler_2)
18 out = SPI_BaudRatePrescaler_2;
21#if defined(SPI_BaudRatePrescaler_4)
23 out = SPI_BaudRatePrescaler_4;
26#if defined(SPI_BaudRatePrescaler_8)
28 out = SPI_BaudRatePrescaler_8;
31#if defined(SPI_BaudRatePrescaler_16)
33 out = SPI_BaudRatePrescaler_16;
36#if defined(SPI_BaudRatePrescaler_32)
38 out = SPI_BaudRatePrescaler_32;
41#if defined(SPI_BaudRatePrescaler_64)
43 out = SPI_BaudRatePrescaler_64;
46#if defined(SPI_BaudRatePrescaler_128)
48 out = SPI_BaudRatePrescaler_128;
51#if defined(SPI_BaudRatePrescaler_256)
53 out = SPI_BaudRatePrescaler_256;
61CH32SPI::CH32SPI(ch32_spi_id_t
id,
RawData dma_rx,
RawData dma_tx, GPIO_TypeDef* sck_port,
62 uint16_t sck_pin, GPIO_TypeDef* miso_port, uint16_t miso_pin,
63 GPIO_TypeDef* mosi_port, uint16_t mosi_pin, uint32_t pin_remap,
64 bool master_mode,
bool firstbit_msb, uint16_t prescaler,
66 :
SPI(dma_rx, dma_tx),
67 instance_(CH32_SPI_GetInstanceID(id)),
68 dma_rx_channel_(CH32_SPI_RX_DMA_CHANNEL_MAP[id]),
69 dma_tx_channel_(CH32_SPI_TX_DMA_CHANNEL_MAP[id]),
71 dma_enable_min_size_(dma_enable_min_size),
72 mode_(master_mode ? SPI_Mode_Master : SPI_Mode_Slave),
73 datasize_(SPI_DataSize_8b),
74 firstbit_(firstbit_msb ? SPI_FirstBit_MSB : SPI_FirstBit_LSB),
75 prescaler_(prescaler),
78 miso_port_(miso_port),
80 mosi_port_(mosi_port),
83 ASSERT(instance_ !=
nullptr);
88 if (CH32_SPI_APB_MAP[
id] == 1)
90 RCC_APB1PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[
id], ENABLE);
92 else if (CH32_SPI_APB_MAP[
id] == 2)
94 RCC_APB2PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[
id], ENABLE);
100 RCC_AHBPeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP_DMA[
id], ENABLE);
104 GPIO_InitTypeDef gpio = {};
105 gpio.GPIO_Speed = GPIO_Speed_50MHz;
108 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(sck_port_), ENABLE);
109 if (mode_ == SPI_Mode_Master)
111 gpio.GPIO_Pin = sck_pin_;
112 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
116 gpio.GPIO_Pin = sck_pin_;
117 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
119 GPIO_Init(sck_port_, &gpio);
122 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(miso_port_), ENABLE);
123 if (mode_ == SPI_Mode_Master)
125 gpio.GPIO_Pin = miso_pin_;
126 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
130 gpio.GPIO_Pin = miso_pin_;
131 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
133 GPIO_Init(miso_port_, &gpio);
136 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(mosi_port_), ENABLE);
137 if (mode_ == SPI_Mode_Master)
139 gpio.GPIO_Pin = mosi_pin_;
140 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
144 gpio.GPIO_Pin = mosi_pin_;
145 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
147 GPIO_Init(mosi_port_, &gpio);
151 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
152 GPIO_PinRemapConfig(pin_remap, ENABLE);
158 SPI_InitTypeDef init = {};
159 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
160 init.SPI_Mode = mode_;
161 init.SPI_DataSize = datasize_;
163 (config.
clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
165 (config.
clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
167 init.SPI_BaudRatePrescaler = prescaler_;
168 init.SPI_FirstBit = firstbit_;
169 init.SPI_CRCPolynomial = 7;
171 SPI_Init(instance_, &init);
172 SPI_Cmd(instance_, ENABLE);
179 ch32_dma_callback_t cb = [](
void* arg)
180 {
reinterpret_cast<CH32SPI*
>(arg)->RxDmaIRQHandler(); };
181 CH32_DMA_RegisterCallback(CH32_DMA_GetID(dma_rx_channel_), cb,
this);
183 DMA_InitTypeDef di = {};
184 DMA_DeInit(dma_rx_channel_);
185 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
186 di.DMA_MemoryBaseAddr = (uint32_t)dma_rx.
addr_;
187 di.DMA_DIR = DMA_DIR_PeripheralSRC;
188 di.DMA_BufferSize = 0;
189 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
190 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
191 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
192 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
193 di.DMA_Mode = DMA_Mode_Normal;
194 di.DMA_Priority = DMA_Priority_High;
195 di.DMA_M2M = DMA_M2M_Disable;
196 DMA_Init(dma_rx_channel_, &di);
197 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
198 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_rx_channel_)]);
202 ch32_dma_callback_t cb = [](
void* arg)
203 {
reinterpret_cast<CH32SPI*
>(arg)->TxDmaIRQHandler(); };
204 CH32_DMA_RegisterCallback(CH32_DMA_GetID(dma_tx_channel_), cb,
this);
206 DMA_InitTypeDef di = {};
207 DMA_DeInit(dma_tx_channel_);
208 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
209 di.DMA_MemoryBaseAddr = 0;
210 di.DMA_DIR = DMA_DIR_PeripheralDST;
211 di.DMA_BufferSize = 0;
212 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
213 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
214 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
215 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
216 di.DMA_Mode = DMA_Mode_Normal;
217 di.DMA_Priority = DMA_Priority_VeryHigh;
218 di.DMA_M2M = DMA_M2M_Disable;
219 DMA_Init(dma_tx_channel_, &di);
220 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
221 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_tx_channel_)]);
226 GetConfig() = config;
227 GetConfig().
prescaler = MapCH32PrescalerToEnum(prescaler_);
234 uint16_t ch32_presc = 0;
235 if (!MapEnumToCH32Prescaler(config.
prescaler, ch32_presc))
237 return ErrorCode::NOT_SUPPORT;
241 SPI_Cmd(instance_, DISABLE);
242 SPI_I2S_DeInit(instance_);
244 SPI_InitTypeDef init = {};
245 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
246 init.SPI_Mode = mode_;
247 init.SPI_DataSize = datasize_;
253 init.SPI_BaudRatePrescaler = ch32_presc;
254 init.SPI_FirstBit = firstbit_;
255 init.SPI_CRCPolynomial = 7;
257 SPI_Init(instance_, &init);
258 SPI_Cmd(instance_, ENABLE);
261 prescaler_ = ch32_presc;
264 return ErrorCode::OK;
267ErrorCode CH32SPI::PollingTransfer(uint8_t* rx,
const uint8_t* tx, uint32_t len)
269 for (uint32_t i = 0; i < len; ++i)
271 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_TXE) == RESET)
274 SPI_I2S_SendData(instance_, tx ? tx[i] : 0x00);
276 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_RXNE) == RESET)
279 uint16_t d = SPI_I2S_ReceiveData(instance_);
280 if (rx) rx[i] =
static_cast<uint8_t
>(d & 0xff);
282 return ErrorCode::OK;
288 const uint32_t rsz = read_data.
size_;
289 const uint32_t wsz = write_data.
size_;
290 const uint32_t need = (rsz > wsz) ? rsz : wsz;
294 if (op.
type != OperationRW::OperationType::BLOCK)
296 return ErrorCode::OK;
299 if (DmaBusy())
return ErrorCode::BUSY;
304 ASSERT(rx.
size_ >= need);
305 ASSERT(tx.
size_ >= need);
307 if (need > dma_enable_min_size_)
310 read_buff_ = read_data;
314 PrepareTxBuffer(write_data, need);
316 StartDmaDuplex(need);
319 if (op.
type == OperationRW::OperationType::BLOCK)
321 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
323 return ErrorCode::OK;
328 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
329 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
334 memcpy(txp, write_data.
addr_, wsz);
335 if (need > wsz) memset(txp + wsz, 0x00, need - wsz);
339 memset(txp, 0x00, need);
342 ErrorCode ec = PollingTransfer(rxp, txp, need);
346 memcpy(read_data.
addr_, rxp, rsz);
351 if (op.
type != OperationRW::OperationType::BLOCK) op.
UpdateStatus(
false, ec);
358 const uint32_t n = read_data.
size_;
361 if (op.
type != OperationRW::OperationType::BLOCK)
363 return ErrorCode::OK;
366 if (DmaBusy())
return ErrorCode::BUSY;
371 ASSERT(rx.
size_ >= n + 1);
372 ASSERT(tx.
size_ >= n + 1);
374 const uint32_t total = n + 1;
376 if (total > dma_enable_min_size_)
378 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
379 txp[0] =
static_cast<uint8_t
>(reg | 0x80);
380 memset(txp + 1, 0x00, n);
383 read_buff_ = read_data;
387 StartDmaDuplex(total);
390 if (op.
type == OperationRW::OperationType::BLOCK)
392 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
394 return ErrorCode::OK;
399 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
400 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
401 txp[0] =
static_cast<uint8_t
>(reg | 0x80);
402 memset(txp + 1, 0x00, n);
404 ErrorCode ec = PollingTransfer(rxp, txp, total);
405 memcpy(read_data.
addr_, rxp + 1, n);
409 if (op.
type != OperationRW::OperationType::BLOCK) op.
UpdateStatus(
false, ec);
416 const uint32_t n = write_data.
size_;
419 if (op.
type != OperationRW::OperationType::BLOCK)
421 return ErrorCode::OK;
424 if (DmaBusy())
return ErrorCode::BUSY;
430 ASSERT(tx.
size_ >= n + 1);
432 const uint32_t total = n + 1;
434 if (total > dma_enable_min_size_)
436 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
437 txp[0] =
static_cast<uint8_t
>(reg & 0x7F);
438 memcpy(txp + 1, write_data.
addr_, n);
441 read_buff_ = {
nullptr, 0};
445 StartDmaDuplex(total);
448 if (op.
type == OperationRW::OperationType::BLOCK)
450 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
452 return ErrorCode::OK;
457 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
458 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
459 txp[0] =
static_cast<uint8_t
>(reg & 0x7F);
460 memcpy(txp + 1, write_data.
addr_, n);
462 ErrorCode ec = PollingTransfer(rxp, txp, total);
466 if (op.
type != OperationRW::OperationType::BLOCK) op.
UpdateStatus(
false, ec);
471void CH32SPI::PrepareTxBuffer(
ConstRawData write_data, uint32_t need_len, uint32_t prefix,
475 uint8_t* txp =
static_cast<uint8_t*
>(tx.
addr_);
477 if (write_data.
size_ > 0)
479 const uint32_t copy =
480 (write_data.
size_ > need_len - prefix) ? (need_len - prefix) : write_data.
size_;
481 memcpy(txp + prefix, write_data.
addr_, copy);
482 if (prefix + copy < need_len)
484 memset(txp + prefix + copy, dummy, need_len - prefix - copy);
489 memset(txp + prefix, dummy, need_len - prefix);
493void CH32SPI::StartDmaDuplex(uint32_t count)
498 dma_rx_channel_->MADDR =
reinterpret_cast<uint32_t
>(rx.
addr_);
499 dma_rx_channel_->CNTR = count;
501 dma_tx_channel_->MADDR =
reinterpret_cast<uint32_t
>(tx.
addr_);
502 dma_tx_channel_->CNTR = count;
504 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, ENABLE);
505 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, ENABLE);
507 DMA_Cmd(dma_rx_channel_, ENABLE);
508 DMA_Cmd(dma_tx_channel_, ENABLE);
511void CH32SPI::StopDma()
513 DMA_Cmd(dma_tx_channel_, DISABLE);
514 DMA_Cmd(dma_rx_channel_, DISABLE);
517void CH32SPI::RxDmaIRQHandler()
519 if (DMA_GetITStatus(CH32_SPI_RX_DMA_IT_MAP[id_]) == RESET)
return;
521 DMA_ClearITPendingBit(CH32_SPI_RX_DMA_IT_MAP[id_]);
523 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, DISABLE);
524 DMA_Cmd(dma_rx_channel_, DISABLE);
527 if (read_buff_.
size_ > 0)
530 uint8_t* rxp =
static_cast<uint8_t*
>(rx.
addr_);
533 memcpy(read_buff_.
addr_, rxp + 1, read_buff_.
size_);
537 memcpy(read_buff_.
addr_, rxp, read_buff_.
size_);
539 read_buff_.
size_ = 0;
548void CH32SPI::TxDmaIRQHandler()
550 if (DMA_GetITStatus(CH32_SPI_TX_DMA_IT_MAP[id_]) == RESET)
return;
551 DMA_ClearITPendingBit(CH32_SPI_TX_DMA_IT_MAP[id_]);
553 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, DISABLE);
554 DMA_Cmd(dma_tx_channel_, DISABLE);
560 if (DmaBusy())
return ErrorCode::BUSY;
564 if (op.
type != OperationRW::OperationType::BLOCK)
566 return ErrorCode::OK;
571 ASSERT(rx.
size_ >= size);
572 ASSERT(tx.
size_ >= size);
574 if (size > dma_enable_min_size_)
577 read_buff_ = {
nullptr, 0};
581 StartDmaDuplex(
static_cast<uint32_t
>(size));
584 if (op.
type == OperationRW::OperationType::BLOCK)
586 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
588 return ErrorCode::OK;
593 PollingTransfer(
static_cast<uint8_t*
>(rx.
addr_),
594 static_cast<const uint8_t*
>(tx.
addr_),
static_cast<uint32_t
>(size));
598 if (op.
type != OperationRW::OperationType::BLOCK) op.
UpdateStatus(
false, ec);
605 RCC_ClocksTypeDef clocks{};
606 RCC_GetClocksFreq(&clocks);
608 if (CH32_SPI_APB_MAP[id_] == 2)
610 return clocks.PCLK2_Frequency;
612 else if (CH32_SPI_APB_MAP[id_] == 1)
614 return clocks.PCLK1_Frequency;
622#if defined(SPI_BaudRatePrescaler_1024)
624#elif defined(SPI_BaudRatePrescaler_512)
626#elif defined(SPI_BaudRatePrescaler_256)
628#elif defined(SPI_BaudRatePrescaler_128)
630#elif defined(SPI_BaudRatePrescaler_64)
632#elif defined(SPI_BaudRatePrescaler_32)
634#elif defined(SPI_BaudRatePrescaler_16)
636#elif defined(SPI_BaudRatePrescaler_8)
638#elif defined(SPI_BaudRatePrescaler_4)
640#elif defined(SPI_BaudRatePrescaler_2)
651#if defined(SPI_BaudRatePrescaler_2)
652 case SPI_BaudRatePrescaler_2:
655#if defined(SPI_BaudRatePrescaler_4)
656 case SPI_BaudRatePrescaler_4:
659#if defined(SPI_BaudRatePrescaler_8)
660 case SPI_BaudRatePrescaler_8:
663#if defined(SPI_BaudRatePrescaler_16)
664 case SPI_BaudRatePrescaler_16:
667#if defined(SPI_BaudRatePrescaler_32)
668 case SPI_BaudRatePrescaler_32:
671#if defined(SPI_BaudRatePrescaler_64)
672 case SPI_BaudRatePrescaler_64:
675#if defined(SPI_BaudRatePrescaler_128)
676 case SPI_BaudRatePrescaler_128:
679#if defined(SPI_BaudRatePrescaler_256)
680 case SPI_BaudRatePrescaler_256:
ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) override
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数。Sets SPI configuration parameters.
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op) override
进行 SPI 读写操作。Performs SPI read and write operations.
SPI::Prescaler GetMaxPrescaler() const override
获取 SPI 设备的最大分频系数。Gets the maximum prescaler of the SPI device.
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
ErrorCode Transfer(size_t size, OperationRW &op) override
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) override
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
常量原始数据封装类。 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).
union LibXR::Operation::@5 data
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
原始数据封装类。 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.
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
存储 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.