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 // 时钟配置。
89 // Clock configuration.
90 if (CH32_SPI_APB_MAP[id] == 1)
91 {
92 RCC_APB1PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[id], ENABLE);
93 }
94 else if (CH32_SPI_APB_MAP[id] == 2)
95 {
96 RCC_APB2PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[id], ENABLE);
97 }
98 else
99 {
100 ASSERT(false);
101 }
102 RCC_AHBPeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP_DMA[id], ENABLE);
103
104 // GPIO 配置。
105 // GPIO configuration.
106 {
107 GPIO_InitTypeDef gpio = {};
108 gpio.GPIO_Speed = GPIO_Speed_50MHz;
109
110 // SCK 引脚。
111 // SCK.
112 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(sck_port_), ENABLE);
113 if (mode_ == SPI_Mode_Master)
114 {
115 gpio.GPIO_Pin = sck_pin_;
116 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
117 }
118 else
119 {
120 gpio.GPIO_Pin = sck_pin_;
121 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
122 }
123 GPIO_Init(sck_port_, &gpio);
124
125 // MISO 引脚。
126 // MISO.
127 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(miso_port_), ENABLE);
128 if (mode_ == SPI_Mode_Master)
129 {
130 gpio.GPIO_Pin = miso_pin_;
131 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
132 }
133 else
134 {
135 gpio.GPIO_Pin = miso_pin_;
136 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
137 }
138 GPIO_Init(miso_port_, &gpio);
139
140 // MOSI 引脚。
141 // MOSI.
142 RCC_APB2PeriphClockCmd(ch32_get_gpio_periph(mosi_port_), ENABLE);
143 if (mode_ == SPI_Mode_Master)
144 {
145 gpio.GPIO_Pin = mosi_pin_;
146 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
147 }
148 else
149 {
150 gpio.GPIO_Pin = mosi_pin_;
151 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
152 }
153 GPIO_Init(mosi_port_, &gpio);
154
155 if (pin_remap != 0)
156 {
157 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
158 GPIO_PinRemapConfig(pin_remap, ENABLE);
159 }
160 }
161
162 // SPI 基础配置。
163 // SPI base configuration.
164 {
165 SPI_InitTypeDef init = {};
166 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
167 init.SPI_Mode = mode_;
168 init.SPI_DataSize = datasize_;
169 init.SPI_CPOL =
170 (config.clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
171 init.SPI_CPHA =
172 (config.clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
173 init.SPI_NSS = nss_;
174 init.SPI_BaudRatePrescaler = prescaler_;
175 init.SPI_FirstBit = firstbit_;
176 init.SPI_CRCPolynomial = 7;
177
178 SPI_Init(instance_, &init);
179 SPI_Cmd(instance_, ENABLE);
180 }
181
182 // DMA 通道基础配置(MADDR/CNTR 在运行时设置)。
183 // DMA channel base configuration (MADDR/CNTR set at runtime).
184 {
185 // RX 通道。
186 // RX.
187 {
188 ch32_dma_callback_t cb = [](void* arg)
189 { reinterpret_cast<CH32SPI*>(arg)->RxDmaIRQHandler(); };
190 ch32_dma_register_callback(ch32_dma_get_id(dma_rx_channel_), cb, this);
191
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_)]);
208 }
209 // TX 通道。
210 // TX.
211 {
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);
215
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_)]);
232 }
233 }
234
235 // 同步基类配置,供速率查询辅助逻辑使用。
236 // Sync the base-class configuration for rate-query helpers.
237 GetConfig() = config;
238 GetConfig().prescaler = MapCH32PrescalerToEnum(prescaler_);
239}
240
241// SetConfig 会更新 polarity / phase,并同步基类配置。
242// SetConfig updates polarity / phase and synchronizes the base-class configuration.
244{
245 // 1) 把 SPI::Prescaler → CH32 Prescaler 宏
246 uint16_t ch32_presc = 0;
247 if (!MapEnumToCH32Prescaler(config.prescaler, ch32_presc))
248 {
250 }
251
252 // 2) 关 / 复位 / 重新初始化
253 SPI_Cmd(instance_, DISABLE);
254 SPI_I2S_DeInit(instance_);
255
256 SPI_InitTypeDef init = {};
257 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
258 init.SPI_Mode = mode_;
259 init.SPI_DataSize = datasize_;
260 init.SPI_CPOL =
261 (config.clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
262 init.SPI_CPHA =
263 (config.clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
264 init.SPI_NSS = nss_;
265 init.SPI_BaudRatePrescaler = ch32_presc;
266 init.SPI_FirstBit = firstbit_;
267 init.SPI_CRCPolynomial = 7;
268
269 SPI_Init(instance_, &init);
270 SPI_Cmd(instance_, ENABLE);
271
272 // 3) 同步本地缓存与基类配置(影响 GetBusSpeed/IsDoubleBuffer)
273 prescaler_ = ch32_presc;
274 GetConfig() = config;
275
276 return ErrorCode::OK;
277}
278
279ErrorCode CH32SPI::PollingTransfer(uint8_t* rx, const uint8_t* tx, uint32_t len)
280{
281 for (uint32_t i = 0; i < len; ++i)
282 {
283 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_TXE) == RESET)
284 {
285 }
286 SPI_I2S_SendData(instance_, tx ? tx[i] : 0x00);
287
288 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_RXNE) == RESET)
289 {
290 }
291 uint16_t d = SPI_I2S_ReceiveData(instance_);
292 if (rx)
293 {
294 rx[i] = static_cast<uint8_t>(d & 0xff);
295 }
296 }
297 return ErrorCode::OK;
298}
299
301 OperationRW& op, bool in_isr)
302{
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;
306
307 if (NEED == 0)
308 {
309 if (op.type != OperationRW::OperationType::BLOCK)
310 {
311 op.UpdateStatus(in_isr, ErrorCode::OK);
312 }
313 return ErrorCode::OK;
314 }
315
316 if (DmaBusy())
317 {
318 return ErrorCode::BUSY;
319 }
320
321 RawData rx = GetRxBuffer();
322 RawData tx = GetTxBuffer();
323
324 ASSERT(rx.size_ >= NEED);
325 ASSERT(tx.size_ >= NEED);
326
327 if (NEED > dma_enable_min_size_)
328 {
329 mem_read_ = false;
330 read_buff_ = read_data;
331 rw_op_ = op;
332 busy_ = true;
333
334 PrepareTxBuffer(write_data, NEED);
335
336 if (op.type == OperationRW::OperationType::BLOCK)
337 {
338 block_wait_.Start(*op.data.sem_info.sem);
339 }
340 StartDmaDuplex(NEED);
341
342 op.MarkAsRunning();
343 if (op.type == OperationRW::OperationType::BLOCK)
344 {
345 return block_wait_.Wait(op.data.sem_info.timeout);
346 }
347 return ErrorCode::OK;
348 }
349 else
350 {
351 // 轮询路径(使用活动缓冲)
352 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
353 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
354
355 // 准备 tx
356 if (WSZ)
357 {
358 Memory::FastCopy(txp, write_data.addr_, WSZ);
359 if (NEED > WSZ)
360 {
361 Memory::FastSet(txp + WSZ, 0x00, NEED - WSZ);
362 }
363 }
364 else
365 {
366 Memory::FastSet(txp, 0x00, NEED);
367 }
368
369 ErrorCode ec = PollingTransfer(rxp, txp, NEED);
370
371 if (RSZ)
372 {
373 Memory::FastCopy(read_data.addr_, rxp, RSZ);
374 }
375
376 SwitchBuffer();
377
378 if (op.type != OperationRW::OperationType::BLOCK)
379 {
380 op.UpdateStatus(in_isr, ec);
381 }
382 return ec;
383 }
384}
385
386ErrorCode CH32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW& op, bool in_isr)
387{
388 const uint32_t N = read_data.size_;
389 if (N == 0)
390 {
391 if (op.type != OperationRW::OperationType::BLOCK)
392 {
393 op.UpdateStatus(in_isr, ErrorCode::OK);
394 }
395 return ErrorCode::OK;
396 }
397
398 if (DmaBusy())
399 {
400 return ErrorCode::BUSY;
401 }
402
403 RawData rx = GetRxBuffer();
404 RawData tx = GetTxBuffer();
405
406 ASSERT(rx.size_ >= N + 1);
407 ASSERT(tx.size_ >= N + 1);
408
409 const uint32_t TOTAL = N + 1;
410
411 if (TOTAL > dma_enable_min_size_)
412 {
413 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
414 txp[0] = static_cast<uint8_t>(reg | 0x80);
415 Memory::FastSet(txp + 1, 0x00, N);
416
417 mem_read_ = true;
418 read_buff_ = read_data;
419 rw_op_ = op;
420 busy_ = true;
421
422 if (op.type == OperationRW::OperationType::BLOCK)
423 {
424 block_wait_.Start(*op.data.sem_info.sem);
425 }
426 StartDmaDuplex(TOTAL);
427 op.MarkAsRunning();
428 if (op.type == OperationRW::OperationType::BLOCK)
429 {
430 return block_wait_.Wait(op.data.sem_info.timeout);
431 }
432 return ErrorCode::OK;
433 }
434 else
435 {
436 // 轮询
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);
440 Memory::FastSet(txp + 1, 0x00, N);
441
442 ErrorCode ec = PollingTransfer(rxp, txp, TOTAL);
443 Memory::FastCopy(read_data.addr_, rxp + 1, N);
444
445 SwitchBuffer();
446
447 if (op.type != OperationRW::OperationType::BLOCK)
448 {
449 op.UpdateStatus(in_isr, ec);
450 }
451 return ec;
452 }
453}
454
456 bool in_isr)
457{
458 const uint32_t N = write_data.size_;
459 if (N == 0)
460 {
461 if (op.type != OperationRW::OperationType::BLOCK)
462 {
463 op.UpdateStatus(in_isr, ErrorCode::OK);
464 }
465 return ErrorCode::OK;
466 }
467
468 if (DmaBusy())
469 {
470 return ErrorCode::BUSY;
471 }
472
473 RawData rx = GetRxBuffer();
474 RawData tx = GetTxBuffer();
475 (void)rx; // RX 仅用于丢弃
476
477 ASSERT(tx.size_ >= N + 1);
478
479 const uint32_t TOTAL = N + 1;
480
481 if (TOTAL > dma_enable_min_size_)
482 {
483 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
484 txp[0] = static_cast<uint8_t>(reg & 0x7F);
485 Memory::FastCopy(txp + 1, write_data.addr_, N);
486
487 mem_read_ = false;
488 read_buff_ = {nullptr, 0};
489 rw_op_ = op;
490 busy_ = true;
491
492 if (op.type == OperationRW::OperationType::BLOCK)
493 {
494 block_wait_.Start(*op.data.sem_info.sem);
495 }
496 StartDmaDuplex(TOTAL);
497
498 op.MarkAsRunning();
499 if (op.type == OperationRW::OperationType::BLOCK)
500 {
501 return block_wait_.Wait(op.data.sem_info.timeout);
502 }
503 return ErrorCode::OK;
504 }
505 else
506 {
507 // 轮询
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);
511 Memory::FastCopy(txp + 1, write_data.addr_, N);
512
513 ErrorCode ec = PollingTransfer(rxp, txp, TOTAL);
514
515 SwitchBuffer();
516
517 if (op.type != OperationRW::OperationType::BLOCK)
518 {
519 op.UpdateStatus(in_isr, ec);
520 }
521 return ec;
522 }
523}
524
525void CH32SPI::PrepareTxBuffer(ConstRawData write_data, uint32_t need_len, uint32_t prefix,
526 uint8_t dummy)
527{
528 RawData tx = GetTxBuffer();
529 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
530
531 if (write_data.size_ > 0)
532 {
533 const uint32_t COPY =
534 (write_data.size_ > need_len - prefix) ? (need_len - prefix) : write_data.size_;
535 Memory::FastCopy(txp + prefix, write_data.addr_, COPY);
536 if (prefix + COPY < need_len)
537 {
538 Memory::FastSet(txp + prefix + COPY, dummy, need_len - prefix - COPY);
539 }
540 }
541 else
542 {
543 Memory::FastSet(txp + prefix, dummy, need_len - prefix);
544 }
545}
546
547void CH32SPI::StartDmaDuplex(uint32_t count)
548{
549 RawData rx = GetRxBuffer();
550 RawData tx = GetTxBuffer();
551
552 dma_rx_channel_->MADDR = reinterpret_cast<uint32_t>(rx.addr_);
553 dma_rx_channel_->CNTR = count;
554
555 dma_tx_channel_->MADDR = reinterpret_cast<uint32_t>(tx.addr_);
556 dma_tx_channel_->CNTR = count;
557
558 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, ENABLE);
559 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, ENABLE);
560
561 DMA_Cmd(dma_rx_channel_, ENABLE);
562 DMA_Cmd(dma_tx_channel_, ENABLE);
563}
564
565void CH32SPI::StopDma()
566{
567 DMA_Cmd(dma_tx_channel_, DISABLE);
568 DMA_Cmd(dma_rx_channel_, DISABLE);
569}
570
572{
573 if (DMA_GetITStatus(CH32_SPI_RX_DMA_IT_MAP[id_]) == RESET)
574 {
575 return;
576 }
577
578 DMA_ClearITPendingBit(CH32_SPI_RX_DMA_IT_MAP[id_]);
579
580 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, DISABLE);
581 DMA_Cmd(dma_rx_channel_, DISABLE);
582
583 if (!busy_)
584 {
585 return;
586 }
587
588 // 拷贝读数据(若有)
589 const bool has_user_read_copy = (read_buff_.size_ > 0);
590 if (has_user_read_copy)
591 {
592 RawData rx = GetRxBuffer();
593 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
594 if (mem_read_)
595 {
596 Memory::FastCopy(read_buff_.addr_, rxp + 1, read_buff_.size_);
597 }
598 else
599 {
600 Memory::FastCopy(read_buff_.addr_, rxp, read_buff_.size_);
601 }
602 read_buff_.size_ = 0;
603 }
604
605 // 双缓冲切换与状态更新
606 SwitchBuffer();
607 busy_ = false;
608 if (rw_op_.type == OperationRW::OperationType::BLOCK)
609 {
610 (void)block_wait_.TryPost(true, ErrorCode::OK);
611 }
612 else
613 {
615 }
616}
617
618void CH32SPI::TxDmaIRQHandler()
619{
620 if (DMA_GetITStatus(CH32_SPI_TX_DMA_IT_MAP[id_]) == RESET)
621 {
622 return;
623 }
624 DMA_ClearITPendingBit(CH32_SPI_TX_DMA_IT_MAP[id_]);
625
626 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, DISABLE);
627 DMA_Cmd(dma_tx_channel_, DISABLE);
628
629 if (!busy_)
630 {
631 return;
632 }
633}
634
635// 零拷贝传输路径。
636// Zero-copy transfer path.
637ErrorCode CH32SPI::Transfer(size_t size, OperationRW& op, bool in_isr)
638{
639 if (DmaBusy())
640 {
641 return ErrorCode::BUSY;
642 }
643
644 if (size == 0)
645 {
646 if (op.type != OperationRW::OperationType::BLOCK)
647 {
648 op.UpdateStatus(in_isr, ErrorCode::OK);
649 }
650 return ErrorCode::OK;
651 }
652
653 RawData rx = GetRxBuffer();
654 RawData tx = GetTxBuffer();
655 ASSERT(rx.size_ >= size);
656 ASSERT(tx.size_ >= size);
657
658 if (size > dma_enable_min_size_)
659 {
660 rw_op_ = op;
661 read_buff_ = {nullptr, 0};
662 mem_read_ = false;
663 busy_ = true;
664
665 if (op.type == OperationRW::OperationType::BLOCK)
666 {
667 block_wait_.Start(*op.data.sem_info.sem);
668 }
669 StartDmaDuplex(static_cast<uint32_t>(size));
670
671 op.MarkAsRunning();
672 if (op.type == OperationRW::OperationType::BLOCK)
673 {
674 return block_wait_.Wait(op.data.sem_info.timeout);
675 }
676 return ErrorCode::OK;
677 }
678
679 // 小包轮询
680 ErrorCode ec =
681 PollingTransfer(static_cast<uint8_t*>(rx.addr_),
682 static_cast<const uint8_t*>(tx.addr_), static_cast<uint32_t>(size));
683
684 SwitchBuffer();
685
686 if (op.type != OperationRW::OperationType::BLOCK)
687 {
688 op.UpdateStatus(in_isr, ec);
689 }
690 return ec;
691}
692
693// 总线最大时钟频率(Hz)。
694// Maximum bus clock in Hz.
696{
697 RCC_ClocksTypeDef clocks{};
698 RCC_GetClocksFreq(&clocks);
699
700 if (CH32_SPI_APB_MAP[id_] == 2)
701 {
702 return clocks.PCLK2_Frequency;
703 }
704 else if (CH32_SPI_APB_MAP[id_] == 1)
705 {
706 return clocks.PCLK1_Frequency;
707 }
708 return 0u;
709}
710
711// 可用的最大分频枚举值。
712// Maximum available prescaler enumeration.
714{
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)
735#else
737#endif
738}
739
740SPI::Prescaler CH32SPI::MapCH32PrescalerToEnum(uint16_t p)
741{
742 switch (p)
743 {
744#if defined(SPI_BaudRatePrescaler_2)
745 case SPI_BaudRatePrescaler_2:
747#endif
748#if defined(SPI_BaudRatePrescaler_4)
749 case SPI_BaudRatePrescaler_4:
751#endif
752#if defined(SPI_BaudRatePrescaler_8)
753 case SPI_BaudRatePrescaler_8:
755#endif
756#if defined(SPI_BaudRatePrescaler_16)
757 case SPI_BaudRatePrescaler_16:
759#endif
760#if defined(SPI_BaudRatePrescaler_32)
761 case SPI_BaudRatePrescaler_32:
763#endif
764#if defined(SPI_BaudRatePrescaler_64)
765 case SPI_BaudRatePrescaler_64:
767#endif
768#if defined(SPI_BaudRatePrescaler_128)
769 case SPI_BaudRatePrescaler_128:
771#endif
772#if defined(SPI_BaudRatePrescaler_256)
773 case SPI_BaudRatePrescaler_256:
775#endif
776 default:
778 }
779}
780
781// 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:571
ErrorCode PollingTransfer(uint8_t *rx, const uint8_t *tx, uint32_t len)
轮询传输辅助函数 / Polling transfer helper
Definition ch32_spi.cpp:279
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:386
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数。Sets SPI configuration parameters.
Definition ch32_spi.cpp:243
SPI::Prescaler GetMaxPrescaler() const override
获取 SPI 设备的最大分频系数。Gets the maximum prescaler of the SPI device.
Definition ch32_spi.cpp:713
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op, bool in_isr) override
SPI 接口实现 / SPI interface overrides.
Definition ch32_spi.cpp:300
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:455
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
Definition ch32_spi.cpp:695
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:637
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:5
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:178
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:213
OperationType type
Definition libxr_rw.hpp:237
原始数据封装类。 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
LibXR 命名空间
Definition ch32_can.hpp:14
ErrorCode
定义错误码枚举
@ BUSY
忙碌 | Busy
@ NOT_SUPPORT
不支持 | Not supported
@ OK
操作成功 | Operation successful
存储 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