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)
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 memcpy(tx.addr_, write_data.addr_, write_data.size_);
116 if (write_data.size_ < need_write)
117 {
118 memset(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 memcpy(tx.addr_, write_data.addr_, write_data.size_);
133 if (write_data.size_ < need_write)
134 {
135 memset(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 =
145 HAL_SPI_Transmit_DMA(spi_handle_, static_cast<uint8_t *>(tx.addr_), need_write);
146 }
147 else if (read_data.size_ > 0)
148 {
149 read_buff_ = read_data;
150
151 st = HAL_SPI_Receive_DMA(spi_handle_, static_cast<uint8_t *>(rx.addr_),
152 read_data.size_);
153 }
154 else
155 {
156 if (op.type != OperationRW::OperationType::BLOCK)
157 {
158 op.UpdateStatus(false, ErrorCode::OK);
159 }
160 return ErrorCode::OK;
161 }
162
163 if (st != HAL_OK)
164 {
165 return ErrorCode::BUSY;
166 }
167
168 op.MarkAsRunning();
169 if (op.type == OperationRW::OperationType::BLOCK)
170 {
171 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
172 }
173 return ErrorCode::OK;
174 }
175
176 ErrorCode ans = ErrorCode::OK;
177
178 if (write_data.size_ > 0 && read_data.size_ > 0)
179 {
180 memcpy(tx.addr_, write_data.addr_, write_data.size_);
181 if (write_data.size_ < need_write)
182 {
183 memset(reinterpret_cast<uint8_t *>(tx.addr_) + write_data.size_, 0,
184 need_write - write_data.size_);
185 }
186#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
187 SCB_CleanDCache_by_Addr(static_cast<uint32_t *>(tx.addr_),
188 static_cast<int32_t>(need_write));
189#endif
190 ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t *>(tx.addr_),
191 static_cast<uint8_t *>(rx.addr_), need_write,
192 20) == HAL_OK)
193 ? ErrorCode::OK
194 : ErrorCode::BUSY;
195
196 if (ans == ErrorCode::OK)
197 {
198 memcpy(read_data.addr_, rx.addr_, read_data.size_);
199 }
200 SwitchBuffer();
201 }
202 else if (read_data.size_ > 0)
203 {
204 ans = (HAL_SPI_Receive(spi_handle_, static_cast<uint8_t *>(rx.addr_), read_data.size_,
205 20) == HAL_OK)
206 ? ErrorCode::OK
207 : ErrorCode::BUSY;
208
209 if (ans == ErrorCode::OK)
210 {
211 memcpy(read_data.addr_, rx.addr_, read_data.size_);
212 }
213 SwitchBuffer();
214 }
215 else if (write_data.size_ > 0)
216 {
217 memcpy(tx.addr_, write_data.addr_, write_data.size_);
218#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
219 SCB_CleanDCache_by_Addr(static_cast<uint32_t *>(tx.addr_),
220 static_cast<int32_t>(need_write));
221#endif
222 ans = (HAL_SPI_Transmit(spi_handle_, static_cast<uint8_t *>(tx.addr_),
223 write_data.size_, 20) == HAL_OK)
224 ? ErrorCode::OK
225 : ErrorCode::BUSY;
226
227 SwitchBuffer();
228 }
229 else
230 {
231 if (op.type != OperationRW::OperationType::BLOCK)
232 {
233 op.UpdateStatus(false, ErrorCode::OK);
234 }
235 return ErrorCode::OK;
236 }
237
238 if (op.type != OperationRW::OperationType::BLOCK)
239 {
240 op.UpdateStatus(false, ans);
241 }
242 return ans;
243}
244
246{
247 switch (config.clock_polarity)
248 {
250 spi_handle_->Init.CLKPolarity = SPI_POLARITY_LOW;
251 break;
253 spi_handle_->Init.CLKPolarity = SPI_POLARITY_HIGH;
254 break;
255 }
256
257 switch (config.clock_phase)
258 {
260 spi_handle_->Init.CLKPhase = SPI_PHASE_1EDGE;
261 break;
263 spi_handle_->Init.CLKPhase = SPI_PHASE_2EDGE;
264 break;
265 }
266
267 bool ok = true;
268 uint32_t hal_presc = 0;
269
270 switch (config.prescaler)
271 {
272#ifdef SPI_BAUDRATEPRESCALER_1
273 case Prescaler::DIV_1:
274 hal_presc = SPI_BAUDRATEPRESCALER_1;
275 break;
276#endif
277#ifdef SPI_BAUDRATEPRESCALER_2
278 case Prescaler::DIV_2:
279 hal_presc = SPI_BAUDRATEPRESCALER_2;
280 break;
281#endif
282#ifdef SPI_BAUDRATEPRESCALER_4
283 case Prescaler::DIV_4:
284 hal_presc = SPI_BAUDRATEPRESCALER_4;
285 break;
286#endif
287#ifdef SPI_BAUDRATEPRESCALER_8
288 case Prescaler::DIV_8:
289 hal_presc = SPI_BAUDRATEPRESCALER_8;
290 break;
291#endif
292#ifdef SPI_BAUDRATEPRESCALER_16
294 hal_presc = SPI_BAUDRATEPRESCALER_16;
295 break;
296#endif
297#ifdef SPI_BAUDRATEPRESCALER_32
299 hal_presc = SPI_BAUDRATEPRESCALER_32;
300 break;
301#endif
302#ifdef SPI_BAUDRATEPRESCALER_64
304 hal_presc = SPI_BAUDRATEPRESCALER_64;
305 break;
306#endif
307#ifdef SPI_BAUDRATEPRESCALER_128
309 hal_presc = SPI_BAUDRATEPRESCALER_128;
310 break;
311#endif
312#ifdef SPI_BAUDRATEPRESCALER_256
314 hal_presc = SPI_BAUDRATEPRESCALER_256;
315 break;
316#endif
317#ifdef SPI_BAUDRATEPRESCALER_512
319 hal_presc = SPI_BAUDRATEPRESCALER_512;
320 break;
321#endif
322#ifdef SPI_BAUDRATEPRESCALER_1024
324 hal_presc = SPI_BAUDRATEPRESCALER_1024;
325 break;
326#endif
327 default:
328 ok = false;
329 break;
330 }
331
332 ASSERT(ok);
333 if (!ok)
334 {
335 return ErrorCode::NOT_SUPPORT;
336 }
337
338 spi_handle_->Init.BaudRatePrescaler = hal_presc;
339
340 GetConfig() = config;
341
342 return (HAL_SPI_Init(spi_handle_) == HAL_OK) ? ErrorCode::OK : ErrorCode::BUSY;
343}
344
345ErrorCode STM32SPI::MemRead(uint16_t reg, RawData read_data, OperationRW &op)
346{
347 uint32_t need_read = read_data.size_;
348
349 if (spi_handle_->State != HAL_SPI_STATE_READY)
350 {
351 return ErrorCode::BUSY;
352 }
353
354 RawData rx = GetRxBuffer();
355 RawData tx = GetTxBuffer();
356
357 ASSERT(rx.size_ >= need_read + 1);
358 ASSERT(tx.size_ >= need_read + 1);
359
360 if (need_read + 1 > dma_enable_min_size_)
361 {
362 mem_read_ = true;
363 rw_op_ = op;
364
365 uint8_t *txb = reinterpret_cast<uint8_t *>(tx.addr_);
366 memset(txb, 0, need_read + 1);
367 txb[0] = static_cast<uint8_t>(reg | 0x80);
368#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
369 SCB_CleanDCache_by_Addr(static_cast<uint32_t *>(tx.addr_),
370 static_cast<int32_t>(need_read + 1));
371#endif
372 read_buff_ = read_data;
373
374 HAL_StatusTypeDef st =
375 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t *>(tx.addr_),
376 static_cast<uint8_t *>(rx.addr_), need_read + 1);
377
378 if (st != HAL_OK)
379 {
380 return ErrorCode::BUSY;
381 }
382
383 op.MarkAsRunning();
384 if (op.type == OperationRW::OperationType::BLOCK)
385 {
386 return op.data.sem_info.sem->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 memset(txb, 0, need_read + 1);
394 txb[0] = static_cast<uint8_t>(reg | 0x80);
395#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
396 SCB_CleanDCache_by_Addr(static_cast<uint32_t *>(tx.addr_),
397 static_cast<int32_t>(need_read + 1));
398#endif
399
400 ErrorCode ans = (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t *>(tx.addr_),
401 static_cast<uint8_t *>(rx.addr_),
402 need_read + 1, 20) == HAL_OK)
403 ? ErrorCode::OK
404 : ErrorCode::BUSY;
405
406 if (ans == ErrorCode::OK)
407 {
408 uint8_t *rxb = reinterpret_cast<uint8_t *>(rx.addr_);
409 memcpy(read_data.addr_, rxb + 1, need_read);
410 }
411 SwitchBuffer();
412
413 if (op.type != OperationRW::OperationType::BLOCK)
414 {
415 op.UpdateStatus(false, ans);
416 }
417 return ans;
418}
419
420ErrorCode STM32SPI::MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op)
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 memcpy(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 memcpy(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(false, 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 内核时钟” (kernel clock) ===
494// H7: 分组宏 SPI123 / SPI45 / SPI6
495#if defined(RCC_PERIPHCLK_SPI123) || defined(RCC_PERIPHCLK_SPI45) || \
496 defined(RCC_PERIPHCLK_SPI6)
497 // SPI1/2/3 → RCC_PERIPHCLK_SPI123
498 if (
499#ifdef SPI1
500 inst == SPI1 ||
501#endif
502#ifdef SPI2
503 inst == SPI2 ||
504#endif
505#ifdef SPI3
506 inst == SPI3 ||
507#endif
508 false)
509 {
510#ifdef RCC_PERIPHCLK_SPI123
511 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI123);
512#endif
513 }
514 // SPI4/5 → RCC_PERIPHCLK_SPI45
515 if (
516#ifdef SPI4
517 inst == SPI4 ||
518#endif
519#ifdef SPI5
520 inst == SPI5 ||
521#endif
522 false)
523 {
524#ifdef RCC_PERIPHCLK_SPI45
525 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI45);
526#endif
527 }
528// SPI6 → RCC_PERIPHCLK_SPI6
529#ifdef SPI6
530 if (inst == SPI6)
531 {
532#ifdef RCC_PERIPHCLK_SPI6
533 return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
534#endif
535 }
536#endif
537#endif // H7 分组
538
539// 其它系列:通常是逐个 SPIx 宏
540#if defined(RCC_PERIPHCLK_SPI1)
541#ifdef SPI1
542 if (inst == SPI1) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI1);
543#endif
544#endif
545#if defined(RCC_PERIPHCLK_SPI2)
546#ifdef SPI2
547 if (inst == SPI2) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI2);
548#endif
549#endif
550#if defined(RCC_PERIPHCLK_SPI3)
551#ifdef SPI3
552 if (inst == SPI3) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI3);
553#endif
554#endif
555#if defined(RCC_PERIPHCLK_SPI4)
556#ifdef SPI4
557 if (inst == SPI4) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI4);
558#endif
559#endif
560#if defined(RCC_PERIPHCLK_SPI5)
561#ifdef SPI5
562 if (inst == SPI5) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI5);
563#endif
564#endif
565#if defined(RCC_PERIPHCLK_SPI6)
566#ifdef SPI6
567 if (inst == SPI6) return HAL_RCCEx_GetPeriphCLKFreq(RCC_PERIPHCLK_SPI6);
568#endif
569#endif
570#endif // HAL_RCC_MODULE_ENABLED
571
572 // === 2) 回退:使用所在 APB 的 PCLK 作为 SPI 内核时钟 ===
573#if defined(STM32H7) && defined(SPI6)
574 if (inst == SPI6)
575 {
576#if defined(HAL_RCC_GetPCLK4Freq)
577 return HAL_RCC_GetPCLK4Freq();
578#else
579 return HAL_RCC_GetHCLKFreq();
580#endif
581 }
582#endif
583
584 // 大多数系列:SPI1/4/5/6/7/8 → APB2;SPI2/3 → APB1
585 if (
586#ifdef SPI1
587 inst == SPI1 ||
588#endif
589#ifdef SPI4
590 inst == SPI4 ||
591#endif
592#ifdef SPI5
593 inst == SPI5 ||
594#endif
595#ifdef SPI6
596 inst == SPI6 ||
597#endif
598#ifdef SPI7
599 inst == SPI7 ||
600#endif
601#ifdef SPI8
602 inst == SPI8 ||
603#endif
604 false)
605 {
606#if defined(HAL_RCC_GetPCLK2Freq)
607 return HAL_RCC_GetPCLK2Freq();
608#elif defined(HAL_RCC_GetPCLK1Freq)
609 return HAL_RCC_GetPCLK1Freq(); // 低端/单APB系列兜底
610#else
611 return HAL_RCC_GetHCLKFreq();
612#endif
613 }
614 else
615 {
616#if defined(HAL_RCC_GetPCLK1Freq)
617 return HAL_RCC_GetPCLK1Freq();
618#elif defined(HAL_RCC_GetPCLK2Freq)
619 return HAL_RCC_GetPCLK2Freq();
620#else
621 return HAL_RCC_GetHCLKFreq();
622#endif
623 }
624}
625
627{
628#if defined(SPI_BAUDRATEPRESCALER_1024)
629 return Prescaler::DIV_1024;
630#elif defined(SPI_BAUDRATEPRESCALER_512)
631 return Prescaler::DIV_512;
632#elif defined(SPI_BAUDRATEPRESCALER_256)
633 return Prescaler::DIV_256;
634#elif defined(SPI_BAUDRATEPRESCALER_128)
635 return Prescaler::DIV_128;
636#elif defined(SPI_BAUDRATEPRESCALER_64)
637 return Prescaler::DIV_64;
638#elif defined(SPI_BAUDRATEPRESCALER_32)
639 return Prescaler::DIV_32;
640#elif defined(SPI_BAUDRATEPRESCALER_16)
641 return Prescaler::DIV_16;
642#elif defined(SPI_BAUDRATEPRESCALER_8)
643 return Prescaler::DIV_8;
644#elif defined(SPI_BAUDRATEPRESCALER_4)
645 return Prescaler::DIV_4;
646#elif defined(SPI_BAUDRATEPRESCALER_2)
647 return Prescaler::DIV_2;
648#elif defined(SPI_BAUDRATEPRESCALER_1)
649 return Prescaler::DIV_1;
650#else
651 return Prescaler::UNKNOWN;
652#endif
653}
654
655ErrorCode STM32SPI::Transfer(size_t size, OperationRW &op)
656{
657 if (spi_handle_->State != HAL_SPI_STATE_READY)
658 {
659 return ErrorCode::BUSY;
660 }
661
662 if (size == 0)
663 {
664 if (op.type != OperationRW::OperationType::BLOCK)
665 {
666 op.UpdateStatus(false, ErrorCode::OK);
667 }
668 return ErrorCode::OK;
669 }
670
671 RawData rx = GetRxBuffer();
672 RawData tx = GetTxBuffer();
673
674 const uint16_t xfer = static_cast<uint16_t>(size);
675
676 if (size > dma_enable_min_size_)
677 {
678 rw_op_ = op;
679
680#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
681 SCB_CleanDCache_by_Addr(static_cast<uint32_t *>(tx.addr_),
682 static_cast<int32_t>(xfer));
683 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t *>(rx.addr_),
684 static_cast<int32_t>(xfer));
685#endif
686
687 HAL_StatusTypeDef st =
688 HAL_SPI_TransmitReceive_DMA(spi_handle_, static_cast<uint8_t *>(tx.addr_),
689 static_cast<uint8_t *>(rx.addr_), xfer);
690
691 if (st != HAL_OK)
692 {
693 return ErrorCode::BUSY;
694 }
695
696 op.MarkAsRunning();
697 if (op.type == OperationRW::OperationType::BLOCK)
698 {
699 return op.data.sem_info.sem->Wait(op.data.sem_info.timeout);
700 }
701 return ErrorCode::OK;
702 }
703
704 ErrorCode ans =
705 (HAL_SPI_TransmitReceive(spi_handle_, static_cast<uint8_t *>(tx.addr_),
706 static_cast<uint8_t *>(rx.addr_), xfer, 20) == HAL_OK)
707 ? ErrorCode::OK
708 : ErrorCode::BUSY;
709
710#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
711 SCB_InvalidateDCache_by_Addr(static_cast<uint32_t *>(rx.addr_),
712 static_cast<int32_t>(xfer));
713#endif
714
715 SwitchBuffer();
716
717 if (op.type != OperationRW::OperationType::BLOCK)
718 {
719 op.UpdateStatus(false, ans);
720 }
721 return ans;
722}
723
724extern "C" void HAL_SPI_TxCpltCallback(SPI_HandleTypeDef *hspi)
725{
726 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
727 spi->SwitchBuffer();
728 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
729}
730
731extern "C" void HAL_SPI_RxCpltCallback(SPI_HandleTypeDef *hspi)
732{
733 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
734
735 RawData rx = spi->GetRxBuffer();
736
737 if (spi->read_buff_.size_ > 0)
738 {
739 if (!spi->mem_read_)
740 {
741#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
742 SCB_InvalidateDCache_by_Addr(rx.addr_, spi->read_buff_.size_);
743#endif
744 memcpy(spi->read_buff_.addr_, rx.addr_, spi->read_buff_.size_);
745 }
746 else
747 {
748#if defined(__DCACHE_PRESENT) && (__DCACHE_PRESENT == 1U)
749 SCB_InvalidateDCache_by_Addr(rx.addr_, spi->read_buff_.size_ + 1);
750#endif
751 uint8_t *rx_dma_buff = reinterpret_cast<uint8_t *>(rx.addr_);
752 memcpy(spi->read_buff_.addr_, rx_dma_buff + 1, spi->read_buff_.size_);
753 }
754 spi->read_buff_.size_ = 0;
755 }
756
757 spi->SwitchBuffer();
758 spi->rw_op_.UpdateStatus(true, ErrorCode::OK);
759}
760
761extern "C" void HAL_SPI_TxRxCpltCallback(SPI_HandleTypeDef *hspi)
762{
763 HAL_SPI_RxCpltCallback(hspi);
764}
765
766extern "C" void HAL_SPI_ErrorCallback(SPI_HandleTypeDef *hspi)
767{
768 STM32SPI *spi = STM32SPI::map[STM32_SPI_GetID(hspi->Instance)];
769 spi->rw_op_.UpdateStatus(true, ErrorCode::FAILED);
770}
771
772#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).
union LibXR::Operation::@5 data
void MarkAsRunning()
标记操作为运行状态。 Marks the operation as running.
Definition libxr_rw.hpp:202
void UpdateStatus(bool in_isr, Status &&...status)
Updates operation status based on type.
Definition libxr_rw.hpp:171
OperationType type
Definition libxr_rw.hpp:226
原始数据封装类。 A class for encapsulating raw data.
size_t size_
数据大小(字节)。 The size of the data (in bytes).
void * addr_
数据存储地址。 The storage address of the data.
串行外设接口(SPI)抽象类。Abstract class for Serial Peripheral Interface (SPI).
Definition spi.hpp:14
@ EDGE_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:303
void SwitchBuffer()
切换缓冲区。Switches the buffer.
Definition spi.hpp:334
RawData GetTxBuffer()
获取发送数据的缓冲区。Gets the buffer for storing data to be sent.
Definition spi.hpp:319
@ LOW
时钟空闲时为低电平。Clock idle low.
@ HIGH
时钟空闲时为高电平。Clock idle high.
Configuration & GetConfig()
获取 SPI 配置参数。Gets the SPI configuration parameters.
Definition spi.hpp:388
ErrorCode ReadAndWrite(RawData read_data, ConstRawData write_data, OperationRW &op) override
进行 SPI 读写操作。Performs SPI read and write operations.
Definition stm32_spi.cpp:83
ErrorCode MemRead(uint16_t reg, RawData read_data, OperationRW &op) override
从 SPI 设备的寄存器读取数据。 Reads data from a specific register of the SPI device.
ErrorCode MemWrite(uint16_t reg, ConstRawData write_data, OperationRW &op) override
向 SPI 设备的寄存器写入数据。 Writes data to a specific register of the SPI device.
uint32_t GetMaxBusSpeed() const override
获取 SPI 设备的最大时钟速度。Gets the maximum clock speed of the SPI device.
ErrorCode Transfer(size_t size, OperationRW &op) 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 Wait(uint32_t timeout=UINT32_MAX)
等待(减少)信号量 Waits (decrements) the semaphore
Definition semaphore.cpp:25
LibXR 命名空间
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