libxr  1.0
Want to be the best embedded framework
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 ASSERT(ok);
329 if (!ok)
330 {
332 }
333
334 spi_handle_->Init.BaudRatePrescaler = hal_presc;
335
336 GetConfig() = config;
337
338 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
339}
340
341ErrorCode STM32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW& op, bool in_isr)
342{
343 uint32_t need_read = read_data.size_;
344
345 if (spi_handle_->State != HAL_SPI_STATE_READY)
346 {
347 return ErrorCode::BUSY;
348 }
349
350 RawData rx = GetRxBuffer();
351 RawData tx = GetTxBuffer();
352
353 ASSERT(rx.size_ >= need_read + 1);
354 ASSERT(tx.size_ >= need_read + 1);
355
356 if (need_read + 1 > dma_enable_min_size_)
357 {
358 mem_read_ = true;
359 rw_op_ = op;
360 if (op.type == OperationRW::OperationType::BLOCK)
361 {
362 block_wait_.Start(*op.data.sem_info.sem);
363 }
364
365 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
366 Memory::FastSet(txb, 0, need_read + 1);
367 txb[0] = static_cast<uint8_t>(reg | 0x80);
368 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
369 read_buff_ = read_data;
370
371 HAL_StatusTypeDef st =
372 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
373 static_cast<uint8_t*>(rx.addr_), need_read + 1);
374
375 if (st != HAL_OK)
376 {
377 if (op.type == OperationRW::OperationType::BLOCK)
378 {
379 block_wait_.Cancel();
380 }
381 return ErrorCode::BUSY;
382 }
383
384 op.MarkAsRunning();
385 if (op.type == OperationRW::OperationType::BLOCK)
386 {
387 return block_wait_.Wait(op.data.sem_info.timeout);
388 }
389 return ErrorCode::OK;
390 }
391
392 mem_read_ = false;
393 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
394 Memory::FastSet(txb, 0, need_read + 1);
395 txb[0] = static_cast<uint8_t>(reg | 0x80);
396 STM32_CleanDCacheByAddr(tx.addr_, need_read + 1);
397
398 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
399 static_cast<uint8_t*>(rx.addr_), need_read + 1,
400 20) == HAL_OK)
403
404 if (ans == ErrorCode::OK)
405 {
406 uint8_t* rxb = reinterpret_cast<uint8_t*>(rx.addr_);
407 Memory::FastCopy(read_data.addr_, rxb + 1, need_read);
408 }
409 SwitchBuffer();
410
411 if (op.type != OperationRW::OperationType::BLOCK)
412 {
413 op.UpdateStatus(in_isr, ans);
414 }
415 return ans;
416}
417
419 bool in_isr)
420{
421 uint32_t need_write = write_data.size_;
422
423 if (spi_handle_->State != HAL_SPI_STATE_READY)
424 {
425 return ErrorCode::BUSY;
426 }
427
428 RawData tx = GetTxBuffer();
429 ASSERT(tx.size_ >= need_write + 1);
430
431 if (need_write + 1 > dma_enable_min_size_)
432 {
433 mem_read_ = false;
434 rw_op_ = op;
435 if (op.type == OperationRW::OperationType::BLOCK)
436 {
437 block_wait_.Start(*op.data.sem_info.sem);
438 }
439
440 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
441 txb[0] = static_cast<uint8_t>(reg & 0x7F);
442 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
443 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
444 read_buff_ = {nullptr, 0};
445
446 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
447 spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write + 1);
448
449 if (st != HAL_OK)
450 {
451 if (op.type == OperationRW::OperationType::BLOCK)
452 {
453 block_wait_.Cancel();
454 }
455 return ErrorCode::BUSY;
456 }
457
458 op.MarkAsRunning();
459 if (op.type == OperationRW::OperationType::BLOCK)
460 {
461 return block_wait_.Wait(op.data.sem_info.timeout);
462 }
463 return ErrorCode::OK;
464 }
465
466 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
467 txb[0] = static_cast<uint8_t>(reg & 0x7F);
468 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
469 STM32_CleanDCacheByAddr(tx.addr_, need_write + 1);
470
471 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
472 need_write + 1, 20) == HAL_OK)
475
476 SwitchBuffer();
477
478 if (op.type != OperationRW::OperationType::BLOCK)
479 {
480 op.UpdateStatus(in_isr, ans);
481 }
482 return ans;
483}
484
486{
487 SPI_TypeDef* inst = spi_handle_ ? spi_handle_->Instance : nullptr;
488 if (!inst)
489 {
490 return 0u;
491 }
492
493#if defined(HAL_RCC_MODULE_ENABLED)
494// 1) 优先读取独立 SPI 内核时钟。
495// 1) Prefer dedicated SPI kernel clock when available.
496// H7: 分组宏 SPI123 / SPI45 / SPI6
497#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
498 defined(RCC_PERIPHCLK_SPI6)
499 // SPI1/2/3 → RCC_PERIPHCLK_SPI123
500 if (
501#ifdef SPI1
502 inst == SPI1 ||
503#endif
504#ifdef SPI2
505 inst == SPI2 ||
506#endif
507#ifdef SPI3
508 inst == SPI3 ||
509#endif
510 false)
511 {
512#ifdef RCC_PERIPHCLK_SPI123
513 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
514#endif
515 }
516 // SPI4/5 → RCC_PERIPHCLK_SPI45
517 if (
518#ifdef SPI4
519 inst == SPI4 ||
520#endif
521#ifdef SPI5
522 inst == SPI5 ||
523#endif
524 false)
525 {
526#ifdef RCC_PERIPHCLK_SPI45
527 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
528#endif
529 }
530// SPI6 → RCC_PERIPHCLK_SPI6
531#ifdef SPI6
532 if (inst == SPI6)
533 {
534#ifdef RCC_PERIPHCLK_SPI6
535 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
536#endif
537 }
538#endif
539#endif // H7 分组
540
541// 其它系列:通常是逐个 SPIx 宏
542#if defined(RCC_PERIPHCLK_SPI1)
543#ifdef SPI1
544 if (inst == SPI1) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
545#endif
546#endif
547#if defined(RCC_PERIPHCLK_SPI2)
548#ifdef SPI2
549 if (inst == SPI2) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
550#endif
551#endif
552#if defined(RCC_PERIPHCLK_SPI3)
553#ifdef SPI3
554 if (inst == SPI3) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
555#endif
556#endif
557#if defined(RCC_PERIPHCLK_SPI4)
558#ifdef SPI4
559 if (inst == SPI4) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
560#endif
561#endif
562#if defined(RCC_PERIPHCLK_SPI5)
563#ifdef SPI5
564 if (inst == SPI5) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
565#endif
566#endif
567#if defined(RCC_PERIPHCLK_SPI6)
568#ifdef SPI6
569 if (inst == SPI6) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
570#endif
571#endif
572#endif // HAL_RCC_MODULE_ENABLED
573
574 // 2) 回退到所在 APB 的 PCLK。
575 // 2) Fallback to APB PCLK if no dedicated kernel clock is available.
576#if defined(STM32H7) && defined(SPI6)
577 if (inst == SPI6)
578 {
579#if defined(HAL_RCC_GetPCLK4Freq)
580 return HAL_RCC_GetPCLK4Freq();
581#else
582 return HAL_RCC_GetHCLKFreq();
583#endif
584 }
585#endif
586
587 // 大多数系列:SPI1/4/5/6/7/8 → APB2;SPI2/3 → APB1
588 if (
589#ifdef SPI1
590 inst == SPI1 ||
591#endif
592#ifdef SPI4
593 inst == SPI4 ||
594#endif
595#ifdef SPI5
596 inst == SPI5 ||
597#endif
598#ifdef SPI6
599 inst == SPI6 ||
600#endif
601#ifdef SPI7
602 inst == SPI7 ||
603#endif
604#ifdef SPI8
605 inst == SPI8 ||
606#endif
607 false)
608 {
609#if defined(HAL_RCC_GetPCLK2Freq)
610 return HAL_RCC_GetPCLK2Freq();
611#elif defined(HAL_RCC_GetPCLK1Freq)
612 return HAL_RCC_GetPCLK1Freq(); // 低端/单APB系列兜底
613#else
614 return HAL_RCC_GetHCLKFreq();
615#endif
616 }
617 else
618 {
619#if defined(HAL_RCC_GetPCLK1Freq)
620 return HAL_RCC_GetPCLK1Freq();
621#elif defined(HAL_RCC_GetPCLK2Freq)
622 return HAL_RCC_GetPCLK2Freq();
623#else
624 return HAL_RCC_GetHCLKFreq();
625#endif
626 }
627}
628
630{
631#if defined(SPI_BAUDRATEPRESCALER_1024)
632 return Prescaler::DIV_1024;
633#elif defined(SPI_BAUDRATEPRESCALER_512)
634 return Prescaler::DIV_512;
635#elif defined(SPI_BAUDRATEPRESCALER_256)
636 return Prescaler::DIV_256;
637#elif defined(SPI_BAUDRATEPRESCALER_128)
638 return Prescaler::DIV_128;
639#elif defined(SPI_BAUDRATEPRESCALER_64)
640 return Prescaler::DIV_64;
641#elif defined(SPI_BAUDRATEPRESCALER_32)
642 return Prescaler::DIV_32;
643#elif defined(SPI_BAUDRATEPRESCALER_16)
644 return Prescaler::DIV_16;
645#elif defined(SPI_BAUDRATEPRESCALER_8)
646 return Prescaler::DIV_8;
647#elif defined(SPI_BAUDRATEPRESCALER_4)
648 return Prescaler::DIV_4;
649#elif defined(SPI_BAUDRATEPRESCALER_2)
650 return Prescaler::DIV_2;
651#elif defined(SPI_BAUDRATEPRESCALER_1)
652 return Prescaler::DIV_1;
653#else
654 return Prescaler::UNKNOWN;
655#endif
656}
657
658ErrorCode STM32SPI::Transfer(size_t size, OperationRW& op, bool in_isr)
659{
660 if (spi_handle_->State != HAL_SPI_STATE_READY)
661 {
662 return ErrorCode::BUSY;
663 }
664
665 if (size == 0)
666 {
667 if (op.type != OperationRW::OperationType::BLOCK)
668 {
669 op.UpdateStatus(in_isr, ErrorCode::OK);
670 }
671 return ErrorCode::OK;
672 }
673
674 RawData rx = GetRxBuffer();
675 RawData tx = GetTxBuffer();
676
677 const uint16_t xfer = static_cast<uint16_t>(size);
678
679 if (size > dma_enable_min_size_)
680 {
681 rw_op_ = op;
682 if (op.type == OperationRW::OperationType::BLOCK)
683 {
684 block_wait_.Start(*op.data.sem_info.sem);
685 }
686
689
690 HAL_StatusTypeDef st =
691 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
692 static_cast<uint8_t*>(rx.addr_), xfer);
693
694 if (st != HAL_OK)
695 {
696 if (op.type == OperationRW::OperationType::BLOCK)
697 {
698 block_wait_.Cancel();
699 }
700 return ErrorCode::BUSY;
701 }
702
703 op.MarkAsRunning();
704 if (op.type == OperationRW::OperationType::BLOCK)
705 {
706 return block_wait_.Wait(op.data.sem_info.timeout);
707 }
708 return ErrorCode::OK;
709 }
710
711 ErrorCode ans =
712 (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
713 static_cast<uint8_t*>(rx.addr_), xfer, 20) == HAL_OK)
716
718
719 SwitchBuffer();
720
721 if (op.type != OperationRW::OperationType::BLOCK)
722 {
723 op.UpdateStatus(in_isr, ans);
724 }
725 return ans;
726}
727
728extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
729{
730 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
731 ASSERT(spi != nullptr);
732 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
733 {
734 return;
735 }
736 spi->SwitchBuffer();
737 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
738 {
739 (void)spi->block_wait_.TryPost(true, ErrorCode::OK);
740 }
741 else
742 {
743 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
744 }
745}
746
747extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
748{
749 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
750 ASSERT(spi != nullptr);
751 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
752 {
753 return;
754 }
755
756 RawData rx = spi->GetRxBuffer();
757 const bool has_user_read_copy = (spi->read_buff_.size_ > 0);
758
759 if (has_user_read_copy)
760 {
761 if (!spi->mem_read_)
762 {
763 STM32_InvalidateDCacheByAddr(rx.addr_, spi->read_buff_.size_);
764 Memory::FastCopy(spi->read_buff_.addr_, rx.addr_, spi->read_buff_.size_);
765 }
766 else
767 {
768 STM32_InvalidateDCacheByAddr(rx.addr_, spi->read_buff_.size_ + 1);
769 uint8_t* rx_dma_buff = reinterpret_cast<uint8_t*>(rx.addr_);
770 Memory::FastCopy(spi->read_buff_.addr_, rx_dma_buff + 1, spi->read_buff_.size_);
771 }
772 spi->read_buff_.size_ = 0;
773 }
774
775 spi->SwitchBuffer();
776 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
777 {
778 (void)spi->block_wait_.TryPost(true, ErrorCode::OK);
779 }
780 else
781 {
782 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
783 }
784}
785
786extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
787{
788 HAL_SPI_RxCpltCallback(hspi);
789}
790
791extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
792{
793 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
794 ASSERT(spi != nullptr);
795 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
796 {
797 return;
798 }
799 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
800 {
801 (void)spi->block_wait_.TryPost(true, ErrorCode::FAILED);
802 }
803 else
804 {
805 spi->rw_op_.UpdateStatus(true, ErrorCode::FAILED);
806 }
807}
808
809#endif
只读原始数据视图 / 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
Definition libxr_mem.cpp:5
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
OperationType type
可写原始数据视图 / 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:14
@ 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: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.
@ HIGH
时钟空闲时为高电平。Clock idle high.
Configuration & GetConfig()
获取 SPI 配置参数。Gets the SPI configuration parameters.
Definition spi.hpp:396
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 命名空间
Definition ch32_can.hpp:14
void STM32_InvalidateDCacheByAddr(const void *addr, size_t size)
Invalidates D-Cache lines covering the specified memory range.
ErrorCode
定义错误码枚举
@ 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 >
计算两个数的最大值
void STM32_CleanDCacheByAddr(const void *addr, size_t size)
Cleans D-Cache lines covering the specified memory range.
存储 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