libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_spi.cpp
1// NOLINTBEGIN(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
2#include "ch32_spi.hpp"
3
4#include <cstring>
5
6#include "ch32_dma.hpp"
7#include "ch32_gpio.hpp"
8
9using namespace LibXR;
10
11CH32SPI* CH32SPI::map_[CH32_SPI_NUMBER] = {nullptr};
12
13bool CH32SPI::MapEnumToCH32Prescaler(SPI::Prescaler p, uint16_t& out)
14{
15 switch (p)
16 {
17#if defined(SPI_BaudRatePrescaler_2)
19 out = SPI_BaudRatePrescaler_2;
20 return true;
21#endif
22#if defined(SPI_BaudRatePrescaler_4)
24 out = SPI_BaudRatePrescaler_4;
25 return true;
26#endif
27#if defined(SPI_BaudRatePrescaler_8)
29 out = SPI_BaudRatePrescaler_8;
30 return true;
31#endif
32#if defined(SPI_BaudRatePrescaler_16)
34 out = SPI_BaudRatePrescaler_16;
35 return true;
36#endif
37#if defined(SPI_BaudRatePrescaler_32)
39 out = SPI_BaudRatePrescaler_32;
40 return true;
41#endif
42#if defined(SPI_BaudRatePrescaler_64)
44 out = SPI_BaudRatePrescaler_64;
45 return true;
46#endif
47#if defined(SPI_BaudRatePrescaler_128)
49 out = SPI_BaudRatePrescaler_128;
50 return true;
51#endif
52#if defined(SPI_BaudRatePrescaler_256)
54 out = SPI_BaudRatePrescaler_256;
55 return true;
56#endif
57 default:
58 return false; // 不支持 DIV_1 或 >256 的枚举
59 }
60}
61
62CH32SPI::CH32SPI(ch32_spi_id_t id, RawData dma_rx, RawData dma_tx, GPIO_TypeDef* sck_port,
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,
66 uint32_t dma_enable_min_size, SPI::Configuration config)
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]),
71 id_(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),
77 sck_port_(sck_port),
78 sck_pin_(sck_pin),
79 miso_port_(miso_port),
80 miso_pin_(miso_pin),
81 mosi_port_(mosi_port),
82 mosi_pin_(mosi_pin)
83{
84 ASSERT(instance_ != nullptr);
85
86 map_[id] = this;
87
88 // Clock configuration.
89 if (CH32_SPI_APB_MAP[id] == 1)
90 {
91 RCC_APB1PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[id], ENABLE);
92 }
93 else if (CH32_SPI_APB_MAP[id] == 2)
94 {
95 RCC_APB2PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[id], ENABLE);
96 }
97 else
98 {
99 ASSERT(false);
100 }
101 RCC_AHBPeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP_DMA[id], ENABLE);
102
103 // GPIO configuration.
104 {
105 GPIO_InitTypeDef gpio = {};
106 gpio.GPIO_Speed = GPIO_Speed_50MHz;
107
108 // SCK
109 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(sck_port_), ENABLE);
110 if (mode_ == SPI_Mode_Master)
111 {
112 gpio.GPIO_Pin = sck_pin_;
113 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
114 }
115 else
116 {
117 gpio.GPIO_Pin = sck_pin_;
118 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
119 }
120 GPIO_Init(sck_port_, &gpio);
121
122 // MISO
123 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(miso_port_), ENABLE);
124 if (mode_ == SPI_Mode_Master)
125 {
126 gpio.GPIO_Pin = miso_pin_;
127 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
128 }
129 else
130 {
131 gpio.GPIO_Pin = miso_pin_;
132 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
133 }
134 GPIO_Init(miso_port_, &gpio);
135
136 // MOSI
137 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(mosi_port_), ENABLE);
138 if (mode_ == SPI_Mode_Master)
139 {
140 gpio.GPIO_Pin = mosi_pin_;
141 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
142 }
143 else
144 {
145 gpio.GPIO_Pin = mosi_pin_;
146 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
147 }
148 GPIO_Init(mosi_port_, &gpio);
149
150 if (pin_remap != 0)
151 {
152 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
153 GPIO_PinRemapConfig(pin_remap, ENABLE);
154 }
155 }
156
157 // SPI base configuration.
158 {
159 SPI_InitTypeDef init = {};
160 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
161 init.SPI_Mode = mode_;
162 init.SPI_DataSize = datasize_;
163 init.SPI_CPOL =
164 (config.clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
165 init.SPI_CPHA =
166 (config.clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
167 init.SPI_NSS = nss_;
168 init.SPI_BaudRatePrescaler = prescaler_;
169 init.SPI_FirstBit = firstbit_;
170 init.SPI_CRCPolynomial = 7;
171
172 SPI_Init(instance_, &init);
173 SPI_Cmd(instance_, ENABLE);
174 }
175
176 // DMA channel base configuration (MADDR/CNTR set at runtime).
177 {
178 // RX
179 {
180 ch32_dma_callback_t cb = [](void* arg)
181 { reinterpret_cast<CH32SPI*>(arg)->RxDmaIRQHandler(); };
182 ch32_dma_register_callback(ch32_dma_get_id(dma_rx_channel_), cb, this);
183
184 DMA_InitTypeDef di = {};
185 DMA_DeInit(dma_rx_channel_);
186 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
187 di.DMA_MemoryBaseAddr = (uint32_t)dma_rx.addr_;
188 di.DMA_DIR = DMA_DIR_PeripheralSRC;
189 di.DMA_BufferSize = 0;
190 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
191 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
192 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
193 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
194 di.DMA_Mode = DMA_Mode_Normal;
195 di.DMA_Priority = DMA_Priority_High;
196 di.DMA_M2M = DMA_M2M_Disable;
197 DMA_Init(dma_rx_channel_, &di);
198 DMA_ITConfig(dma_rx_channel_, DMA_IT_TC, ENABLE);
199 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_rx_channel_)]);
200 }
201 // TX
202 {
203 ch32_dma_callback_t cb = [](void* arg)
204 { reinterpret_cast<CH32SPI*>(arg)->TxDmaIRQHandler(); };
205 ch32_dma_register_callback(ch32_dma_get_id(dma_tx_channel_), cb, this);
206
207 DMA_InitTypeDef di = {};
208 DMA_DeInit(dma_tx_channel_);
209 di.DMA_PeripheralBaseAddr = (uint32_t)&instance_->DATAR;
210 di.DMA_MemoryBaseAddr = 0;
211 di.DMA_DIR = DMA_DIR_PeripheralDST;
212 di.DMA_BufferSize = 0;
213 di.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
214 di.DMA_MemoryInc = DMA_MemoryInc_Enable;
215 di.DMA_PeripheralDataSize = DMA_PeripheralDataSize_Byte;
216 di.DMA_MemoryDataSize = DMA_MemoryDataSize_Byte;
217 di.DMA_Mode = DMA_Mode_Normal;
218 di.DMA_Priority = DMA_Priority_VeryHigh;
219 di.DMA_M2M = DMA_M2M_Disable;
220 DMA_Init(dma_tx_channel_, &di);
221 DMA_ITConfig(dma_tx_channel_, DMA_IT_TC, ENABLE);
222 NVIC_EnableIRQ(CH32_DMA_IRQ_MAP[ch32_dma_get_id(dma_tx_channel_)]);
223 }
224 }
225
226 // Sync base-class configuration for rate query helpers.
227 GetConfig() = config;
228 GetConfig().prescaler = MapCH32PrescalerToEnum(prescaler_);
229}
230
231// SetConfig updates polarity/phase and synchronizes base-class configuration.
233{
234 // 1) 把 SPI::Prescaler → CH32 Prescaler 宏
235 uint16_t ch32_presc = 0;
236 if (!MapEnumToCH32Prescaler(config.prescaler, ch32_presc))
237 {
238 return ErrorCode::NOT_SUPPORT;
239 }
240
241 // 2) 关 / 复位 / 重新初始化
242 SPI_Cmd(instance_, DISABLE);
243 SPI_I2S_DeInit(instance_);
244
245 SPI_InitTypeDef init = {};
246 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
247 init.SPI_Mode = mode_;
248 init.SPI_DataSize = datasize_;
249 init.SPI_CPOL =
250 (config.clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
251 init.SPI_CPHA =
252 (config.clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
253 init.SPI_NSS = nss_;
254 init.SPI_BaudRatePrescaler = ch32_presc;
255 init.SPI_FirstBit = firstbit_;
256 init.SPI_CRCPolynomial = 7;
257
258 SPI_Init(instance_, &init);
259 SPI_Cmd(instance_, ENABLE);
260
261 // 3) 同步本地缓存与基类配置(影响 GetBusSpeed/IsDoubleBuffer)
262 prescaler_ = ch32_presc;
263 GetConfig() = config;
264
265 return ErrorCode::OK;
266}
267
268ErrorCode CH32SPI::PollingTransfer(uint8_t* rx, const uint8_t* tx, uint32_t len)
269{
270 for (uint32_t i = 0; i < len; ++i)
271 {
272 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_TXE) == RESET)
273 {
274 }
275 SPI_I2S_SendData(instance_, tx ? tx[i] : 0x00);
276
277 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_RXNE) == RESET)
278 {
279 }
280 uint16_t d = SPI_I2S_ReceiveData(instance_);
281 if (rx)
282 {
283 rx[i] = static_cast<uint8_t>(d & 0xff);
284 }
285 }
286 return ErrorCode::OK;
287}
288
289ErrorCode CH32SPI::ReadAndWrite(RawData read_data, ConstRawData write_data,
290 OperationRW& op, bool in_isr)
291{
292 const uint32_t RSZ = read_data.size_;
293 const uint32_t WSZ = write_data.size_;
294 const uint32_t NEED = (RSZ > WSZ) ? RSZ : WSZ;
295
296 if (NEED == 0)
297 {
298 if (op.type != OperationRW::OperationType::BLOCK)
299 {
300 op.UpdateStatus(in_isr, ErrorCode::OK);
301 }
302 return ErrorCode::OK;
303 }
304
305 if (DmaBusy())
306 {
307 return ErrorCode::BUSY;
308 }
309
310 RawData rx = GetRxBuffer();
311 RawData tx = GetTxBuffer();
312
313 ASSERT(rx.size_ >= NEED);
314 ASSERT(tx.size_ >= NEED);
315
316 if (NEED > dma_enable_min_size_)
317 {
318 mem_read_ = false;
319 read_buff_ = read_data;
320 rw_op_ = op;
321 busy_ = true;
322
323 PrepareTxBuffer(write_data, NEED);
324
325 StartDmaDuplex(NEED);
326
327 op.MarkAsRunning();
328 if (op.type == OperationRW::OperationType::BLOCK)
329 {
330 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
331 }
332 return ErrorCode::OK;
333 }
334 else
335 {
336 // 轮询路径(使用活动缓冲)
337 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
338 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
339
340 // 准备 tx
341 if (WSZ)
342 {
343 Memory::FastCopy(txp, write_data.addr_, WSZ);
344 if (NEED > WSZ)
345 {
346 Memory::FastSet(txp + WSZ, 0x00, NEED - WSZ);
347 }
348 }
349 else
350 {
351 Memory::FastSet(txp, 0x00, NEED);
352 }
353
354 ErrorCode ec = PollingTransfer(rxp, txp, NEED);
355
356 if (RSZ)
357 {
358 Memory::FastCopy(read_data.addr_, rxp, RSZ);
359 }
360
361 SwitchBuffer();
362
363 if (op.type != OperationRW::OperationType::BLOCK)
364 {
365 op.UpdateStatus(in_isr, ec);
366 }
367 return ec;
368 }
369}
370
371ErrorCode CH32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW& op, bool in_isr)
372{
373 const uint32_t N = read_data.size_;
374 if (N == 0)
375 {
376 if (op.type != OperationRW::OperationType::BLOCK)
377 {
378 op.UpdateStatus(in_isr, ErrorCode::OK);
379 }
380 return ErrorCode::OK;
381 }
382
383 if (DmaBusy())
384 {
385 return ErrorCode::BUSY;
386 }
387
388 RawData rx = GetRxBuffer();
389 RawData tx = GetTxBuffer();
390
391 ASSERT(rx.size_ >= N + 1);
392 ASSERT(tx.size_ >= N + 1);
393
394 const uint32_t TOTAL = N + 1;
395
396 if (TOTAL > dma_enable_min_size_)
397 {
398 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
399 txp[0] = static_cast<uint8_t>(reg | 0x80);
400 Memory::FastSet(txp + 1, 0x00, N);
401
402 mem_read_ = true;
403 read_buff_ = read_data;
404 rw_op_ = op;
405 busy_ = true;
406
407 StartDmaDuplex(TOTAL);
408
409 op.MarkAsRunning();
410 if (op.type == OperationRW::OperationType::BLOCK)
411 {
412 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
413 }
414 return ErrorCode::OK;
415 }
416 else
417 {
418 // 轮询
419 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
420 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
421 txp[0] = static_cast<uint8_t>(reg | 0x80);
422 Memory::FastSet(txp + 1, 0x00, N);
423
424 ErrorCode ec = PollingTransfer(rxp, txp, TOTAL);
425 Memory::FastCopy(read_data.addr_, rxp + 1, N);
426
427 SwitchBuffer();
428
429 if (op.type != OperationRW::OperationType::BLOCK)
430 {
431 op.UpdateStatus(in_isr, ec);
432 }
433 return ec;
434 }
435}
436
437ErrorCode CH32SPI::MemWrite(uint16_t reg, ConstRawData write_data, OperationRW& op,
438 bool in_isr)
439{
440 const uint32_t N = write_data.size_;
441 if (N == 0)
442 {
443 if (op.type != OperationRW::OperationType::BLOCK)
444 {
445 op.UpdateStatus(in_isr, ErrorCode::OK);
446 }
447 return ErrorCode::OK;
448 }
449
450 if (DmaBusy())
451 {
452 return ErrorCode::BUSY;
453 }
454
455 RawData rx = GetRxBuffer();
456 RawData tx = GetTxBuffer();
457 (void)rx; // RX 仅用于丢弃
458
459 ASSERT(tx.size_ >= N + 1);
460
461 const uint32_t TOTAL = N + 1;
462
463 if (TOTAL > dma_enable_min_size_)
464 {
465 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
466 txp[0] = static_cast<uint8_t>(reg & 0x7F);
467 Memory::FastCopy(txp + 1, write_data.addr_, N);
468
469 mem_read_ = false;
470 read_buff_ = {nullptr, 0};
471 rw_op_ = op;
472 busy_ = true;
473
474 StartDmaDuplex(TOTAL);
475
476 op.MarkAsRunning();
477 if (op.type == OperationRW::OperationType::BLOCK)
478 {
479 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
480 }
481 return ErrorCode::OK;
482 }
483 else
484 {
485 // 轮询
486 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
487 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
488 txp[0] = static_cast<uint8_t>(reg & 0x7F);
489 Memory::FastCopy(txp + 1, write_data.addr_, N);
490
491 ErrorCode ec = PollingTransfer(rxp, txp, TOTAL);
492
493 SwitchBuffer();
494
495 if (op.type != OperationRW::OperationType::BLOCK)
496 {
497 op.UpdateStatus(in_isr, ec);
498 }
499 return ec;
500 }
501}
502
503void CH32SPI::PrepareTxBuffer(ConstRawData write_data, uint32_t need_len, uint32_t prefix,
504 uint8_t dummy)
505{
506 RawData tx = GetTxBuffer();
507 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
508
509 if (write_data.size_ > 0)
510 {
511 const uint32_t COPY =
512 (write_data.size_ > need_len - prefix) ? (need_len - prefix) : write_data.size_;
513 Memory::FastCopy(txp + prefix, write_data.addr_, COPY);
514 if (prefix + COPY < need_len)
515 {
516 Memory::FastSet(txp + prefix + COPY, dummy, need_len - prefix - COPY);
517 }
518 }
519 else
520 {
521 Memory::FastSet(txp + prefix, dummy, need_len - prefix);
522 }
523}
524
525void CH32SPI::StartDmaDuplex(uint32_t count)
526{
527 RawData rx = GetRxBuffer();
528 RawData tx = GetTxBuffer();
529
530 dma_rx_channel_->MADDR = reinterpret_cast<uint32_t>(rx.addr_);
531 dma_rx_channel_->CNTR = count;
532
533 dma_tx_channel_->MADDR = reinterpret_cast<uint32_t>(tx.addr_);
534 dma_tx_channel_->CNTR = count;
535
536 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, ENABLE);
537 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, ENABLE);
538
539 DMA_Cmd(dma_rx_channel_, ENABLE);
540 DMA_Cmd(dma_tx_channel_, ENABLE);
541}
542
543void CH32SPI::StopDma()
544{
545 DMA_Cmd(dma_tx_channel_, DISABLE);
546 DMA_Cmd(dma_rx_channel_, DISABLE);
547}
548
550{
551 if (DMA_GetITStatus(CH32_SPI_RX_DMA_IT_MAP[id_]) == RESET)
552 {
553 return;
554 }
555
556 DMA_ClearITPendingBit(CH32_SPI_RX_DMA_IT_MAP[id_]);
557
558 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, DISABLE);
559 DMA_Cmd(dma_rx_channel_, DISABLE);
560
561 // 拷贝读数据(若有)
562 if (read_buff_.size_ > 0)
563 {
564 RawData rx = GetRxBuffer();
565 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
566 if (mem_read_)
567 {
568 Memory::FastCopy(read_buff_.addr_, rxp + 1, read_buff_.size_);
569 }
570 else
571 {
572 Memory::FastCopy(read_buff_.addr_, rxp, read_buff_.size_);
573 }
574 read_buff_.size_ = 0;
575 }
576
577 // 双缓冲切换与状态更新
578 SwitchBuffer();
579 busy_ = false;
580 rw_op_.UpdateStatus(true, ErrorCode::OK);
581}
582
583void CH32SPI::TxDmaIRQHandler()
584{
585 if (DMA_GetITStatus(CH32_SPI_TX_DMA_IT_MAP[id_]) == RESET)
586 {
587 return;
588 }
589 DMA_ClearITPendingBit(CH32_SPI_TX_DMA_IT_MAP[id_]);
590
591 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, DISABLE);
592 DMA_Cmd(dma_tx_channel_, DISABLE);
593}
594
595// Zero-copy transfer path.
596ErrorCode CH32SPI::Transfer(size_t size, OperationRW& op, bool in_isr)
597{
598 if (DmaBusy())
599 {
600 return ErrorCode::BUSY;
601 }
602
603 if (size == 0)
604 {
605 if (op.type != OperationRW::OperationType::BLOCK)
606 {
607 op.UpdateStatus(in_isr, ErrorCode::OK);
608 }
609 return ErrorCode::OK;
610 }
611
612 RawData rx = GetRxBuffer();
613 RawData tx = GetTxBuffer();
614 ASSERT(rx.size_ >= size);
615 ASSERT(tx.size_ >= size);
616
617 if (size > dma_enable_min_size_)
618 {
619 rw_op_ = op;
620 read_buff_ = {nullptr, 0};
621 mem_read_ = false;
622 busy_ = true;
623
624 StartDmaDuplex(static_cast<uint32_t>(size));
625
626 op.MarkAsRunning();
627 if (op.type == OperationRW::OperationType::BLOCK)
628 {
629 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
630 }
631 return ErrorCode::OK;
632 }
633
634 // 小包轮询
635 ErrorCode ec =
636 PollingTransfer(static_cast<uint8_t*>(rx.addr_),
637 static_cast<const uint8_t*>(tx.addr_), static_cast<uint32_t>(size));
638
639 SwitchBuffer();
640
641 if (op.type != OperationRW::OperationType::BLOCK)
642 {
643 op.UpdateStatus(in_isr, ec);
644 }
645 return ec;
646}
647
648// Maximum bus clock in Hz.
650{
651 RCC_ClocksTypeDef clocks{};
652 RCC_GetClocksFreq(&clocks);
653
654 if (CH32_SPI_APB_MAP[id_] == 2)
655 {
656 return clocks.PCLK2_Frequency;
657 }
658 else if (CH32_SPI_APB_MAP[id_] == 1)
659 {
660 return clocks.PCLK1_Frequency;
661 }
662 return 0u;
663}
664
665// Maximum available prescaler enumeration.
667{
668#if defined(SPI_BaudRatePrescaler_1024)
670#elif defined(SPI_BaudRatePrescaler_512)
672#elif defined(SPI_BaudRatePrescaler_256)
674#elif defined(SPI_BaudRatePrescaler_128)
676#elif defined(SPI_BaudRatePrescaler_64)
678#elif defined(SPI_BaudRatePrescaler_32)
680#elif defined(SPI_BaudRatePrescaler_16)
682#elif defined(SPI_BaudRatePrescaler_8)
684#elif defined(SPI_BaudRatePrescaler_4)
686#elif defined(SPI_BaudRatePrescaler_2)
688#else
690#endif
691}
692
693SPI::Prescaler CH32SPI::MapCH32PrescalerToEnum(uint16_t p)
694{
695 switch (p)
696 {
697#if defined(SPI_BaudRatePrescaler_2)
698 case SPI_BaudRatePrescaler_2:
700#endif
701#if defined(SPI_BaudRatePrescaler_4)
702 case SPI_BaudRatePrescaler_4:
704#endif
705#if defined(SPI_BaudRatePrescaler_8)
706 case SPI_BaudRatePrescaler_8:
708#endif
709#if defined(SPI_BaudRatePrescaler_16)
710 case SPI_BaudRatePrescaler_16:
712#endif
713#if defined(SPI_BaudRatePrescaler_32)
714 case SPI_BaudRatePrescaler_32:
716#endif
717#if defined(SPI_BaudRatePrescaler_64)
718 case SPI_BaudRatePrescaler_64:
720#endif
721#if defined(SPI_BaudRatePrescaler_128)
722 case SPI_BaudRatePrescaler_128:
724#endif
725#if defined(SPI_BaudRatePrescaler_256)
726 case SPI_BaudRatePrescaler_256:
728#endif
729 default:
731 }
732}
733
734// NOLINTEND(cppcoreguidelines-pro-type-cstyle-cast,performance-no-int-to-ptr)
CH32 SPI 驱动实现 / CH32 SPI driver implementation.
Definition ch32_spi.hpp:20
void RxDmaIRQHandler()
DMA 中断回调 / DMA interrupt callbacks.
Definition ch32_spi.cpp:549
ErrorCode PollingTransfer(uint8_t *rx, const uint8_t *tx, uint32_t len)
轮询传输辅助函数 / Polling transfer helper
Definition ch32_spi.cpp:268
OperationRW rw_op_
运行时状态 / Runtime state
Definition ch32_spi.hpp:77
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.
Definition ch32_spi.cpp:371
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数。Sets SPI configuration parameters.
Definition ch32_spi.cpp:232
SPI::Prescaler GetMaxPrescaler() const override
获取 SPI 设备的最大分频系数。Gets the maximum prescaler of the SPI device.
Definition ch32_spi.cpp:666
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op, bool in_isr) override
SPI 接口实现 / SPI interface overrides.
Definition ch32_spi.cpp:289
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.
Definition ch32_spi.cpp:437
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
Definition ch32_spi.cpp:649
uint16_t mode_
SPI 寄存器配置缓存 / Cached SPI register configuration.
Definition ch32_spi.hpp:83
uint16_t prescaler_
SPI_BaudRatePrescaler_x.
Definition ch32_spi.hpp:86
uint16_t datasize_
SPI_DataSize_8b by default.
Definition ch32_spi.hpp:84
uint16_t firstbit_
SPI_FirstBit_MSB / SPI_FirstBit_LSB.
Definition ch32_spi.hpp:85
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
Definition ch32_spi.cpp:62
ErrorCode Transfer(size_t size, OperationRW &op, bool in_isr) override
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
Definition ch32_spi.cpp:596
GPIO_TypeDef * sck_port_
GPIO 配置 / GPIO configuration.
Definition ch32_spi.hpp:90
常量原始数据封装类。 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
Definition libxr_mem.cpp:3
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:172
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:205
OperationType type
Definition libxr_rw.hpp:229
原始数据封装类。 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).
Definition spi.hpp:14
@ 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.
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
@ LOW
时钟空闲时为低电平。Clock idle low.
Configuration & GetConfig()
获取 SPI 配置参数。Gets the SPI configuration parameters.
Definition spi.hpp:396
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
LibXR 命名空间
Definition ch32_can.hpp:14
存储 SPI 配置参数的结构体。Structure for storing SPI configuration parameters.
Definition spi.hpp:85
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