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
5#ifdef HAL_SPI_MODULE_ENABLED
6
7using namespace LibXR;
8
9STM32SPI* STM32SPI::map[STM32_SPI_NUMBER] = {nullptr};
10
11stm32_spi_id_t STM32_SPI_GetID(SPI_TypeDef* addr)
12{
13 if (addr == nullptr)
14 { // NOLINT
15 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
16 }
17#ifdef SPI1
18 else if (addr == SPI1)
19 { // NOLINT
20 return stm32_spi_id_t::STM32_SPI1;
21 }
22#endif
23#ifdef SPI2
24 else if (addr == SPI2)
25 { // NOLINT
26 return stm32_spi_id_t::STM32_SPI2;
27 }
28#endif
29#ifdef SPI3
30 else if (addr == SPI3)
31 { // NOLINT
32 return stm32_spi_id_t::STM32_SPI3;
33 }
34#endif
35#ifdef SPI4
36 else if (addr == SPI4)
37 { // NOLINT
38 return stm32_spi_id_t::STM32_SPI4;
39 }
40#endif
41#ifdef SPI5
42 else if (addr == SPI5)
43 { // NOLINT
44 return stm32_spi_id_t::STM32_SPI5;
45 }
46#endif
47#ifdef SPI6
48 else if (addr == SPI6)
49 { // NOLINT
50 return stm32_spi_id_t::STM32_SPI6;
51 }
52#endif
53#ifdef SPI7
54 else if (addr == SPI7)
55 { // NOLINT
56 return stm32_spi_id_t::STM32_SPI7;
57 }
58#endif
59#ifdef SPI8
60 else if (addr == SPI8)
61 { // NOLINT
62 return stm32_spi_id_t::STM32_SPI8;
63 }
64#endif
65 else
66 {
67 return stm32_spi_id_t::STM32_SPI_ID_ERROR;
68 }
69}
70
71STM32SPI::STM32SPI(SPI_HandleTypeDef* spi_handle, RawData rx, RawData tx,
72 uint32_t dma_enable_min_size)
73 : SPI(rx, tx),
74 spi_handle_(spi_handle),
75 id_(STM32_SPI_GetID(spi_handle_->Instance)),
76 dma_enable_min_size_(dma_enable_min_size)
77{
78 ASSERT(id_ != STM32_SPI_ID_ERROR);
79
80 map[id_] = this;
81}
82
84 OperationRW& op, bool in_isr)
85{
86 uint32_t need_write = max(write_data.size_, read_data.size_);
87
88 RawData rx = GetRxBuffer();
89 RawData tx = GetTxBuffer();
90
91 if (rx.size_ > 0)
92 {
93 ASSERT(need_write <= rx.size_);
94 }
95 if (tx.size_ > 0)
96 {
97 ASSERT(need_write <= tx.size_);
98 }
99
100 if (spi_handle_->State != HAL_SPI_STATE_READY)
101 {
102 return ErrorCode::BUSY;
103 }
104
105 mem_read_ = false;
106
107 if (need_write > dma_enable_min_size_)
108 {
109 rw_op_ = op;
110 if (op.type == OperationRW::OperationType::BLOCK)
111 {
112 block_wait_.Start(*op.data.sem_info.sem);
113 }
114
115 HAL_StatusTypeDef st = HAL_OK;
116
117 if (write_data.size_ > 0 && read_data.size_ > 0)
118 {
119 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
120 if (write_data.size_ < need_write)
121 {
122 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
123 need_write - write_data.size_);
124 }
125#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
126 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
127 static_cast<int32_t>(need_write));
128#endif
129 read_buff_ = read_data;
130
131 st = HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
132 static_cast<uint8_t*>(rx.addr_), need_write);
133 }
134 else if (write_data.size_ > 0)
135 {
136 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
137 if (write_data.size_ < need_write)
138 {
139 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
140 need_write - write_data.size_);
141 }
142#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
143 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
144 static_cast<int32_t>(need_write));
145#endif
146 read_buff_ = {nullptr, 0};
147
148 st = HAL_SPI_Transmit_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write);
149 }
150 else if (read_data.size_ > 0)
151 {
152 read_buff_ = read_data;
153
154 st = HAL_SPI_Receive_DMA(spi_handle_, static_cast<uint8_t*>(rx.addr_),
155 read_data.size_);
156 }
157 else
158 {
159 if (op.type != OperationRW::OperationType::BLOCK)
160 {
161 op.UpdateStatus(in_isr, ErrorCode::OK);
162 }
163 return ErrorCode::OK;
164 }
165
166 if (st != HAL_OK)
167 {
168 if (op.type == OperationRW::OperationType::BLOCK)
169 {
170 block_wait_.Cancel();
171 }
172 return ErrorCode::BUSY;
173 }
174
175 op.MarkAsRunning();
176 if (op.type == OperationRW::OperationType::BLOCK)
177 {
178 return block_wait_.Wait(op.data.sem_info.timeout);
179 }
180 return ErrorCode::OK;
181 }
182
184
185 if (write_data.size_ > 0 && read_data.size_ > 0)
186 {
187 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
188 if (write_data.size_ < need_write)
189 {
190 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
191 need_write - write_data.size_);
192 }
193#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
194 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
195 static_cast<int32_t>(need_write));
196#endif
197 ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
198 static_cast<uint8_t*>(rx.addr_), need_write,
199 20) == HAL_OK)
202
203 if (ans == ErrorCode::OK)
204 {
205 Memory::FastCopy(read_data.addr_, rx.addr_, read_data.size_);
206 }
207 SwitchBuffer();
208 }
209 else if (read_data.size_ > 0)
210 {
211 ans = (HAL_SPI_Receive(spi_handle_, static_cast<uint8_t*>(rx.addr_), read_data.size_,
212 20) == HAL_OK)
215
216 if (ans == ErrorCode::OK)
217 {
218 Memory::FastCopy(read_data.addr_, rx.addr_, read_data.size_);
219 }
220 SwitchBuffer();
221 }
222 else if (write_data.size_ > 0)
223 {
224 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
225#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
226 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
227 static_cast<int32_t>(need_write));
228#endif
229 ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
230 write_data.size_, 20) == HAL_OK)
233
234 SwitchBuffer();
235 }
236 else
237 {
238 if (op.type != OperationRW::OperationType::BLOCK)
239 {
240 op.UpdateStatus(in_isr, ErrorCode::OK);
241 }
242 return ErrorCode::OK;
243 }
244
245 if (op.type != OperationRW::OperationType::BLOCK)
246 {
247 op.UpdateStatus(in_isr, ans);
248 }
249 return ans;
250}
251
253{
254 switch (config.clock_polarity)
255 {
257 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
258 break;
260 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
261 break;
262 }
263
264 switch (config.clock_phase)
265 {
267 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
268 break;
270 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
271 break;
272 }
273
274 bool ok = true;
275 uint32_t hal_presc = 0;
276
277 switch (config.prescaler)
278 {
279#ifdef SPI_BAUDRATEPRESCALER_1
280 case Prescaler::DIV_1:
281 hal_presc = SPI_BAUDRATEPRESCALER_1;
282 break;
283#endif
284#ifdef SPI_BAUDRATEPRESCALER_2
285 case Prescaler::DIV_2:
286 hal_presc = SPI_BAUDRATEPRESCALER_2;
287 break;
288#endif
289#ifdef SPI_BAUDRATEPRESCALER_4
290 case Prescaler::DIV_4:
291 hal_presc = SPI_BAUDRATEPRESCALER_4;
292 break;
293#endif
294#ifdef SPI_BAUDRATEPRESCALER_8
295 case Prescaler::DIV_8:
296 hal_presc = SPI_BAUDRATEPRESCALER_8;
297 break;
298#endif
299#ifdef SPI_BAUDRATEPRESCALER_16
301 hal_presc = SPI_BAUDRATEPRESCALER_16;
302 break;
303#endif
304#ifdef SPI_BAUDRATEPRESCALER_32
306 hal_presc = SPI_BAUDRATEPRESCALER_32;
307 break;
308#endif
309#ifdef SPI_BAUDRATEPRESCALER_64
311 hal_presc = SPI_BAUDRATEPRESCALER_64;
312 break;
313#endif
314#ifdef SPI_BAUDRATEPRESCALER_128
316 hal_presc = SPI_BAUDRATEPRESCALER_128;
317 break;
318#endif
319#ifdef SPI_BAUDRATEPRESCALER_256
321 hal_presc = SPI_BAUDRATEPRESCALER_256;
322 break;
323#endif
324#ifdef SPI_BAUDRATEPRESCALER_512
326 hal_presc = SPI_BAUDRATEPRESCALER_512;
327 break;
328#endif
329#ifdef SPI_BAUDRATEPRESCALER_1024
331 hal_presc = SPI_BAUDRATEPRESCALER_1024;
332 break;
333#endif
334 default:
335 ok = false;
336 break;
337 }
338
339 ASSERT(ok);
340 if (!ok)
341 {
343 }
344
345 spi_handle_->Init.BaudRatePrescaler = hal_presc;
346
347 GetConfig() = config;
348
349 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
350}
351
352ErrorCode STM32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW& op, bool in_isr)
353{
354 uint32_t need_read = read_data.size_;
355
356 if (spi_handle_->State != HAL_SPI_STATE_READY)
357 {
358 return ErrorCode::BUSY;
359 }
360
361 RawData rx = GetRxBuffer();
362 RawData tx = GetTxBuffer();
363
364 ASSERT(rx.size_ >= need_read + 1);
365 ASSERT(tx.size_ >= need_read + 1);
366
367 if (need_read + 1 > dma_enable_min_size_)
368 {
369 mem_read_ = true;
370 rw_op_ = op;
371 if (op.type == OperationRW::OperationType::BLOCK)
372 {
373 block_wait_.Start(*op.data.sem_info.sem);
374 }
375
376 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
377 Memory::FastSet(txb, 0, need_read + 1);
378 txb[0] = static_cast<uint8_t>(reg | 0x80);
379#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
380 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
381 static_cast<int32_t>(need_read + 1));
382#endif
383 read_buff_ = read_data;
384
385 HAL_StatusTypeDef st =
386 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
387 static_cast<uint8_t*>(rx.addr_), need_read + 1);
388
389 if (st != HAL_OK)
390 {
391 if (op.type == OperationRW::OperationType::BLOCK)
392 {
393 block_wait_.Cancel();
394 }
395 return ErrorCode::BUSY;
396 }
397
398 op.MarkAsRunning();
399 if (op.type == OperationRW::OperationType::BLOCK)
400 {
401 return block_wait_.Wait(op.data.sem_info.timeout);
402 }
403 return ErrorCode::OK;
404 }
405
406 mem_read_ = false;
407 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
408 Memory::FastSet(txb, 0, need_read + 1);
409 txb[0] = static_cast<uint8_t>(reg | 0x80);
410#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
411 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
412 static_cast<int32_t>(need_read + 1));
413#endif
414
415 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
416 static_cast<uint8_t*>(rx.addr_), need_read + 1,
417 20) == HAL_OK)
420
421 if (ans == ErrorCode::OK)
422 {
423 uint8_t* rxb = reinterpret_cast<uint8_t*>(rx.addr_);
424 Memory::FastCopy(read_data.addr_, rxb + 1, need_read);
425 }
426 SwitchBuffer();
427
428 if (op.type != OperationRW::OperationType::BLOCK)
429 {
430 op.UpdateStatus(in_isr, ans);
431 }
432 return ans;
433}
434
436 bool in_isr)
437{
438 uint32_t need_write = write_data.size_;
439
440 if (spi_handle_->State != HAL_SPI_STATE_READY)
441 {
442 return ErrorCode::BUSY;
443 }
444
445 RawData tx = GetTxBuffer();
446 ASSERT(tx.size_ >= need_write + 1);
447
448 if (need_write + 1 > dma_enable_min_size_)
449 {
450 mem_read_ = false;
451 rw_op_ = op;
452 if (op.type == OperationRW::OperationType::BLOCK)
453 {
454 block_wait_.Start(*op.data.sem_info.sem);
455 }
456
457 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
458 txb[0] = static_cast<uint8_t>(reg & 0x7F);
459 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
460#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
461 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
462 static_cast<int32_t>(need_write + 1));
463#endif
464 read_buff_ = {nullptr, 0};
465
466 HAL_StatusTypeDef st = HAL_SPI_Transmit_DMA(
467 spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write + 1);
468
469 if (st != HAL_OK)
470 {
471 if (op.type == OperationRW::OperationType::BLOCK)
472 {
473 block_wait_.Cancel();
474 }
475 return ErrorCode::BUSY;
476 }
477
478 op.MarkAsRunning();
479 if (op.type == OperationRW::OperationType::BLOCK)
480 {
481 return block_wait_.Wait(op.data.sem_info.timeout);
482 }
483 return ErrorCode::OK;
484 }
485
486 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
487 txb[0] = static_cast<uint8_t>(reg & 0x7F);
488 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
489#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
490 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
491 static_cast<int32_t>(need_write + 1));
492#endif
493
494 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
495 need_write + 1, 20) == HAL_OK)
498
499 SwitchBuffer();
500
501 if (op.type != OperationRW::OperationType::BLOCK)
502 {
503 op.UpdateStatus(in_isr, ans);
504 }
505 return ans;
506}
507
509{
510 SPI_TypeDef* inst = spi_handle_ ? spi_handle_->Instance : nullptr;
511 if (!inst)
512 {
513 return 0u;
514 }
515
516#if defined(HAL_RCC_MODULE_ENABLED)
517// 1) 优先读取独立 SPI 内核时钟。
518// 1) Prefer dedicated SPI kernel clock when available.
519// H7: 分组宏 SPI123 / SPI45 / SPI6
520#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
521 defined(RCC_PERIPHCLK_SPI6)
522 // SPI1/2/3 → RCC_PERIPHCLK_SPI123
523 if (
524#ifdef SPI1
525 inst == SPI1 ||
526#endif
527#ifdef SPI2
528 inst == SPI2 ||
529#endif
530#ifdef SPI3
531 inst == SPI3 ||
532#endif
533 false)
534 {
535#ifdef RCC_PERIPHCLK_SPI123
536 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
537#endif
538 }
539 // SPI4/5 → RCC_PERIPHCLK_SPI45
540 if (
541#ifdef SPI4
542 inst == SPI4 ||
543#endif
544#ifdef SPI5
545 inst == SPI5 ||
546#endif
547 false)
548 {
549#ifdef RCC_PERIPHCLK_SPI45
550 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
551#endif
552 }
553// SPI6 → RCC_PERIPHCLK_SPI6
554#ifdef SPI6
555 if (inst == SPI6)
556 {
557#ifdef RCC_PERIPHCLK_SPI6
558 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
559#endif
560 }
561#endif
562#endif // H7 分组
563
564// 其它系列:通常是逐个 SPIx 宏
565#if defined(RCC_PERIPHCLK_SPI1)
566#ifdef SPI1
567 if (inst == SPI1) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
568#endif
569#endif
570#if defined(RCC_PERIPHCLK_SPI2)
571#ifdef SPI2
572 if (inst == SPI2) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
573#endif
574#endif
575#if defined(RCC_PERIPHCLK_SPI3)
576#ifdef SPI3
577 if (inst == SPI3) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
578#endif
579#endif
580#if defined(RCC_PERIPHCLK_SPI4)
581#ifdef SPI4
582 if (inst == SPI4) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
583#endif
584#endif
585#if defined(RCC_PERIPHCLK_SPI5)
586#ifdef SPI5
587 if (inst == SPI5) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
588#endif
589#endif
590#if defined(RCC_PERIPHCLK_SPI6)
591#ifdef SPI6
592 if (inst == SPI6) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
593#endif
594#endif
595#endif // HAL_RCC_MODULE_ENABLED
596
597 // 2) 回退到所在 APB 的 PCLK。
598 // 2) Fallback to APB PCLK if no dedicated kernel clock is available.
599#if defined(STM32H7) && defined(SPI6)
600 if (inst == SPI6)
601 {
602#if defined(HAL_RCC_GetPCLK4Freq)
603 return HAL_RCC_GetPCLK4Freq();
604#else
605 return HAL_RCC_GetHCLKFreq();
606#endif
607 }
608#endif
609
610 // 大多数系列:SPI1/4/5/6/7/8 → APB2;SPI2/3 → APB1
611 if (
612#ifdef SPI1
613 inst == SPI1 ||
614#endif
615#ifdef SPI4
616 inst == SPI4 ||
617#endif
618#ifdef SPI5
619 inst == SPI5 ||
620#endif
621#ifdef SPI6
622 inst == SPI6 ||
623#endif
624#ifdef SPI7
625 inst == SPI7 ||
626#endif
627#ifdef SPI8
628 inst == SPI8 ||
629#endif
630 false)
631 {
632#if defined(HAL_RCC_GetPCLK2Freq)
633 return HAL_RCC_GetPCLK2Freq();
634#elif defined(HAL_RCC_GetPCLK1Freq)
635 return HAL_RCC_GetPCLK1Freq(); // 低端/单APB系列兜底
636#else
637 return HAL_RCC_GetHCLKFreq();
638#endif
639 }
640 else
641 {
642#if defined(HAL_RCC_GetPCLK1Freq)
643 return HAL_RCC_GetPCLK1Freq();
644#elif defined(HAL_RCC_GetPCLK2Freq)
645 return HAL_RCC_GetPCLK2Freq();
646#else
647 return HAL_RCC_GetHCLKFreq();
648#endif
649 }
650}
651
653{
654#if defined(SPI_BAUDRATEPRESCALER_1024)
655 return Prescaler::DIV_1024;
656#elif defined(SPI_BAUDRATEPRESCALER_512)
657 return Prescaler::DIV_512;
658#elif defined(SPI_BAUDRATEPRESCALER_256)
659 return Prescaler::DIV_256;
660#elif defined(SPI_BAUDRATEPRESCALER_128)
661 return Prescaler::DIV_128;
662#elif defined(SPI_BAUDRATEPRESCALER_64)
663 return Prescaler::DIV_64;
664#elif defined(SPI_BAUDRATEPRESCALER_32)
665 return Prescaler::DIV_32;
666#elif defined(SPI_BAUDRATEPRESCALER_16)
667 return Prescaler::DIV_16;
668#elif defined(SPI_BAUDRATEPRESCALER_8)
669 return Prescaler::DIV_8;
670#elif defined(SPI_BAUDRATEPRESCALER_4)
671 return Prescaler::DIV_4;
672#elif defined(SPI_BAUDRATEPRESCALER_2)
673 return Prescaler::DIV_2;
674#elif defined(SPI_BAUDRATEPRESCALER_1)
675 return Prescaler::DIV_1;
676#else
677 return Prescaler::UNKNOWN;
678#endif
679}
680
681ErrorCode STM32SPI::Transfer(size_t size, OperationRW& op, bool in_isr)
682{
683 if (spi_handle_->State != HAL_SPI_STATE_READY)
684 {
685 return ErrorCode::BUSY;
686 }
687
688 if (size == 0)
689 {
690 if (op.type != OperationRW::OperationType::BLOCK)
691 {
692 op.UpdateStatus(in_isr, ErrorCode::OK);
693 }
694 return ErrorCode::OK;
695 }
696
697 RawData rx = GetRxBuffer();
698 RawData tx = GetTxBuffer();
699
700 const uint16_t xfer = static_cast<uint16_t>(size);
701
702 if (size > dma_enable_min_size_)
703 {
704 rw_op_ = op;
705 if (op.type == OperationRW::OperationType::BLOCK)
706 {
707 block_wait_.Start(*op.data.sem_info.sem);
708 }
709
710#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
711 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_), static_cast<int32_t>(xfer));
712 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t*>(rx.addr_),
713 static_cast<int32_t>(xfer));
714#endif
715
716 HAL_StatusTypeDef st =
717 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
718 static_cast<uint8_t*>(rx.addr_), xfer);
719
720 if (st != HAL_OK)
721 {
722 if (op.type == OperationRW::OperationType::BLOCK)
723 {
724 block_wait_.Cancel();
725 }
726 return ErrorCode::BUSY;
727 }
728
729 op.MarkAsRunning();
730 if (op.type == OperationRW::OperationType::BLOCK)
731 {
732 return block_wait_.Wait(op.data.sem_info.timeout);
733 }
734 return ErrorCode::OK;
735 }
736
737 ErrorCode ans =
738 (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
739 static_cast<uint8_t*>(rx.addr_), xfer, 20) == HAL_OK)
742
743#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
744 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t*>(rx.addr_),
745 static_cast<int32_t>(xfer));
746#endif
747
748 SwitchBuffer();
749
750 if (op.type != OperationRW::OperationType::BLOCK)
751 {
752 op.UpdateStatus(in_isr, ans);
753 }
754 return ans;
755}
756
757extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
758{
759 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
760 ASSERT(spi != nullptr);
761 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
762 {
763 return;
764 }
765 spi->SwitchBuffer();
766 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
767 {
768 (void)spi->block_wait_.TryPost(true, ErrorCode::OK);
769 }
770 else
771 {
772 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
773 }
774}
775
776extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
777{
778 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
779 ASSERT(spi != nullptr);
780 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
781 {
782 return;
783 }
784
785 RawData rx = spi->GetRxBuffer();
786 const bool has_user_read_copy = (spi->read_buff_.size_ > 0);
787
788 if (has_user_read_copy)
789 {
790 if (!spi->mem_read_)
791 {
792#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
793 SCB_InvalidateDCache_by_Addr(rx.addr_, spi->read_buff_.size_);
794#endif
795 Memory::FastCopy(spi->read_buff_.addr_, rx.addr_, spi->read_buff_.size_);
796 }
797 else
798 {
799#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
800 SCB_InvalidateDCache_by_Addr(rx.addr_, spi->read_buff_.size_ + 1);
801#endif
802 uint8_t* rx_dma_buff = reinterpret_cast<uint8_t*>(rx.addr_);
803 Memory::FastCopy(spi->read_buff_.addr_, rx_dma_buff + 1, spi->read_buff_.size_);
804 }
805 spi->read_buff_.size_ = 0;
806 }
807
808 spi->SwitchBuffer();
809 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
810 {
811 (void)spi->block_wait_.TryPost(true, ErrorCode::OK);
812 }
813 else
814 {
815 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
816 }
817}
818
819extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
820{
821 HAL_SPI_RxCpltCallback(hspi);
822}
823
824extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
825{
826 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
827 ASSERT(spi != nullptr);
828 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::NONE)
829 {
830 return;
831 }
832 if (spi->rw_op_.type == STM32SPI::OperationRW::OperationType::BLOCK)
833 {
834 (void)spi->block_wait_.TryPost(true, ErrorCode::FAILED);
835 }
836 else
837 {
838 spi->rw_op_.UpdateStatus(true, ErrorCode::FAILED);
839 }
840}
841
842#endif
常量原始数据封装类。 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_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:71
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:83
LibXR 命名空间
Definition ch32_can.hpp:14
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 >
计算两个数的最大值
存储 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