6#include "ch32_gpio.hpp"
10CH32SPI *CH32SPI::map[ch32_spi_id_t::CH32_SPI_NUMBER] = {
nullptr};
12CH32SPI::CH32SPI(ch32_spi_id_t
id,
RawData dma_rx,
RawData dma_tx, GPIO_TypeDef *sck_port,
13 uint16_t sck_pin, GPIO_TypeDef *miso_port, uint16_t miso_pin,
14 GPIO_TypeDef *mosi_port, uint16_t mosi_pin, uint32_t pin_remap,
15 bool master_mode,
bool firstbit_msb, uint16_t prescaler,
20 instance_(CH32_SPI_GetInstanceID(id)),
21 dma_rx_channel_(CH32_SPI_RX_DMA_CHANNEL_MAP[id]),
22 dma_tx_channel_(CH32_SPI_TX_DMA_CHANNEL_MAP[id]),
24 dma_enable_min_size_(dma_enable_min_size),
25 mode_(master_mode ? SPI_Mode_Master : SPI_Mode_Slave),
26 datasize_(SPI_DataSize_8b),
27 firstbit_(firstbit_msb ? SPI_FirstBit_MSB : SPI_FirstBit_LSB),
28 prescaler_(prescaler),
31 miso_port_(miso_port),
33 mosi_port_(mosi_port),
36 ASSERT(instance_ !=
nullptr);
37 ASSERT(dma_buff_tx_.size_ >= 1);
39 ASSERT(dma_buff_rx_.size_ >= 1);
44 if (CH32_SPI_APB_MAP[
id] == 1)
46 RCC_APB1PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[
id], ENABLE);
48 else if (CH32_SPI_APB_MAP[
id] == 2)
50 RCC_APB2PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[
id], ENABLE);
56 RCC_AHBPeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP_DMA[
id], ENABLE);
60 GPIO_InitTypeDef gpio = {};
61 gpio.GPIO_Speed = GPIO_Speed_50MHz;
64 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(sck_port_), ENABLE);
65 if (mode_ == SPI_Mode_Master)
67 gpio.GPIO_Pin = sck_pin_;
68 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
72 gpio.GPIO_Pin = sck_pin_;
73 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
75 GPIO_Init(sck_port_, &gpio);
78 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(miso_port_), ENABLE);
79 if (mode_ == SPI_Mode_Master)
81 gpio.GPIO_Pin = miso_pin_;
82 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
86 gpio.GPIO_Pin = miso_pin_;
87 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
89 GPIO_Init(miso_port_, &gpio);
92 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(mosi_port_), ENABLE);
93 if (mode_ == SPI_Mode_Master)
95 gpio.GPIO_Pin = mosi_pin_;
96 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
100 gpio.GPIO_Pin = mosi_pin_;
101 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
103 GPIO_Init(mosi_port_, &gpio);
107 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
108 GPIO_PinRemapConfig(pin_remap, ENABLE);
114 SPI_InitTypeDef init = {};
115 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
116 init.SPI_Mode = mode_;
117 init.SPI_DataSize = datasize_;
119 (config.
clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
121 (config.
clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
123 init.SPI_BaudRatePrescaler = prescaler_;
124 init.SPI_FirstBit = firstbit_;
125 init.SPI_CRCPolynomial = 7;
127 SPI_Init(instance_, &init);
128 SPI_Cmd(instance_, ENABLE);
135 ch32_dma_callback_t cb = [](
void *arg)
136 {
reinterpret_cast<CH32SPI *
>(arg)->RxDmaIRQHandler(); };
137 CH32_DMA_RegisterCallback(CH32_DMA_GetID(dma_rx_channel_), cb,
this);
139 DMA_InitTypeDef di = {};
140 DMA_DeInit(dma_rx_channel_);
141 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
142 di.DMA_MemoryBaseAddr = (uint32_t)dma_buff_rx_.addr_;
143 di.DMA_DIR = DMA_DIR_PeripheralSRC;
144 di.DMA_BufferSize = 0;
145 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
146 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
147 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
148 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
149 di.DMA_Mode = DMA_Mode_Normal;
150 di.DMA_Priority = DMA_Priority_High;
151 di.DMA_M2M = DMA_M2M_Disable;
152 DMA_Init(dma_rx_channel_, &di);
153 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
154 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_rx_channel_)]);
158 ch32_dma_callback_t cb = [](
void *arg)
159 {
reinterpret_cast<CH32SPI *
>(arg)->TxDmaIRQHandler(); };
160 CH32_DMA_RegisterCallback(CH32_DMA_GetID(dma_tx_channel_), cb,
this);
162 DMA_InitTypeDef di = {};
163 DMA_DeInit(dma_tx_channel_);
164 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
165 di.DMA_MemoryBaseAddr = 0;
166 di.DMA_DIR = DMA_DIR_PeripheralDST;
167 di.DMA_BufferSize = 0;
168 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
169 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
170 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
171 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
172 di.DMA_Mode = DMA_Mode_Normal;
173 di.DMA_Priority = DMA_Priority_VeryHigh;
174 di.DMA_M2M = DMA_M2M_Disable;
175 DMA_Init(dma_tx_channel_, &di);
176 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
177 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[CH32_DMA_GetID(dma_tx_channel_)]);
185 SPI_Cmd(instance_, DISABLE);
186 SPI_I2S_DeInit(instance_);
188 SPI_InitTypeDef init = {};
189 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
190 init.SPI_Mode = mode_;
191 init.SPI_DataSize = datasize_;
197 init.SPI_BaudRatePrescaler = prescaler_;
198 init.SPI_FirstBit = firstbit_;
199 init.SPI_CRCPolynomial = 7;
200 SPI_Init(instance_, &init);
201 SPI_Cmd(instance_, ENABLE);
202 return ErrorCode::OK;
205ErrorCode CH32SPI::PollingTransfer(uint8_t *rx,
const uint8_t *tx, uint32_t len)
207 for (uint32_t i = 0; i < len; ++i)
210 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_TXE) == RESET)
213 SPI_I2S_SendData(instance_, tx ? tx[i] : 0xFF);
216 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_RXNE) == RESET)
219 uint16_t d = SPI_I2S_ReceiveData(instance_);
220 if (rx) rx[i] =
static_cast<uint8_t
>(d & 0xFF);
222 return ErrorCode::OK;
228 const uint32_t rsz = read_data.
size_;
229 const uint32_t wsz = write_data.
size_;
230 const uint32_t need = (rsz > wsz) ? rsz : wsz;
234 if (op.
type != OperationRW::OperationType::BLOCK)
236 return ErrorCode::OK;
239 if (DmaBusy())
return ErrorCode::BUSY;
241 if (need > dma_enable_min_size_)
243 ASSERT(dma_buff_tx_.
size_ >= need);
244 ASSERT(dma_buff_rx_.
size_ >= need);
247 read_buff_ = read_data;
251 PrepareTxBuffer(write_data, need);
254 StartDmaDuplex(need);
257 if (op.
type == OperationRW::OperationType::BLOCK)
259 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
261 return ErrorCode::OK;
266 uint8_t *rx =
static_cast<uint8_t *
>(dma_buff_rx_.
addr_);
267 uint8_t *tx =
static_cast<uint8_t *
>(dma_buff_tx_.
addr_);
272 memcpy(tx, write_data.
addr_, wsz);
273 if (need > wsz) memset(tx + wsz, 0xFF, need - wsz);
277 memset(tx, 0xFF, need);
280 ErrorCode ec = PollingTransfer(rsz ? rx :
nullptr, tx, need);
284 memcpy(read_data.
addr_, rx, rsz);
287 if (op.
type == OperationRW::OperationType::BLOCK)
300 const uint32_t n = read_data.
size_;
303 if (op.
type != OperationRW::OperationType::BLOCK)
305 return ErrorCode::OK;
308 if (DmaBusy())
return ErrorCode::BUSY;
310 const uint32_t total = n + 1;
311 if (total > dma_enable_min_size_)
313 ASSERT(dma_buff_tx_.
size_ >= total);
314 ASSERT(dma_buff_rx_.
size_ >= total);
316 uint8_t *tx =
static_cast<uint8_t *
>(dma_buff_tx_.
addr_);
317 tx[0] =
static_cast<uint8_t
>(reg | 0x80);
318 memset(tx + 1, 0xFF, n);
321 read_buff_ = read_data;
325 StartDmaDuplex(total);
328 if (op.
type == OperationRW::OperationType::BLOCK)
330 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
332 return ErrorCode::OK;
337 uint8_t *rx =
static_cast<uint8_t *
>(dma_buff_rx_.
addr_);
338 uint8_t *tx =
static_cast<uint8_t *
>(dma_buff_tx_.
addr_);
339 tx[0] =
static_cast<uint8_t
>(reg | 0x80);
340 memset(tx + 1, 0xFF, n);
342 ErrorCode ec = PollingTransfer(rx, tx, n + 1);
343 memcpy(read_data.
addr_, rx + 1, n);
345 if (op.
type == OperationRW::OperationType::BLOCK)
358 const uint32_t n = write_data.
size_;
361 if (op.
type != OperationRW::OperationType::BLOCK)
363 return ErrorCode::OK;
366 if (DmaBusy())
return ErrorCode::BUSY;
368 const uint32_t total = n + 1;
369 if (total > dma_enable_min_size_)
371 ASSERT(dma_buff_tx_.
size_ >= total);
372 ASSERT(dma_buff_rx_.
size_ >= total);
374 uint8_t *tx =
static_cast<uint8_t *
>(dma_buff_tx_.
addr_);
375 tx[0] =
static_cast<uint8_t
>(reg & 0x7F);
376 memcpy(tx + 1, write_data.
addr_, n);
379 read_buff_ = {
nullptr, 0};
383 StartDmaDuplex(total);
386 if (op.
type == OperationRW::OperationType::BLOCK)
388 return op.
data.sem_info.sem->
Wait(op.
data.sem_info.timeout);
390 return ErrorCode::OK;
395 uint8_t *rx =
static_cast<uint8_t *
>(dma_buff_rx_.
addr_);
396 uint8_t *tx =
static_cast<uint8_t *
>(dma_buff_tx_.
addr_);
397 tx[0] =
static_cast<uint8_t
>(reg & 0x7F);
398 memcpy(tx + 1, write_data.
addr_, n);
400 ErrorCode ec = PollingTransfer(rx, tx, n + 1);
402 if (op.
type == OperationRW::OperationType::BLOCK)
413void CH32SPI::PrepareTxBuffer(
ConstRawData write_data, uint32_t need_len, uint32_t prefix,
416 uint8_t *tx =
static_cast<uint8_t *
>(dma_buff_tx_.
addr_);
417 if (write_data.
size_ > 0)
419 const uint32_t copy =
420 (write_data.
size_ > need_len - prefix) ? (need_len - prefix) : write_data.
size_;
421 memcpy(tx + prefix, write_data.
addr_, copy);
422 if (prefix + copy < need_len)
424 memset(tx + prefix + copy, dummy, need_len - prefix - copy);
429 memset(tx + prefix, dummy, need_len - prefix);
433void CH32SPI::StartDmaDuplex(uint32_t count)
436 dma_rx_channel_->MADDR =
reinterpret_cast<uint32_t
>(dma_buff_rx_.
addr_);
437 dma_rx_channel_->CNTR = count;
439 dma_tx_channel_->MADDR =
reinterpret_cast<uint32_t
>(dma_buff_tx_.
addr_);
440 dma_tx_channel_->CNTR = count;
442 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, ENABLE);
443 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, ENABLE);
445 DMA_Cmd(dma_rx_channel_, ENABLE);
446 DMA_Cmd(dma_tx_channel_, ENABLE);
449void CH32SPI::StopDma()
451 DMA_Cmd(dma_tx_channel_, DISABLE);
452 DMA_Cmd(dma_rx_channel_, DISABLE);
455void CH32SPI::RxDmaIRQHandler()
458 if (DMA_GetITStatus(CH32_SPI_RX_DMA_IT_MAP[id_]) == RESET)
return;
460 DMA_ClearITPendingBit(CH32_SPI_RX_DMA_IT_MAP[id_]);
462 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, DISABLE);
463 DMA_Cmd(dma_rx_channel_, DISABLE);
466 if (read_buff_.
size_ > 0)
468 uint8_t *rx =
static_cast<uint8_t *
>(dma_buff_rx_.
addr_);
472 memcpy(read_buff_.
addr_, rx + 1, read_buff_.
size_);
476 memcpy(read_buff_.
addr_, rx, read_buff_.
size_);
484void CH32SPI::TxDmaIRQHandler()
486 if (DMA_GetITStatus(CH32_SPI_TX_DMA_IT_MAP[id_]) == RESET)
return;
487 DMA_ClearITPendingBit(CH32_SPI_TX_DMA_IT_MAP[id_]);
489 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, DISABLE);
490 DMA_Cmd(dma_tx_channel_, DISABLE);
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.
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.
@ LOW
时钟空闲时为低电平。Clock idle low.
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.
ClockPolarity clock_polarity
SPI 时钟极性。SPI clock polarity.