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
83ErrorCode STM32SPI::ReadAndWrite(RawData read_data, ConstRawData write_data,
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
111 HAL_StatusTypeDef st = HAL_OK;
112
113 if (write_data.size_ > 0 && read_data.size_ > 0)
114 {
115 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
116 if (write_data.size_ < need_write)
117 {
118 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
119 need_write - write_data.size_);
120 }
121#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
122 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
123 static_cast<int32_t>(need_write));
124#endif
125 read_buff_ = read_data;
126
127 st = HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
128 static_cast<uint8_t*>(rx.addr_), need_write);
129 }
130 else if (write_data.size_ > 0)
131 {
132 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
133 if (write_data.size_ < need_write)
134 {
135 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
136 need_write - write_data.size_);
137 }
138#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
139 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
140 static_cast<int32_t>(need_write));
141#endif
142 read_buff_ = {nullptr, 0};
143
144 st = HAL_SPI_Transmit_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_), need_write);
145 }
146 else if (read_data.size_ > 0)
147 {
148 read_buff_ = read_data;
149
150 st = HAL_SPI_Receive_DMA(spi_handle_, static_cast<uint8_t*>(rx.addr_),
151 read_data.size_);
152 }
153 else
154 {
155 if (op.type != OperationRW::OperationType::BLOCK)
156 {
157 op.UpdateStatus(in_isr, ErrorCode::OK);
158 }
159 return ErrorCode::OK;
160 }
161
162 if (st != HAL_OK)
163 {
164 return ErrorCode::BUSY;
165 }
166
167 op.MarkAsRunning();
168 if (op.type == OperationRW::OperationType::BLOCK)
169 {
170 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
171 }
172 return ErrorCode::OK;
173 }
174
175 ErrorCode ans = ErrorCode::OK;
176
177 if (write_data.size_ > 0 && read_data.size_ > 0)
178 {
179 Memory::FastCopy(tx.addr_, write_data.addr_, write_data.size_);
180 if (write_data.size_ < need_write)
181 {
182 Memory::FastSet(reinterpret_cast<uint8_t*>(tx.addr_) + write_data.size_, 0,
183 need_write - write_data.size_);
184 }
185#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
186 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
187 static_cast<int32_t>(need_write));
188#endif
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)
192 ? ErrorCode::OK
193 : ErrorCode::BUSY;
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)
205 ? ErrorCode::OK
206 : ErrorCode::BUSY;
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#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
218 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
219 static_cast<int32_t>(need_write));
220#endif
221 ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
222 write_data.size_, 20) == HAL_OK)
223 ? ErrorCode::OK
224 : ErrorCode::BUSY;
225
226 SwitchBuffer();
227 }
228 else
229 {
230 if (op.type != OperationRW::OperationType::BLOCK)
231 {
232 op.UpdateStatus(in_isr, ErrorCode::OK);
233 }
234 return ErrorCode::OK;
235 }
236
237 if (op.type != OperationRW::OperationType::BLOCK)
238 {
239 op.UpdateStatus(in_isr, ans);
240 }
241 return ans;
242}
243
245{
246 switch (config.clock_polarity)
247 {
249 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
250 break;
252 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
253 break;
254 }
255
256 switch (config.clock_phase)
257 {
259 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
260 break;
262 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
263 break;
264 }
265
266 bool ok = true;
267 uint32_t hal_presc = 0;
268
269 switch (config.prescaler)
270 {
271#ifdef SPI_BAUDRATEPRESCALER_1
272 case Prescaler::DIV_1:
273 hal_presc = SPI_BAUDRATEPRESCALER_1;
274 break;
275#endif
276#ifdef SPI_BAUDRATEPRESCALER_2
277 case Prescaler::DIV_2:
278 hal_presc = SPI_BAUDRATEPRESCALER_2;
279 break;
280#endif
281#ifdef SPI_BAUDRATEPRESCALER_4
282 case Prescaler::DIV_4:
283 hal_presc = SPI_BAUDRATEPRESCALER_4;
284 break;
285#endif
286#ifdef SPI_BAUDRATEPRESCALER_8
287 case Prescaler::DIV_8:
288 hal_presc = SPI_BAUDRATEPRESCALER_8;
289 break;
290#endif
291#ifdef SPI_BAUDRATEPRESCALER_16
293 hal_presc = SPI_BAUDRATEPRESCALER_16;
294 break;
295#endif
296#ifdef SPI_BAUDRATEPRESCALER_32
298 hal_presc = SPI_BAUDRATEPRESCALER_32;
299 break;
300#endif
301#ifdef SPI_BAUDRATEPRESCALER_64
303 hal_presc = SPI_BAUDRATEPRESCALER_64;
304 break;
305#endif
306#ifdef SPI_BAUDRATEPRESCALER_128
308 hal_presc = SPI_BAUDRATEPRESCALER_128;
309 break;
310#endif
311#ifdef SPI_BAUDRATEPRESCALER_256
313 hal_presc = SPI_BAUDRATEPRESCALER_256;
314 break;
315#endif
316#ifdef SPI_BAUDRATEPRESCALER_512
318 hal_presc = SPI_BAUDRATEPRESCALER_512;
319 break;
320#endif
321#ifdef SPI_BAUDRATEPRESCALER_1024
323 hal_presc = SPI_BAUDRATEPRESCALER_1024;
324 break;
325#endif
326 default:
327 ok = false;
328 break;
329 }
330
331 ASSERT(ok);
332 if (!ok)
333 {
334 return ErrorCode::NOT_SUPPORT;
335 }
336
337 spi_handle_->Init.BaudRatePrescaler = hal_presc;
338
339 GetConfig() = config;
340
341 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
342}
343
344ErrorCode STM32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW& op, bool in_isr)
345{
346 uint32_t need_read = read_data.size_;
347
348 if (spi_handle_->State != HAL_SPI_STATE_READY)
349 {
350 return ErrorCode::BUSY;
351 }
352
353 RawData rx = GetRxBuffer();
354 RawData tx = GetTxBuffer();
355
356 ASSERT(rx.size_ >= need_read + 1);
357 ASSERT(tx.size_ >= need_read + 1);
358
359 if (need_read + 1 > dma_enable_min_size_)
360 {
361 mem_read_ = true;
362 rw_op_ = op;
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#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
368 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
369 static_cast<int32_t>(need_read + 1));
370#endif
371 read_buff_ = read_data;
372
373 HAL_StatusTypeDef st =
374 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
375 static_cast<uint8_t*>(rx.addr_), need_read + 1);
376
377 if (st != HAL_OK)
378 {
379 return ErrorCode::BUSY;
380 }
381
382 op.MarkAsRunning();
383 if (op.type == OperationRW::OperationType::BLOCK)
384 {
385 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
386 }
387 return ErrorCode::OK;
388 }
389
390 mem_read_ = false;
391 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
392 Memory::FastSet(txb, 0, need_read + 1);
393 txb[0] = static_cast<uint8_t>(reg | 0x80);
394#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
395 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
396 static_cast<int32_t>(need_read + 1));
397#endif
398
399 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
400 static_cast<uint8_t*>(rx.addr_), need_read + 1,
401 20) == HAL_OK)
402 ? ErrorCode::OK
403 : ErrorCode::BUSY;
404
405 if (ans == ErrorCode::OK)
406 {
407 uint8_t* rxb = reinterpret_cast<uint8_t*>(rx.addr_);
408 Memory::FastCopy(read_data.addr_, rxb + 1, need_read);
409 }
410 SwitchBuffer();
411
412 if (op.type != OperationRW::OperationType::BLOCK)
413 {
414 op.UpdateStatus(in_isr, ans);
415 }
416 return ans;
417}
418
419ErrorCode STM32SPI::MemWrite(uint16_t reg, ConstRawData write_data, OperationRW& op,
420 bool in_isr)
421{
422 uint32_t need_write = write_data.size_;
423
424 if (spi_handle_->State != HAL_SPI_STATE_READY)
425 {
426 return ErrorCode::BUSY;
427 }
428
429 RawData tx = GetTxBuffer();
430 ASSERT(tx.size_ >= need_write + 1);
431
432 if (need_write + 1 > dma_enable_min_size_)
433 {
434 mem_read_ = false;
435 rw_op_ = op;
436
437 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
438 txb[0] = static_cast<uint8_t>(reg & 0x7F);
439 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
440#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
441 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
442 static_cast<int32_t>(need_write + 1));
443#endif
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 return ErrorCode::BUSY;
452 }
453
454 op.MarkAsRunning();
455 if (op.type == OperationRW::OperationType::BLOCK)
456 {
457 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
458 }
459 return ErrorCode::OK;
460 }
461
462 uint8_t* txb = reinterpret_cast<uint8_t*>(tx.addr_);
463 txb[0] = static_cast<uint8_t>(reg & 0x7F);
464 Memory::FastCopy(txb + 1, write_data.addr_, need_write);
465#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
466 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_),
467 static_cast<int32_t>(need_write + 1));
468#endif
469
470 ErrorCode ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t*>(tx.addr_),
471 need_write + 1, 20) == HAL_OK)
472 ? ErrorCode::OK
473 : ErrorCode::BUSY;
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
682#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
683 SCB_CleanDCache_by_Addr(static_cast<uint32_t*>(tx.addr_), static_cast<int32_t>(xfer));
684 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t*>(rx.addr_),
685 static_cast<int32_t>(xfer));
686#endif
687
688 HAL_StatusTypeDef st =
689 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t*>(tx.addr_),
690 static_cast<uint8_t*>(rx.addr_), xfer);
691
692 if (st != HAL_OK)
693 {
694 return ErrorCode::BUSY;
695 }
696
697 op.MarkAsRunning();
698 if (op.type == OperationRW::OperationType::BLOCK)
699 {
700 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
701 }
702 return ErrorCode::OK;
703 }
704
705 ErrorCode ans =
706 (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t*>(tx.addr_),
707 static_cast<uint8_t*>(rx.addr_), xfer, 20) == HAL_OK)
708 ? ErrorCode::OK
709 : ErrorCode::BUSY;
710
711#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
712 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t*>(rx.addr_),
713 static_cast<int32_t>(xfer));
714#endif
715
716 SwitchBuffer();
717
718 if (op.type != OperationRW::OperationType::BLOCK)
719 {
720 op.UpdateStatus(in_isr, ans);
721 }
722 return ans;
723}
724
725extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef* hspi)
726{
727 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
728 spi->SwitchBuffer();
729 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
730}
731
732extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef* hspi)
733{
734 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
735
736 RawData rx = spi->GetRxBuffer();
737
738 if (spi->read_buff_.size_ > 0)
739 {
740 if (!spi->mem_read_)
741 {
742#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
743 SCB_InvalidateDCache_by_Addr(rx.addr_, spi->read_buff_.size_);
744#endif
745 Memory::FastCopy(spi->read_buff_.addr_, rx.addr_, spi->read_buff_.size_);
746 }
747 else
748 {
749#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
750 SCB_InvalidateDCache_by_Addr(rx.addr_, spi->read_buff_.size_ + 1);
751#endif
752 uint8_t* rx_dma_buff = reinterpret_cast<uint8_t*>(rx.addr_);
753 Memory::FastCopy(spi->read_buff_.addr_, rx_dma_buff + 1, spi->read_buff_.size_);
754 }
755 spi->read_buff_.size_ = 0;
756 }
757
758 spi->SwitchBuffer();
759 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
760}
761
762extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef* hspi)
763{
764 HAL_SPI_RxCpltCallback(hspi);
765}
766
767extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef* hspi)
768{
769 STM32SPI* spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
770 spi->rw_op_.UpdateStatus(true, ErrorCode::FAILED);
771}
772
773#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:3
union LibXR::Operation::@5 data
void UpdateStatus(bool in_isr, Status &&status)
Updates operation status based on type.
Definition libxr_rw.hpp:172
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:205
OperationType type
Definition libxr_rw.hpp:229
原始数据封装类。 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
ErrorCode Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
LibXR 命名空间
Definition ch32_can.hpp:14
constexpr auto max(T1 a, T2 b) -> typename std::common_type< T1, T2 >::type
计算两个数的最大值
存储 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