libxr  1.0
Want to be the best embedded framework
Loading...
Searching...
No Matches
ch32_spi.cpp
1#include "ch32_spi.hpp"
2
3#include <cstring>
4
5#include "ch32_dma.hpp"
6#include "ch32_gpio.hpp"
7
8using namespace LibXR;
9
10CH32SPI* CH32SPI::map[CH32_SPI_NUMBER] = {nullptr};
11
12bool CH32SPI::MapEnumToCH32Prescaler(SPI::Prescaler p, uint16_t& out)
13{
14 switch (p)
15 {
16#if defined(SPI_BaudRatePrescaler_2)
18 out = SPI_BaudRatePrescaler_2;
19 return true;
20#endif
21#if defined(SPI_BaudRatePrescaler_4)
23 out = SPI_BaudRatePrescaler_4;
24 return true;
25#endif
26#if defined(SPI_BaudRatePrescaler_8)
28 out = SPI_BaudRatePrescaler_8;
29 return true;
30#endif
31#if defined(SPI_BaudRatePrescaler_16)
33 out = SPI_BaudRatePrescaler_16;
34 return true;
35#endif
36#if defined(SPI_BaudRatePrescaler_32)
38 out = SPI_BaudRatePrescaler_32;
39 return true;
40#endif
41#if defined(SPI_BaudRatePrescaler_64)
43 out = SPI_BaudRatePrescaler_64;
44 return true;
45#endif
46#if defined(SPI_BaudRatePrescaler_128)
48 out = SPI_BaudRatePrescaler_128;
49 return true;
50#endif
51#if defined(SPI_BaudRatePrescaler_256)
53 out = SPI_BaudRatePrescaler_256;
54 return true;
55#endif
56 default:
57 return false; // 不支持 DIV_1 或 >256 的枚举
58 }
59}
60
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,
65 uint32_t dma_enable_min_size, SPI::Configuration config)
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]),
70 id_(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),
76 sck_port_(sck_port),
77 sck_pin_(sck_pin),
78 miso_port_(miso_port),
79 miso_pin_(miso_pin),
80 mosi_port_(mosi_port),
81 mosi_pin_(mosi_pin)
82{
83 ASSERT(instance_ != nullptr);
84
85 map[id] = this;
86
87 // === 时钟 ===
88 if (CH32_SPI_APB_MAP[id] == 1)
89 {
90 RCC_APB1PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[id], ENABLE);
91 }
92 else if (CH32_SPI_APB_MAP[id] == 2)
93 {
94 RCC_APB2PeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP[id], ENABLE);
95 }
96 else
97 {
98 ASSERT(false);
99 }
100 RCC_AHBPeriphClockCmd(CH32_SPI_RCC_PERIPH_MAP_DMA[id], ENABLE);
101
102 // === GPIO ===
103 {
104 GPIO_InitTypeDef gpio = {};
105 gpio.GPIO_Speed = GPIO_Speed_50MHz;
106
107 // SCK
108 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(sck_port_), ENABLE);
109 if (mode_ == SPI_Mode_Master)
110 {
111 gpio.GPIO_Pin = sck_pin_;
112 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
113 }
114 else
115 {
116 gpio.GPIO_Pin = sck_pin_;
117 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
118 }
119 GPIO_Init(sck_port_, &gpio);
120
121 // MISO
122 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(miso_port_), ENABLE);
123 if (mode_ == SPI_Mode_Master)
124 {
125 gpio.GPIO_Pin = miso_pin_;
126 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
127 }
128 else
129 {
130 gpio.GPIO_Pin = miso_pin_;
131 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
132 }
133 GPIO_Init(miso_port_, &gpio);
134
135 // MOSI
136 RCC_APB2PeriphClockCmd(CH32GetGPIOPeriph(mosi_port_), ENABLE);
137 if (mode_ == SPI_Mode_Master)
138 {
139 gpio.GPIO_Pin = mosi_pin_;
140 gpio.GPIO_Mode = GPIO_Mode_AF_PP;
141 }
142 else
143 {
144 gpio.GPIO_Pin = mosi_pin_;
145 gpio.GPIO_Mode = GPIO_Mode_IN_FLOATING;
146 }
147 GPIO_Init(mosi_port_, &gpio);
148
149 if (pin_remap != 0)
150 {
151 RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
152 GPIO_PinRemapConfig(pin_remap, ENABLE);
153 }
154 }
155
156 // === SPI 基本配置 ===
157 {
158 SPI_InitTypeDef init = {};
159 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
160 init.SPI_Mode = mode_;
161 init.SPI_DataSize = datasize_;
162 init.SPI_CPOL =
163 (config.clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
164 init.SPI_CPHA =
165 (config.clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
166 init.SPI_NSS = nss_;
167 init.SPI_BaudRatePrescaler = prescaler_;
168 init.SPI_FirstBit = firstbit_;
169 init.SPI_CRCPolynomial = 7;
170
171 SPI_Init(instance_, &init);
172 SPI_Cmd(instance_, ENABLE);
173 }
174
175 // === DMA 通道基础配置(MADDR/CNTR 运行时再设) ===
176 {
177 // RX
178 {
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);
182
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_)]);
199 }
200 // TX
201 {
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);
205
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_)]);
222 }
223 }
224
225 // === 同步基类配置用于速率查询 ===
226 GetConfig() = config;
227 GetConfig().prescaler = MapCH32PrescalerToEnum(prescaler_);
228}
229
230// === SetConfig:更新极性/相位,并同步基类配置 ===
232{
233 // 1) 把 SPI::Prescaler → CH32 Prescaler 宏
234 uint16_t ch32_presc = 0;
235 if (!MapEnumToCH32Prescaler(config.prescaler, ch32_presc))
236 {
237 return ErrorCode::NOT_SUPPORT;
238 }
239
240 // 2) 关 / 复位 / 重新初始化
241 SPI_Cmd(instance_, DISABLE);
242 SPI_I2S_DeInit(instance_);
243
244 SPI_InitTypeDef init = {};
245 init.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
246 init.SPI_Mode = mode_;
247 init.SPI_DataSize = datasize_;
248 init.SPI_CPOL =
249 (config.clock_polarity == SPI::ClockPolarity::LOW) ? SPI_CPOL_Low : SPI_CPOL_High;
250 init.SPI_CPHA =
251 (config.clock_phase == SPI::ClockPhase::EDGE_1) ? SPI_CPHA_1Edge : SPI_CPHA_2Edge;
252 init.SPI_NSS = nss_;
253 init.SPI_BaudRatePrescaler = ch32_presc;
254 init.SPI_FirstBit = firstbit_;
255 init.SPI_CRCPolynomial = 7;
256
257 SPI_Init(instance_, &init);
258 SPI_Cmd(instance_, ENABLE);
259
260 // 3) 同步本地缓存与基类配置(影响 GetBusSpeed/IsDoubleBuffer)
261 prescaler_ = ch32_presc;
262 GetConfig() = config;
263
264 return ErrorCode::OK;
265}
266
267ErrorCode CH32SPI::PollingTransfer(uint8_t* rx, const uint8_t* tx, uint32_t len)
268{
269 for (uint32_t i = 0; i < len; ++i)
270 {
271 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_TXE) == RESET)
272 {
273 }
274 SPI_I2S_SendData(instance_, tx ? tx[i] : 0x00);
275
276 while (SPI_I2S_GetFlagStatus(instance_, SPI_I2S_FLAG_RXNE) == RESET)
277 {
278 }
279 uint16_t d = SPI_I2S_ReceiveData(instance_);
280 if (rx) rx[i] = static_cast<uint8_t>(d & 0xff);
281 }
282 return ErrorCode::OK;
283}
284
285ErrorCode CH32SPI::ReadAndWrite(RawData read_data, ConstRawData write_data,
286 OperationRW& op)
287{
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;
291
292 if (need == 0)
293 {
294 if (op.type != OperationRW::OperationType::BLOCK)
295 op.UpdateStatus(false, ErrorCode::OK);
296 return ErrorCode::OK;
297 }
298
299 if (DmaBusy()) return ErrorCode::BUSY;
300
301 RawData rx = GetRxBuffer();
302 RawData tx = GetTxBuffer();
303
304 ASSERT(rx.size_ >= need);
305 ASSERT(tx.size_ >= need);
306
307 if (need > dma_enable_min_size_)
308 {
309 mem_read_ = false;
310 read_buff_ = read_data;
311 rw_op_ = op;
312 busy_ = true;
313
314 PrepareTxBuffer(write_data, need);
315
316 StartDmaDuplex(need);
317
318 op.MarkAsRunning();
319 if (op.type == OperationRW::OperationType::BLOCK)
320 {
321 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
322 }
323 return ErrorCode::OK;
324 }
325 else
326 {
327 // 轮询路径(使用活动缓冲)
328 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
329 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
330
331 // 准备 tx
332 if (wsz)
333 {
334 memcpy(txp, write_data.addr_, wsz);
335 if (need > wsz) memset(txp + wsz, 0x00, need - wsz);
336 }
337 else
338 {
339 memset(txp, 0x00, need);
340 }
341
342 ErrorCode ec = PollingTransfer(rxp, txp, need);
343
344 if (rsz)
345 {
346 memcpy(read_data.addr_, rxp, rsz);
347 }
348
349 SwitchBuffer();
350
351 if (op.type != OperationRW::OperationType::BLOCK) op.UpdateStatus(false, ec);
352 return ec;
353 }
354}
355
356ErrorCode CH32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW& op)
357{
358 const uint32_t n = read_data.size_;
359 if (n == 0)
360 {
361 if (op.type != OperationRW::OperationType::BLOCK)
362 op.UpdateStatus(false, ErrorCode::OK);
363 return ErrorCode::OK;
364 }
365
366 if (DmaBusy()) return ErrorCode::BUSY;
367
368 RawData rx = GetRxBuffer();
369 RawData tx = GetTxBuffer();
370
371 ASSERT(rx.size_ >= n + 1);
372 ASSERT(tx.size_ >= n + 1);
373
374 const uint32_t total = n + 1;
375
376 if (total > dma_enable_min_size_)
377 {
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);
381
382 mem_read_ = true;
383 read_buff_ = read_data;
384 rw_op_ = op;
385 busy_ = true;
386
387 StartDmaDuplex(total);
388
389 op.MarkAsRunning();
390 if (op.type == OperationRW::OperationType::BLOCK)
391 {
392 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
393 }
394 return ErrorCode::OK;
395 }
396 else
397 {
398 // 轮询
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);
403
404 ErrorCode ec = PollingTransfer(rxp, txp, total);
405 memcpy(read_data.addr_, rxp + 1, n);
406
407 SwitchBuffer();
408
409 if (op.type != OperationRW::OperationType::BLOCK) op.UpdateStatus(false, ec);
410 return ec;
411 }
412}
413
414ErrorCode CH32SPI::MemWrite(uint16_t reg, ConstRawData write_data, OperationRW& op)
415{
416 const uint32_t n = write_data.size_;
417 if (n == 0)
418 {
419 if (op.type != OperationRW::OperationType::BLOCK)
420 op.UpdateStatus(false, ErrorCode::OK);
421 return ErrorCode::OK;
422 }
423
424 if (DmaBusy()) return ErrorCode::BUSY;
425
426 RawData rx = GetRxBuffer();
427 RawData tx = GetTxBuffer();
428 (void)rx; // RX 仅用于丢弃
429
430 ASSERT(tx.size_ >= n + 1);
431
432 const uint32_t total = n + 1;
433
434 if (total > dma_enable_min_size_)
435 {
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);
439
440 mem_read_ = false;
441 read_buff_ = {nullptr, 0};
442 rw_op_ = op;
443 busy_ = true;
444
445 StartDmaDuplex(total);
446
447 op.MarkAsRunning();
448 if (op.type == OperationRW::OperationType::BLOCK)
449 {
450 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
451 }
452 return ErrorCode::OK;
453 }
454 else
455 {
456 // 轮询
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);
461
462 ErrorCode ec = PollingTransfer(rxp, txp, total);
463
464 SwitchBuffer();
465
466 if (op.type != OperationRW::OperationType::BLOCK) op.UpdateStatus(false, ec);
467 return ec;
468 }
469}
470
471void CH32SPI::PrepareTxBuffer(ConstRawData write_data, uint32_t need_len, uint32_t prefix,
472 uint8_t dummy)
473{
474 RawData tx = GetTxBuffer();
475 uint8_t* txp = static_cast<uint8_t*>(tx.addr_);
476
477 if (write_data.size_ > 0)
478 {
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)
483 {
484 memset(txp + prefix + copy, dummy, need_len - prefix - copy);
485 }
486 }
487 else
488 {
489 memset(txp + prefix, dummy, need_len - prefix);
490 }
491}
492
493void CH32SPI::StartDmaDuplex(uint32_t count)
494{
495 RawData rx = GetRxBuffer();
496 RawData tx = GetTxBuffer();
497
498 dma_rx_channel_->MADDR = reinterpret_cast<uint32_t>(rx.addr_);
499 dma_rx_channel_->CNTR = count;
500
501 dma_tx_channel_->MADDR = reinterpret_cast<uint32_t>(tx.addr_);
502 dma_tx_channel_->CNTR = count;
503
504 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, ENABLE);
505 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, ENABLE);
506
507 DMA_Cmd(dma_rx_channel_, ENABLE);
508 DMA_Cmd(dma_tx_channel_, ENABLE);
509}
510
511void CH32SPI::StopDma()
512{
513 DMA_Cmd(dma_tx_channel_, DISABLE);
514 DMA_Cmd(dma_rx_channel_, DISABLE);
515}
516
517void CH32SPI::RxDmaIRQHandler()
518{
519 if (DMA_GetITStatus(CH32_SPI_RX_DMA_IT_MAP[id_]) == RESET) return;
520
521 DMA_ClearITPendingBit(CH32_SPI_RX_DMA_IT_MAP[id_]);
522
523 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Rx, DISABLE);
524 DMA_Cmd(dma_rx_channel_, DISABLE);
525
526 // 拷贝读数据(若有)
527 if (read_buff_.size_ > 0)
528 {
529 RawData rx = GetRxBuffer();
530 uint8_t* rxp = static_cast<uint8_t*>(rx.addr_);
531 if (mem_read_)
532 {
533 memcpy(read_buff_.addr_, rxp + 1, read_buff_.size_);
534 }
535 else
536 {
537 memcpy(read_buff_.addr_, rxp, read_buff_.size_);
538 }
539 read_buff_.size_ = 0;
540 }
541
542 // 双缓冲切换与状态更新
543 SwitchBuffer();
544 busy_ = false;
545 rw_op_.UpdateStatus(true, ErrorCode::OK);
546}
547
548void CH32SPI::TxDmaIRQHandler()
549{
550 if (DMA_GetITStatus(CH32_SPI_TX_DMA_IT_MAP[id_]) == RESET) return;
551 DMA_ClearITPendingBit(CH32_SPI_TX_DMA_IT_MAP[id_]);
552
553 SPI_I2S_DMACmd(instance_, SPI_I2S_DMAReq_Tx, DISABLE);
554 DMA_Cmd(dma_tx_channel_, DISABLE);
555}
556
557// === 零拷贝 Transfer ===
558ErrorCode CH32SPI::Transfer(size_t size, OperationRW& op)
559{
560 if (DmaBusy()) return ErrorCode::BUSY;
561
562 if (size == 0)
563 {
564 if (op.type != OperationRW::OperationType::BLOCK)
565 op.UpdateStatus(false, ErrorCode::OK);
566 return ErrorCode::OK;
567 }
568
569 RawData rx = GetRxBuffer();
570 RawData tx = GetTxBuffer();
571 ASSERT(rx.size_ >= size);
572 ASSERT(tx.size_ >= size);
573
574 if (size > dma_enable_min_size_)
575 {
576 rw_op_ = op;
577 read_buff_ = {nullptr, 0};
578 mem_read_ = false;
579 busy_ = true;
580
581 StartDmaDuplex(static_cast<uint32_t>(size));
582
583 op.MarkAsRunning();
584 if (op.type == OperationRW::OperationType::BLOCK)
585 {
586 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
587 }
588 return ErrorCode::OK;
589 }
590
591 // 小包轮询
592 ErrorCode ec =
593 PollingTransfer(static_cast<uint8_t*>(rx.addr_),
594 static_cast<const uint8_t*>(tx.addr_), static_cast<uint32_t>(size));
595
596 SwitchBuffer();
597
598 if (op.type != OperationRW::OperationType::BLOCK) op.UpdateStatus(false, ec);
599 return ec;
600}
601
602// === 最大总线时钟(Hz) ===
604{
605 RCC_ClocksTypeDef clocks{};
606 RCC_GetClocksFreq(&clocks);
607
608 if (CH32_SPI_APB_MAP[id_] == 2)
609 {
610 return clocks.PCLK2_Frequency;
611 }
612 else if (CH32_SPI_APB_MAP[id_] == 1)
613 {
614 return clocks.PCLK1_Frequency;
615 }
616 return 0u;
617}
618
619// === 最大可用分频枚举 ===
621{
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)
642#else
644#endif
645}
646
647SPI::Prescaler CH32SPI::MapCH32PrescalerToEnum(uint16_t p)
648{
649 switch (p)
650 {
651#if defined(SPI_BaudRatePrescaler_2)
652 case SPI_BaudRatePrescaler_2:
654#endif
655#if defined(SPI_BaudRatePrescaler_4)
656 case SPI_BaudRatePrescaler_4:
658#endif
659#if defined(SPI_BaudRatePrescaler_8)
660 case SPI_BaudRatePrescaler_8:
662#endif
663#if defined(SPI_BaudRatePrescaler_16)
664 case SPI_BaudRatePrescaler_16:
666#endif
667#if defined(SPI_BaudRatePrescaler_32)
668 case SPI_BaudRatePrescaler_32:
670#endif
671#if defined(SPI_BaudRatePrescaler_64)
672 case SPI_BaudRatePrescaler_64:
674#endif
675#if defined(SPI_BaudRatePrescaler_128)
676 case SPI_BaudRatePrescaler_128:
678#endif
679#if defined(SPI_BaudRatePrescaler_256)
680 case SPI_BaudRatePrescaler_256:
682#endif
683 default:
685 }
686}
ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) override
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
Definition ch32_spi.cpp:414
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数。Sets SPI configuration parameters.
Definition ch32_spi.cpp:231
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op) override
进行 SPI 读写操作。Performs SPI read and write operations.
Definition ch32_spi.cpp:285
SPI::Prescaler GetMaxPrescaler() const override
获取 SPI 设备的最大分频系数。Gets the maximum prescaler of the SPI device.
Definition ch32_spi.cpp:620
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
Definition ch32_spi.cpp:603
ErrorCode Transfer(size_t size, OperationRW &op) override
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
Definition ch32_spi.cpp:558
ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) override
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
Definition ch32_spi.cpp:356
常量原始数据封装类。 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.
Definition libxr_rw.hpp:202
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
Definition libxr_rw.hpp:171
OperationType type
Definition libxr_rw.hpp:226
原始数据封装类。 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:303
void SwitchBuffer()
切换缓冲区。Switches the buffer.
Definition spi.hpp:334
RawData GetTxBuffer()
获取发送数据的缓冲区。Gets the buffer for storing data to be sent.
Definition spi.hpp:319
@ LOW
时钟空闲时为低电平。Clock idle low.
Configuration & GetConfig()
获取 SPI 配置参数。Gets the SPI configuration parameters.
Definition spi.hpp:388
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
LibXR 命名空间
存储 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