libxr
Embedded C++ framework for bare-metal, RTOS and Linux
Loading...
Searching...
No Matches
stm32_spi.cpp
1#include "stm32_spi.hpp"
2
3#include "libxr_def.hpp"
4#include "stm32_dcache.hpp"
5
6#ifdef HAL_SPI_MODULE_ENABLED
7
8using namespace LibXR;
9
10STM32SPI* STM32SPI::map[STM32_SPI_NUMBER] = {nullptr};
11
12stm32_spi_id_t STM32_SPI_GetID(SPI_TypeDef* addr)
13{
14 if (addr == nullptr)
15 { // NOLINT
16 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
17 }
18#ifdef SPI1
19 else if (addr == SPI1)
20 { // NOLINT
21 return stm32_spi_id_t::STM32_SPI1;
22 }
23#endif
24#ifdef SPI2
25 else if (addr == SPI2)
26 { // NOLINT
27 return stm32_spi_id_t::STM32_SPI2;
28 }
29#endif
30#ifdef SPI3
31 else if (addr == SPI3)
32 { // NOLINT
33 return stm32_spi_id_t::STM32_SPI3;
34 }
35#endif
36#ifdef SPI4
37 else if (addr == SPI4)
38 { // NOLINT
39 return stm32_spi_id_t::STM32_SPI4;
40 }
41#endif
42#ifdef SPI5
43 else if (addr == SPI5)
44 { // NOLINT
45 return stm32_spi_id_t::STM32_SPI5;
46 }
47#endif
48#ifdef SPI6
49 else if (addr == SPI6)
50 { // NOLINT
51 return stm32_spi_id_t::STM32_SPI6;
52 }
53#endif
54#ifdef SPI7
55 else if (addr == SPI7)
56 { // NOLINT
57 return stm32_spi_id_t::STM32_SPI7;
58 }
59#endif
60#ifdef SPI8
61 else if (addr == SPI8)
62 { // NOLINT
63 return stm32_spi_id_t::STM32_SPI8;
64 }
65#endif
66 else
67 {
68 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
69 }
70}
71
72STM32SPI::STM32SPI(SPI_HandleTypeDef* spi_handle, RawData rx, RawData tx,
73 uint32_t dma_enable_min_size)
74 : SPI(rx, tx),
75 spi_handle_(spi_handle),
76 id_(STM32_SPI_GetID(spi_handle_->Instance)),
77 dma_enable_min_size_(dma_enable_min_size)
78{
79 ASSERT(id_ != STM32_SPI_ID_ERROR);
80
81 map[id_] = this;
82}
83
85 OperationRW& op, bool in_isr)
86{
87 uint32_t need_write = max(write_data.size_, read_data.size_);
88
89 RawData rx = GetRxBuffer();
90 RawData tx = GetTxBuffer();
91
92 if (rx.size_ > 0)
93 {
94 ASSERT(need_write <= rx.size_);
95 }
96 if (tx.size_ > 0)
97 {
98 ASSERT(need_write <= tx.size_);
99 }
100
101 if (spi_handle_->State != HAL_SPI_STATE_READY)
102 {
103 return ErrorCode::BUSY;
104 }
105
106 mem_read_ = false;
107
108 if (need_write > dma_enable_min_size_)
109 {
110 rw_op_ = op;
111 if (op.type == OperationRW::OperationType::BLOCK)
112 {
113 block_wait_.Start(*op.data.sem_info.sem);
114 }
115
116 HAL_StatusTypeDef st = HAL_OK;
117
118 if (write_data.size_ > 0 && read_data.size_ > 0)
119 {
120 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
121 if (write_data.size_ < need_write)
122 {
123 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
124 need_write - write_data.size_);
125 }
126 STM32_CleanDCacheByAddr(tx.addr_, need_write);
127 read_buff_ = read_data;
128
129 st = HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
130 static_cast<uint8_t*>(rx.addr_), need_write);
131 }
132 else if (write_data.size_ > 0)
133 {
134 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
135 if (write_data.size_ < need_write)
136 {
137 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
138 need_write - write_data.size_);
139 }
140 STM32_CleanDCacheByAddr(tx.addr_, need_write);
141 read_buff_ = {nullptr, 0};
142
143 st = HAL_SPI_Transmit_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write);
144 }
145 else if (read_data.size_ > 0)
146 {
147 read_buff_ = read_data;
148
149 st = HAL_SPI_Receive_DMA(spi_handle_, static_cast<uint8_t*>(rx.addr_),
150 read_data.size_);
151 }
152 else
153 {
154 if (op.type != OperationRW::OperationType::BLOCK)
155 {
156 op.UpdateStatus(in_isr, ErrorCode::OK);
157 }
158 return ErrorCode::OK;
159 }
160
161 if (st != HAL_OK)
162 {
163 if (op.type == OperationRW::OperationType::BLOCK)
164 {
165 block_wait_.Cancel();
166 }
167 return ErrorCode::BUSY;
168 }
169
170 op.MarkAsRunning();
171 if (op.type == OperationRW::OperationType::BLOCK)
172 {
173 return block_wait_.Wait(op.data.sem_info.timeout);
174 }
175 return ErrorCode::OK;
176 }
177
179
180 if (write_data.size_ > 0 && read_data.size_ > 0)
181 {
182 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
183 if (write_data.size_ < need_write)
184 {
185 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
186 need_write - write_data.size_);
187 }
188 STM32_CleanDCacheByAddr(tx.addr_, need_write);
189 ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
190 static_cast<uint8_t*>(rx.addr_), need_write,
191 20) == HAL_OK)
194
195 if (ans == ErrorCode::OK)
196 {
197 Memory::FastCopy(read_data.addr_, rx.addr_, read_data.size_);
198 }
199 SwitchBuffer();
200 }
201 else if (read_data.size_ > 0)
202 {
203 ans = (HAL_SPI_Receive(spi_handle_, static_cast<uint8_t*>(rx.addr_), read_data.size_,
204 20) == HAL_OK)
207
208 if (ans == ErrorCode::OK)
209 {
210 Memory::FastCopy(read_data.addr_, rx.addr_, read_data.size_);
211 }
212 SwitchBuffer();
213 }
214 else if (write_data.size_ > 0)
215 {
216 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
217 STM32_CleanDCacheByAddr(tx.addr_, need_write);
218 ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
219 write_data.size_, 20) == HAL_OK)
222
223 SwitchBuffer();
224 }
225 else
226 {
227 if (op.type != OperationRW::OperationType::BLOCK)
228 {
229 op.UpdateStatus(in_isr, ErrorCode::OK);
230 }
231 return ErrorCode::OK;
232 }
233
234 if (op.type != OperationRW::OperationType::BLOCK)
235 {
236 op.UpdateStatus(in_isr, ans);
237 }
238 return ans;
239}
240
242{
243 switch (config.clock_polarity)
244 {
246 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
247 break;
249 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
250 break;
251 }
252
253 switch (config.clock_phase)
254 {
256 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
257 break;
259 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
260 break;
261 }
262
263 bool ok = true;
264 uint32_t hal_presc = 0;
265
266 switch (config.prescaler)
267 {
268#ifdef SPI_BAUDRATEPRESCALER_1
269 case Prescaler::DIV_1:
270 hal_presc = SPI_BAUDRATEPRESCALER_1;
271 break;
272#endif
273#ifdef SPI_BAUDRATEPRESCALER_2
274 case Prescaler::DIV_2:
275 hal_presc = SPI_BAUDRATEPRESCALER_2;
276 break;
277#endif
278#ifdef SPI_BAUDRATEPRESCALER_4
279 case Prescaler::DIV_4:
280 hal_presc = SPI_BAUDRATEPRESCALER_4;
281 break;
282#endif
283#ifdef SPI_BAUDRATEPRESCALER_8
284 case Prescaler::DIV_8:
285 hal_presc = SPI_BAUDRATEPRESCALER_8;
286 break;
287#endif
288#ifdef SPI_BAUDRATEPRESCALER_16
290 hal_presc = SPI_BAUDRATEPRESCALER_16;
291 break;
292#endif
293#ifdef SPI_BAUDRATEPRESCALER_32
295 hal_presc = SPI_BAUDRATEPRESCALER_32;
296 break;
297#endif
298#ifdef SPI_BAUDRATEPRESCALER_64
300 hal_presc = SPI_BAUDRATEPRESCALER_64;
301 break;
302#endif
303#ifdef SPI_BAUDRATEPRESCALER_128
305 hal_presc = SPI_BAUDRATEPRESCALER_128;
306 break;
307#endif
308#ifdef SPI_BAUDRATEPRESCALER_256
310 hal_presc = SPI_BAUDRATEPRESCALER_256;
311 break;
312#endif
313#ifdef SPI_BAUDRATEPRESCALER_512
315 hal_presc = SPI_BAUDRATEPRESCALER_512;
316 break;
317#endif
318#ifdef SPI_BAUDRATEPRESCALER_1024
320 hal_presc = SPI_BAUDRATEPRESCALER_1024;
321 break;
322#endif
323 default:
324 ok = false;
325 break;
326 }
327
328 if (!ok)
329 {
331 }
332
333 spi_handle_->Init.BaudRatePrescaler = hal_presc;
334
335 GetConfig() = config;
336
337 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
338}
339
340ErrorCode STM32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW& op, bool in_isr)
341{
342 uint32_t need_read = read_data.size_;
343
344 if (spi_handle_->State != HAL_SPI_STATE_READY)
345 {
346 return ErrorCode::BUSY;
347 }
348
349 RawData rx = GetRxBuffer();
350 RawData tx = GetTxBuffer();
351
352 ASSERT(rx.size_ >= need_read + 1);
353 ASSERT(tx.size_ >= need_read + 1);
354
355 if (need_read + 1 > dma_enable_min_size_)
356 {
357 mem_read_ = true;
358 rw_op_ = op;
359 if (op.type == OperationRW::OperationType::BLOCK)
360 {
361 block_wait_.Start(*op.data.sem_info.sem);
362 }
363
364 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
365 Memory::FastSet(txb, 0, need_read + 1);
366 txb[0] = static_cast<uint8_t>(reg | 0x80);
367 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
368 read_buff_ = read_data;
369
370 HAL_StatusTypeDef st =
371 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
372 static_cast<uint8_t*>(rx.addr_), need_read + 1);
373
374 if (st != HAL_OK)
375 {
376 if (op.type == OperationRW::OperationType::BLOCK)
377 {
378 block_wait_.Cancel();
379 }
380 return ErrorCode::BUSY;
381 }
382
383 op.MarkAsRunning();
384 if (op.type == OperationRW::OperationType::BLOCK)
385 {
386 return block_wait_.Wait(op.data.sem_info.timeout);
387 }
388 return ErrorCode::OK;
389 }
390
391 mem_read_ = false;
392 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
393 Memory::FastSet(txb, 0, need_read + 1);
394 txb[0] = static_cast<uint8_t>(reg | 0x80);
395 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
396
397 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
398 static_cast<uint8_t*>(rx.addr_), need_read + 1,
399 20) == HAL_OK)
402
403 if (ans == ErrorCode::OK)
404 {
405 uint8_t* rxb = reinterpret_cast<uint8_t*>(rx.addr_);
406 Memory::FastCopy(read_data.addr_, rxb + 1, need_read);
407 }
408 SwitchBuffer();
409
410 if (op.type != OperationRW::OperationType::BLOCK)
411 {
412 op.UpdateStatus(in_isr, ans);
413 }
414 return ans;
415}
416
418 bool in_isr)
419{
420 uint32_t need_write = write_data.size_;
421
422 if (spi_handle_->State != HAL_SPI_STATE_READY)
423 {
424 return ErrorCode::BUSY;
425 }
426
427 RawData tx = GetTxBuffer();
428 ASSERT(tx.size_ >= need_write + 1);
429
430 if (need_write + 1 > dma_enable_min_size_)
431 {
432 mem_read_ = false;
433 rw_op_ = op;
434 if (op.type == OperationRW::OperationType::BLOCK)
435 {
436 block_wait_.Start(*op.data.sem_info.sem);
437 }
438
439 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
440 txb[0] = static_cast<uint8_t>(reg & 0x7F);
441 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
442 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
443 read_buff_ = {nullptr, 0};
444
445 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
446 spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write + 1);
447
448 if (st != HAL_OK)
449 {
450 if (op.type == OperationRW::OperationType::BLOCK)
451 {
452 block_wait_.Cancel();
453 }
454 return ErrorCode::BUSY;
455 }
456
457 op.MarkAsRunning();
458 if (op.type == OperationRW::OperationType::BLOCK)
459 {
460 return block_wait_.Wait(op.data.sem_info.timeout);
461 }
462 return ErrorCode::OK;
463 }
464
465 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
466 txb[0] = static_cast<uint8_t>(reg & 0x7F);
467 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
468 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
469
470 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
471 need_write + 1, 20) == HAL_OK)
474
475 SwitchBuffer();
476
477 if (op.type != OperationRW::OperationType::BLOCK)
478 {
479 op.UpdateStatus(in_isr, ans);
480 }
481 return ans;
482}
483
485{
486 SPI_TypeDef* inst = spi_handle_ ? spi_handle_->Instance : nullptr;
487 if (!inst)
488 {
489 return 0u;
490 }
491
492#if defined(HAL_RCC_MODULE_ENABLED)
493// 1) 优先读取独立 SPI 内核时钟。
494// 1) Prefer dedicated SPI kernel clock when available.
495// H7: 分组宏 SPI123 / SPI45 / SPI6
496#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
497 defined(RCC_PERIPHCLK_SPI6)
498 // SPI1/2/3 → RCC_PERIPHCLK_SPI123
499 if (
500#ifdef SPI1
501 inst == SPI1 ||
502#endif
503#ifdef SPI2
504 inst == SPI2 ||
505#endif
506#ifdef SPI3
507 inst == SPI3 ||
508#endif
509 false)
510 {
511#ifdef RCC_PERIPHCLK_SPI123
512 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
513#endif
514 }
515 // SPI4/5 → RCC_PERIPHCLK_SPI45
516 if (
517#ifdef SPI4
518 inst == SPI4 ||
519#endif
520#ifdef SPI5
521 inst == SPI5 ||
522#endif
523 false)
524 {
525#ifdef RCC_PERIPHCLK_SPI45
526 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
527#endif
528 }
529// SPI6 → RCC_PERIPHCLK_SPI6
530#ifdef SPI6
531 if (inst == SPI6)
532 {
533#ifdef RCC_PERIPHCLK_SPI6
534 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
535#endif
536 }
537#endif
538#endif // H7 分组
539
540// 其它系列:通常是逐个 SPIx 宏
541#if defined(RCC_PERIPHCLK_SPI1)
542#ifdef SPI1
543 if (inst == SPI1) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
544#endif
545#endif
546#if defined(RCC_PERIPHCLK_SPI2)
547#ifdef SPI2
548 if (inst == SPI2) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
549#endif
550#endif
551#if defined(RCC_PERIPHCLK_SPI3)
552#ifdef SPI3
553 if (inst == SPI3) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
554#endif
555#endif
556#if defined(RCC_PERIPHCLK_SPI4)
557#ifdef SPI4
558 if (inst == SPI4) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
559#endif
560#endif
561#if defined(RCC_PERIPHCLK_SPI5)
562#ifdef SPI5
563 if (inst == SPI5) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
564#endif
565#endif
566#if defined(RCC_PERIPHCLK_SPI6)
567#ifdef SPI6
568 if (inst == SPI6) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
569#endif
570#endif
571#endif // HAL_RCC_MODULE_ENABLED
572
573 // 2) 回退到所在 APB 的 PCLK。
574 // 2) Fallback to APB PCLK if no dedicated kernel clock is available.
575#if defined(STM32H7) && defined(SPI6)
576 if (inst == SPI6)
577 {
578#if defined(HAL_RCC_GetPCLK4Freq)
579 return HAL_RCC_GetPCLK4Freq();
580#else
581 return HAL_RCC_GetHCLKFreq();
582#endif
583 }
584#endif
585
586 // 大多数系列:SPI1/4/5/6/7/8 → APB2; / SPI2/3 → APB1
587 if (
588#ifdef SPI1
589 inst == SPI1 ||
590#endif
591#ifdef SPI4
592 inst == SPI4 ||
593#endif
594#ifdef SPI5
595 inst == SPI5 ||
596#endif
597#ifdef SPI6
598 inst == SPI6 ||
599#endif
600#ifdef SPI7
601 inst == SPI7 ||
602#endif
603#ifdef SPI8
604 inst == SPI8 ||
605#endif
606 false)
607 {
608#if defined(HAL_RCC_GetPCLK2Freq)
609 return HAL_RCC_GetPCLK2Freq();
610#elif defined(HAL_RCC_GetPCLK1Freq)
611 return HAL_RCC_GetPCLK1Freq(); // 低端/单APB系列兜底
612#else
613 return HAL_RCC_GetHCLKFreq();
614#endif
615 }
616 else
617 {
618#if defined(HAL_RCC_GetPCLK1Freq)
619 return HAL_RCC_GetPCLK1Freq();
620#elif defined(HAL_RCC_GetPCLK2Freq)
621 return HAL_RCC_GetPCLK2Freq();
622#else
623 return HAL_RCC_GetHCLKFreq();
624#endif
625 }
626}
627
629{
630#if defined(SPI_BAUDRATEPRESCALER_1024)
631 return Prescaler::DIV_1024;
632#elif defined(SPI_BAUDRATEPRESCALER_512)
633 return Prescaler::DIV_512;
634#elif defined(SPI_BAUDRATEPRESCALER_256)
635 return Prescaler::DIV_256;
636#elif defined(SPI_BAUDRATEPRESCALER_128)
637 return Prescaler::DIV_128;
638#elif defined(SPI_BAUDRATEPRESCALER_64)
639 return Prescaler::DIV_64;
640#elif defined(SPI_BAUDRATEPRESCALER_32)
641 return Prescaler::DIV_32;
642#elif defined(SPI_BAUDRATEPRESCALER_16)
643 return Prescaler::DIV_16;
644#elif defined(SPI_BAUDRATEPRESCALER_8)
645 return Prescaler::DIV_8;
646#elif defined(SPI_BAUDRATEPRESCALER_4)
647 return Prescaler::DIV_4;
648#elif defined(SPI_BAUDRATEPRESCALER_2)
649 return Prescaler::DIV_2;
650#elif defined(SPI_BAUDRATEPRESCALER_1)
651 return Prescaler::DIV_1;
652#else
653 return Prescaler::UNKNOWN;
654#endif
655}
656
657ErrorCode STM32SPI::Transfer(size_t size, OperationRW& op, bool in_isr)
658{
659 if (spi_handle_->State != HAL_SPI_STATE_READY)
660 {
661 return ErrorCode::BUSY;
662 }
663
664 if (size == 0)
665 {
666 if (op.type != OperationRW::OperationType::BLOCK)
667 {
668 op.UpdateStatus(in_isr, ErrorCode::OK);
669 }
670 return ErrorCode::OK;
671 }
672
673 RawData rx = GetRxBuffer();
674 RawData tx = GetTxBuffer();
675
676 const uint16_t xfer = static_cast<uint16_t>(size);
677
678 if (size > dma_enable_min_size_)
679 {
680 rw_op_ = op;
681 if (op.type == OperationRW::OperationType::BLOCK)
682 {
683 block_wait_.Start(*op.data.sem_info.sem);
684 }
685
688
689 HAL_StatusTypeDef st =
690 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
691 static_cast<uint8_t*>(rx.addr_), xfer);
692
693 if (st != HAL_OK)
694 {
695 if (op.type == OperationRW::OperationType::BLOCK)
696 {
697 block_wait_.Cancel();
698 }
699 return ErrorCode::BUSY;
700 }
701
702 op.MarkAsRunning();
703 if (op.type == OperationRW::OperationType::BLOCK)
704 {
705 return block_wait_.Wait(op.data.sem_info.timeout);
706 }
707 return ErrorCode::OK;
708 }
709
710 ErrorCode ans =
711 (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
712 static_cast<uint8_t*>(rx.addr_), xfer, 20) == HAL_OK)
715
717
718 SwitchBuffer();
719
720 if (op.type != OperationRW::OperationType::BLOCK)
721 {
722 op.UpdateStatus(in_isr, ans);
723 }
724 return ans;
725}
726
727extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
728{
729 const auto spi_id = STM32_SPI_GetID(hspi->Instance);
730 STM32SPI* spi = (spi_id == STM32_SPI_ID_ERROR) ? nullptr : STM32SPI::map[spi_id];
731 if (spi == nullptr)
732 {
733 return;
734 }
735 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
736 {
737 return;
738 }
739 spi->SwitchBuffer();
740 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
741 {
742 (void)spi->block_wait_.TryPost(true, ErrorCode::OK);
743 }
744 else
745 {
746 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
747 }
748}
749
750extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
751{
752 const auto spi_id = STM32_SPI_GetID(hspi->Instance);
753 STM32SPI* spi = (spi_id == STM32_SPI_ID_ERROR) ? nullptr : STM32SPI::map[spi_id];
754 if (spi == nullptr)
755 {
756 return;
757 }
758 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
759 {
760 return;
761 }
762
763 RawData rx = spi->GetRxBuffer();
764 const bool has_user_read_copy = (spi->read_buff_.size_ > 0);
765
766 if (has_user_read_copy)
767 {
768 if (!spi->mem_read_)
769 {
770 STM32_InvalidateDCacheByAddr(rx.addr_, spi->read_buff_.size_);
771 Memory::FastCopy(spi->read_buff_.addr_, rx.addr_, spi->read_buff_.size_);
772 }
773 else
774 {
775 STM32_InvalidateDCacheByAddr(rx.addr_, spi->read_buff_.size_ + 1);
776 uint8_t* rx_dma_buff = reinterpret_cast<uint8_t*>(rx.addr_);
777 Memory::FastCopy(spi->read_buff_.addr_, rx_dma_buff + 1, spi->read_buff_.size_);
778 }
779 spi->read_buff_.size_ = 0;
780 }
781
782 spi->SwitchBuffer();
783 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
784 {
785 (void)spi->block_wait_.TryPost(true, ErrorCode::OK);
786 }
787 else
788 {
789 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
790 }
791}
792
793extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
794{
795 HAL_SPI_RxCpltCallback(hspi);
796}
797
798extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
799{
800 const auto spi_id = STM32_SPI_GetID(hspi->Instance);
801 STM32SPI* spi = (spi_id == STM32_SPI_ID_ERROR) ? nullptr : STM32SPI::map[spi_id];
802 if (spi == nullptr)
803 {
804 return;
805 }
806 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
807 {
808 return;
809 }
810 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
811 {
812 (void)spi->block_wait_.TryPost(true, ErrorCode::FAILED);
813 }
814 else
815 {
816 spi->rw_op_.UpdateStatus(true, ErrorCode::FAILED);
817 }
818}
819
820#endif
bool TryPost(bool in_isr, ErrorCode ec)
尝试认领完成并唤醒调用者 / Try to claim completion and wake the caller.
void Start(Semaphore &sem)
绑定信号量并开始等待 / Bind a semaphore and start waiting.
ErrorCode Wait(uint32_t timeout)
等待完成或超时交接 / Wait for completion or a timeout handoff.
void Cancel()
清除等待状态,不发送通知 / Clear the wait state without posting.
只读原始数据视图 / Immutable raw data view
size_t size_
数据字节数 / Data size in bytes
const void * addr_
数据起始地址 / Data start address
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
uint32_t timeout
等待超时值 / Wait timeout.
void UpdateStatus(bool in_isr, Status &&status)
按通知方式报告完成结果 / Report completion using the selected mode.
union LibXR::Operation::@6 data
完成通知对象,由 type 选择有效成员 / Notification target selected by type.
void MarkAsRunning()
标记轮询操作正在执行 / Mark a polling operation as running.
Semaphore * sem
借用的信号量 / Borrowed semaphore.
OperationType type
当前通知方式 / Current notification mode.
可写原始数据视图 / Mutable raw data view
size_t size_
数据字节数 / Data size in bytes
void * addr_
数据起始地址 / Data start address
串行外设接口(SPI)抽象类。 Abstract class for Serial Peripheral Interface (SPI).
Definition spi.hpp:15
@ EDGE_2
在第二个时钟边沿采样数据 / Data sampled on the second clock edge.
@ 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.
@ DIV_1
分频系数为 1 / Division factor is 1.
@ 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:307
void SwitchBuffer()
切换缓冲区 / Switches the buffer.
Definition spi.hpp:338
RawData GetTxBuffer()
获取发送数据的缓冲区 / Gets the buffer for storing data to be sent.
Definition spi.hpp:323
@ LOW
时钟空闲时为低电平 / Clock idle low.
@ HIGH
时钟空闲时为高电平 / Clock idle high.
Configuration & GetConfig()
获取 SPI 配置参数 / Gets the SPI configuration parameters.
Definition spi.hpp:397
STM32 SPI 驱动实现 / STM32 SPI driver implementation.
Definition stm32_spi.hpp:55
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.
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.
STM32SPI(SPI_HandleTypeDef *spi_handle, RawData dma_buff_rx, RawData dma_buff_tx, uint32_t dma_enable_min_size=3)
构造 SPI 对象 / Construct SPI object
Definition stm32_spi.cpp:72
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度 / Gets the maximum clock speed of the SPI device.
ErrorCode Transfer(size_t size, OperationRW &op, bool in_isr) override
进行一次SPI传输(使用当前缓冲区数据,零拷贝,支持双缓冲)。 Performs a SPI transfer (zero-copy, supports double buffering).
ErrorCode SetConfig(SPI::Configuration config) override
设置 SPI 配置参数 / Sets SPI configuration parameters.
Prescaler GetMaxPrescaler() const override
获取 SPI 设备的最大分频系数 / Gets the maximum prescaler of the SPI device.
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op, bool in_isr) override
进行 SPI 读写操作 / Performs SPI read and write operations.
Definition stm32_spi.cpp:84
LibXR 命名空间 / LibXR namespace.
Definition ch32_can.hpp:14
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
失效指定内存范围覆盖的 D-Cache cache line Invalidates D-Cache lines covering the specified memory range
ErrorCode
定义错误码枚举 / Defines an enumeration for error codes
@ BUSY
忙碌 / Busy
@ NOT_SUPPORT
不支持 / Not supported
@ FAILED
操作失败 / Operation failed
@ OK
操作成功 / Operation successful
constexpr auto max(LeftType a, RightType b) -> std::common_type_t< LeftType, RightType >
计算两个数的最大值 / Computes the maximum of two numbers
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
清理指定内存范围覆盖的 D-Cache cache line Cleans D-Cache lines covering the specified memory range
存储 SPI 配置参数的结构体。 Structure for storing SPI configuration parameters.
Definition spi.hpp:86
ClockPhase clock_phase
SPI 时钟相位 / SPI clock phase.
Definition spi.hpp:89
Prescaler prescaler
SPI 分频系数 / SPI prescaler.
Definition spi.hpp:90
ClockPolarity clock_polarity
SPI 时钟极性 / SPI clock polarity.
Definition spi.hpp:87