Skyward boardcore
Loading...
Searching...
No Matches
DMA.cpp
Go to the documentation of this file.
1/* Copyright (c) 2025 Skyward Experimental Rocketry
2 * Author: Alberto Nidasio, Fabrizio Monti
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23#include "DMA.h"
24
25#include <kernel/logging.h>
26#include <utils/ClockUtils.h>
27#include <utils/Debug.h>
28
29#include <map>
30
31using namespace miosix;
32
43void __attribute__((naked)) DMA1_Stream0_IRQHandler()
44{
45 saveContext();
46 asm volatile("bl _Z20DMA1_Stream0_IRQImplv");
47 restoreContext();
48}
49
50void __attribute__((used)) DMA1_Stream0_IRQImpl()
51{
52 Boardcore::DMADriver::instance().IRQhandleInterrupt(
54}
55
56#ifndef STM32F407xx
57// This stream is used by miosix for STM32F407xx boards
58void __attribute__((naked)) DMA1_Stream1_IRQHandler()
59{
60 saveContext();
61 asm volatile("bl _Z20DMA1_Stream1_IRQImplv");
62 restoreContext();
63}
64
65void __attribute__((used)) DMA1_Stream1_IRQImpl()
66{
67 Boardcore::DMADriver::instance().IRQhandleInterrupt(
69}
70#endif // STM32F407xx
71
72void __attribute__((naked)) DMA1_Stream2_IRQHandler()
73{
74 saveContext();
75 asm volatile("bl _Z20DMA1_Stream2_IRQImplv");
76 restoreContext();
77}
78
79void __attribute__((used)) DMA1_Stream2_IRQImpl()
80{
81 Boardcore::DMADriver::instance().IRQhandleInterrupt(
83}
84
85#ifndef STM32F407xx
86// This stream is used by miosix for STM32F407xx boards
87void __attribute__((naked)) DMA1_Stream3_IRQHandler()
88{
89 saveContext();
90 asm volatile("bl _Z20DMA1_Stream3_IRQImplv");
91 restoreContext();
92}
93
94void __attribute__((used)) DMA1_Stream3_IRQImpl()
95{
96 Boardcore::DMADriver::instance().IRQhandleInterrupt(
98}
99#endif // STM32F407xx
100
101void __attribute__((naked)) DMA1_Stream4_IRQHandler()
102{
103 saveContext();
104 asm volatile("bl _Z20DMA1_Stream4_IRQImplv");
105 restoreContext();
106}
107
108void __attribute__((used)) DMA1_Stream4_IRQImpl()
109{
110 Boardcore::DMADriver::instance().IRQhandleInterrupt(
112}
113
114void __attribute__((naked)) DMA1_Stream5_IRQHandler()
115{
116 saveContext();
117 asm volatile("bl _Z20DMA1_Stream5_IRQImplv");
118 restoreContext();
119}
120
121void __attribute__((used)) DMA1_Stream5_IRQImpl()
122{
123 Boardcore::DMADriver::instance().IRQhandleInterrupt(
125}
126
127void __attribute__((naked)) DMA1_Stream6_IRQHandler()
128{
129 saveContext();
130 asm volatile("bl _Z20DMA1_Stream6_IRQImplv");
131 restoreContext();
132}
133
134void __attribute__((used)) DMA1_Stream6_IRQImpl()
135{
136 Boardcore::DMADriver::instance().IRQhandleInterrupt(
138}
139
140void __attribute__((naked)) DMA1_Stream7_IRQHandler()
141{
142 saveContext();
143 asm volatile("bl _Z20DMA1_Stream7_IRQImplv");
144 restoreContext();
145}
146
147void __attribute__((used)) DMA1_Stream7_IRQImpl()
148{
149 Boardcore::DMADriver::instance().IRQhandleInterrupt(
151}
152
153void __attribute__((naked)) DMA2_Stream0_IRQHandler()
154{
155 saveContext();
156 asm volatile("bl _Z20DMA2_Stream0_IRQImplv");
157 restoreContext();
158}
159
160void __attribute__((used)) DMA2_Stream0_IRQImpl()
161{
162 Boardcore::DMADriver::instance().IRQhandleInterrupt(
164}
165
166void __attribute__((naked)) DMA2_Stream1_IRQHandler()
167{
168 saveContext();
169 asm volatile("bl _Z20DMA2_Stream1_IRQImplv");
170 restoreContext();
171}
172
173void __attribute__((used)) DMA2_Stream1_IRQImpl()
174{
175 Boardcore::DMADriver::instance().IRQhandleInterrupt(
177}
178
179void __attribute__((naked)) DMA2_Stream2_IRQHandler()
180{
181 saveContext();
182 asm volatile("bl _Z20DMA2_Stream2_IRQImplv");
183 restoreContext();
184}
185
186void __attribute__((used)) DMA2_Stream2_IRQImpl()
187{
188 Boardcore::DMADriver::instance().IRQhandleInterrupt(
190}
191
192// This stream is used by miosix for all currently supported
193// boards, so it is simply commented out
194// void __attribute__((naked)) DMA2_Stream3_IRQHandler()
195// {
196// saveContext();
197// asm volatile("bl _Z20DMA2_Stream3_IRQImplv");
198// restoreContext();
199// }
200
201// void __attribute__((used)) DMA2_Stream3_IRQImpl()
202// {
203// Boardcore::DMADriver::instance().IRQhandleInterrupt(
204// Boardcore::DMADefs::DMAStreamId::DMA2_Str3);
205// }
206
207void __attribute__((naked)) DMA2_Stream4_IRQHandler()
208{
209 saveContext();
210 asm volatile("bl _Z20DMA2_Stream4_IRQImplv");
211 restoreContext();
212}
213
214void __attribute__((used)) DMA2_Stream4_IRQImpl()
215{
216 Boardcore::DMADriver::instance().IRQhandleInterrupt(
218}
219
220#if !defined(STM32F767xx) && !defined(STM32F429xx)
221// This stream is used by miosix for STM32F767xx
222// and STM32F429xx boards
223void __attribute__((naked)) DMA2_Stream5_IRQHandler()
224{
225 saveContext();
226 asm volatile("bl _Z20DMA2_Stream5_IRQImplv");
227 restoreContext();
228}
229
230void __attribute__((used)) DMA2_Stream5_IRQImpl()
231{
232 Boardcore::DMADriver::instance().IRQhandleInterrupt(
234}
235#endif // STM32F767xx & STM32F429xx
236
237void __attribute__((naked)) DMA2_Stream6_IRQHandler()
238{
239 saveContext();
240 asm volatile("bl _Z20DMA2_Stream6_IRQImplv");
241 restoreContext();
242}
243
244void __attribute__((used)) DMA2_Stream6_IRQImpl()
245{
246 Boardcore::DMADriver::instance().IRQhandleInterrupt(
248}
249
250#if !defined(STM32F767xx) && !defined(STM32F429xx)
251// This stream is used by miosix for STM32F767xx
252// and STM32F429xx boards
253void __attribute__((naked)) DMA2_Stream7_IRQHandler()
254{
255 saveContext();
256 asm volatile("bl _Z20DMA2_Stream7_IRQImplv");
257 restoreContext();
258}
259
260void __attribute__((used)) DMA2_Stream7_IRQImpl()
261{
262 Boardcore::DMADriver::instance().IRQhandleInterrupt(
264}
265#endif // STM32F767xx & STM32F429xx
266
267namespace Boardcore
268{
269
271{
272 DMAStream& stream = streams.at(id);
273
274 stream.readFlags();
275 stream.clearAllFlags();
276
277 // Run the callbacks if necessary
278 if (stream.halfTransferCallback && stream.halfTransferFlag)
279 stream.halfTransferCallback();
280
281 if (stream.transferCompleteCallback && stream.transferCompleteFlag)
282 stream.transferCompleteCallback();
283
284 if (stream.errorCallback &&
285 (stream.transferErrorFlag || stream.fifoErrorFlag ||
286 stream.directModeErrorFlag))
287 {
288 stream.errorCallback();
289 }
290
291 // Wakeup the thread if the user is waiting
292 if (stream.waitingThread)
293 IRQwakeupThread(stream);
294}
295
296void DMADriver::IRQwakeupThread(DMAStream& stream)
297{
298 // Wakeup the waiting thread
299 stream.waitingThread->wakeup();
300
301 // If the waiting thread has a higher priority than the current
302 // thread then reschedule
303 if (stream.waitingThread->IRQgetPriority() >
304 miosix::Thread::IRQgetCurrentThread()->IRQgetPriority())
305 {
306 miosix::Scheduler::IRQfindNextThread();
307 }
308
309 // Clear the thread pointer, this way the thread will be sure it is
310 // not a spurious wakeup
311 stream.waitingThread = nullptr;
312}
313
315{
316 static DMADriver instance;
317 return instance;
318}
319
321{
322 Lock<FastMutex> l(mutex);
323
324 // Return true, meaning that the channel is free, only if it is not yet
325 // allocated
326 return streams.count(id) == 0;
327}
328
330 DMADefs::Channel channel,
331 std::chrono::nanoseconds timeout)
332{
333 Lock<FastMutex> l(mutex);
334
335 // Wait until the stream is free or the timeout expires
336 while (streams.count(id) != 0)
337 {
338 if (timeout == std::chrono::nanoseconds::zero())
339 {
340 cv.wait(l);
341 }
342 else
343 {
344 auto res = cv.timedWait(l, timeout.count());
345
346 if (res == TimedWaitResult::Timeout)
347 {
348 // The timeout expired
349 return DMAStreamGuard(nullptr);
350 }
351 }
352 }
353
354 streams.insert(
355 std::pair<DMADefs::DMAStreamId, DMAStream>(id, DMAStream(id, channel)));
356 return DMAStreamGuard(&(streams.at(id)));
357}
358
360 DMADefs::Peripherals peripheral, std::chrono::nanoseconds timeout)
361{
362 const auto availableStreams =
363 DMADefs::mapPeripherals.equal_range(peripheral);
364
365 Lock<FastMutex> l(mutex);
366 while (true)
367 {
368 // Iterate through the streams for that peripheral,
369 // return the first available
370 for (auto it = availableStreams.first; it != availableStreams.second;
371 ++it)
372 {
373 DMADefs::DMAStreamId id = it->second.first;
374 DMADefs::Channel channel = it->second.second;
375
376 if (streams.count(id) == 0)
377 {
378 // Stream is free
379 streams.insert(std::pair<DMADefs::DMAStreamId, DMAStream>(
380 id, DMAStream(id, channel)));
381 return DMAStreamGuard(&(streams.at(id)));
382 }
383 }
384
385 if (timeout == std::chrono::nanoseconds::zero())
386 {
387 cv.wait(l);
388 }
389 else
390 {
391 auto res = cv.timedWait(l, timeout.count());
392
393 if (res == TimedWaitResult::Timeout)
394 {
395 // The timeout expired
396 return DMAStreamGuard(nullptr);
397 }
398 }
399 }
400}
401
403{
404 Lock<FastMutex> l(mutex);
405
406 if (streams.count(id) != 0)
407 {
408 streams.erase(id);
409 cv.broadcast();
410 }
411}
412
413DMADriver::DMADriver()
414{
415 // For now the clocks are always enabled
418
419 // Reset interrupts flags by setting the clear bits to 1
420 constexpr int resetValue = 0x0f7d0f7d;
421 DMA1->HIFCR = resetValue;
422 DMA1->LIFCR = resetValue;
423 DMA2->HIFCR = resetValue;
424 DMA2->LIFCR = resetValue;
425}
426
428{
429 currentSetup = transaction;
430
431 // Reset the configuration
432 registers->CR = 0;
433
434 // Wait for the stream to actually be disabled
435 while (registers->CR & DMA_SxCR_EN)
436 ;
437
438 setChannel(currentChannel);
439 registers->CR |= static_cast<uint32_t>(transaction.direction);
440 registers->CR |= static_cast<uint32_t>(transaction.priority);
441 if (transaction.circularMode)
442 registers->CR |= DMA_SxCR_CIRC;
443
445
447 {
448 // In memory to peripheral mode, the source address is the memory
449 // address
450
451 registers->CR |= static_cast<uint32_t>(transaction.srcSize)
452 << DMA_SxCR_MSIZE_Pos;
453 registers->CR |= static_cast<uint32_t>(transaction.dstSize)
454 << DMA_SxCR_PSIZE_Pos;
455
456 if (transaction.srcIncrement)
457 registers->CR |= DMA_SxCR_MINC;
458 if (transaction.dstIncrement)
459 registers->CR |= DMA_SxCR_PINC;
460
461 registers->M0AR = reinterpret_cast<uint32_t>(transaction.srcAddress);
462 registers->PAR = reinterpret_cast<uint32_t>(transaction.dstAddress);
463 }
464 else
465 {
466 // In peripheral to memory or memory to memory mode, the source address
467 // goes into the peripheral address register
468
469 registers->CR |= static_cast<uint32_t>(transaction.srcSize)
470 << DMA_SxCR_PSIZE_Pos;
471 registers->CR |= static_cast<uint32_t>(transaction.dstSize)
472 << DMA_SxCR_MSIZE_Pos;
473
474 if (transaction.srcIncrement)
475 registers->CR |= DMA_SxCR_PINC;
476 if (transaction.dstIncrement)
477 registers->CR |= DMA_SxCR_MINC;
478
479 registers->PAR = reinterpret_cast<uint32_t>(transaction.srcAddress);
480 registers->M0AR = reinterpret_cast<uint32_t>(transaction.dstAddress);
481 }
482
483 if (transaction.doubleBufferMode)
484 {
485 registers->CR |= DMA_SxCR_DBM;
486 registers->M1AR =
487 reinterpret_cast<uint32_t>(transaction.secondMemoryAddress);
488 }
489
490 bool enableInterrupt = false;
491 if (transaction.enableHalfTransferInterrupt)
492 {
494 registers->CR |= DMA_SxCR_HTIE;
495 enableInterrupt = true;
496 }
497 if (transaction.enableTransferCompleteInterrupt)
498 {
500 registers->CR |= DMA_SxCR_TCIE;
501 enableInterrupt = true;
502 }
503 if (transaction.enableTransferErrorInterrupt)
504 {
506 registers->CR |= DMA_SxCR_TEIE;
507 enableInterrupt = true;
508 }
509 if (transaction.enableFifoErrorInterrupt)
510 {
512 registers->FCR |= DMA_SxFCR_FEIE;
513 enableInterrupt = true;
514 }
515 if (transaction.enableDirectModeErrorInterrupt)
516 {
518 registers->CR |= DMA_SxCR_DMEIE;
519 enableInterrupt = true;
520 }
521
522 // Select the interrupt number
523 IRQn_Type irqNumber = DMADefs::irqNumberMapping[static_cast<uint8_t>(id)];
524 if (enableInterrupt)
525 {
526 NVIC_SetPriority(irqNumber, 8);
527 NVIC_ClearPendingIRQ(irqNumber);
528 NVIC_EnableIRQ(irqNumber);
529 }
530 else
531 {
532 NVIC_DisableIRQ(irqNumber);
533 }
534}
535
537{
538 // Reset all saved flags
539 halfTransferFlag = false;
540 transferCompleteFlag = false;
541 transferErrorFlag = false;
542 fifoErrorFlag = false;
543 directModeErrorFlag = false;
544
545 // Before setting EN bit to '1' to start a new transfer, the event
546 // flags corresponding to the stream in DMA_LISR or DMA_HISR
547 // register must be cleared.
549
550 // Enable the peripheral
551 registers->CR |= DMA_SxCR_EN;
552}
553
554void DMAStream::disable() { registers->CR &= ~DMA_SxCR_EN; }
555
557{
558 waitForInterruptEventImpl(
559 currentSetup.enableHalfTransferInterrupt,
560 std::bind(&DMAStream::getHalfTransferFlagStatus, this),
561 std::bind(&DMAStream::clearHalfTransferFlag, this), halfTransferFlag,
562 -1);
563}
564
566{
567 waitForInterruptEventImpl(
570 std::bind(&DMAStream::clearTransferCompleteFlag, this),
571 transferCompleteFlag, -1);
572
573#ifdef STM32F767xx
574 invalidateCache();
575#endif // STM32F767xx
576}
577
578bool DMAStream::timedWaitForHalfTransfer(std::chrono::nanoseconds timeout_ns)
579{
580 return waitForInterruptEventImpl(
581 currentSetup.enableHalfTransferInterrupt,
582 std::bind(&DMAStream::getHalfTransferFlagStatus, this),
583 std::bind(&DMAStream::clearHalfTransferFlag, this), halfTransferFlag,
584 timeout_ns.count());
585}
586
588 std::chrono::nanoseconds timeout_ns)
589{
590 bool ret = waitForInterruptEventImpl(
593 std::bind(&DMAStream::clearTransferCompleteFlag, this),
594 transferCompleteFlag, timeout_ns.count());
595
596#ifdef STM32F767xx
597 invalidateCache();
598#endif // STM32F767xx
599
600 return ret;
601}
602
603#ifdef STM32F767xx
604void DMAStream::invalidateCache()
605{
622 // If the data was copied from memory to a peripheral there's
623 // no need to worry about cache
625 return;
626
627 constexpr uint8_t CACHE_LINE_SIZE = 32;
628
629 // Aligned ptr: round down to the nearest address that is
630 // 32 bytes aligned
631 uintptr_t alignedPtr =
632 (uintptr_t)currentSetup.dstAddress & ~(CACHE_LINE_SIZE - 1);
633
634 // Evaluate how many bytes were added, due to the round down
635 uintptr_t diff = (uintptr_t)currentSetup.dstAddress - alignedPtr;
636
637 // Aligned size: compute the amount of bytes being invalidated
638 int32_t alignedSize = currentSetup.numberOfDataItems;
639 if (currentSetup.dstSize == DMATransaction::DataSize::BITS_16)
640 alignedSize *= 2;
641 else if (currentSetup.dstSize == DMATransaction::DataSize::BITS_32)
642 alignedSize *= 4;
643 alignedSize += diff;
644
645 SCB_InvalidateDCache_by_Addr((uint32_t*)alignedPtr, alignedSize);
646}
647#endif // STM32F767xx
648
649void DMAStream::setHalfTransferCallback(std::function<void()> callback)
650{
651 halfTransferCallback = callback;
652}
653
654void DMAStream::resetHalfTransferCallback() { halfTransferCallback = nullptr; }
655
656void DMAStream::setTransferCompleteCallback(std::function<void()> callback)
657{
658 transferCompleteCallback = callback;
659}
660
662{
663 transferCompleteCallback = nullptr;
664}
665
666void DMAStream::setErrorCallback(std::function<void()> callback)
667{
668 errorCallback = callback;
669}
670
671void DMAStream::resetErrorCallback() { errorCallback = nullptr; }
672
674{
675 uint8_t flags = *ISR >> IFindex;
676
677 halfTransferFlag = flags & DMA_LISR_HTIF0;
678 transferCompleteFlag = flags & DMA_LISR_TCIF0;
679 transferErrorFlag = flags & DMA_LISR_TEIF0;
680 fifoErrorFlag = flags & DMA_LISR_DMEIF0;
681 directModeErrorFlag = flags & DMA_LISR_DMEIF0;
682}
683
684bool DMAStream::setNumberOfDataItems(const uint16_t nBytes)
685{
686 // Verify that the stream is disabled while doing it
687 if ((registers->CR & DMA_SxCR_EN) != 0)
688 {
689 // Cannot proceed
690 return false;
691 }
692
693 currentSetup.numberOfDataItems = nBytes;
694 registers->NDTR = nBytes;
695 return true;
696}
697
699{
700 registers->CR |= static_cast<uint32_t>(channel);
701}
702
704{
705 return (registers->CR & DMA_SxCR_CT) != 0 ? 2 : 1;
706}
707
708DMAStream::DMAStream(DMADefs::DMAStreamId id, DMADefs::Channel channel)
709 : id(id), currentChannel(channel)
710{
711 // Get the channel registers base address and the interrupt flags clear
712 // register address
714 {
715 registers = reinterpret_cast<DMA_Stream_TypeDef*>(
716 DMA1_BASE + 0x10 + 0x18 * static_cast<uint8_t>(id));
717
719 {
720 // Streams from 0 to 3 use low registers (LIFCR and LISR)
721 IFCR = &DMA1->LIFCR;
722 ISR = &DMA1->LISR;
723 }
724 else
725 {
726 // Streams from 4 to 7 use high registers (HIFCR and HISR)
727 IFCR = &DMA1->HIFCR;
728 ISR = &DMA1->HISR;
729 }
730 }
731 else
732 {
733 registers = reinterpret_cast<DMA_Stream_TypeDef*>(
734 DMA2_BASE + 0x10 + 0x18 * (static_cast<uint8_t>(id) - 8));
735
737 {
738 // Streams from 0 to 3 use low registers (LIFCR and LISR)
739 IFCR = &DMA2->LIFCR;
740 ISR = &DMA2->LISR;
741 }
742 else
743 {
744 // Streams from 4 to 7 use high registers (HIFCR and HISR)
745 IFCR = &DMA2->HIFCR;
746 ISR = &DMA2->HISR;
747 }
748 }
749
750 // Compute the index for the interrupt flags clear register
751 // Refer to reference manual for the register bits structure
752 int offset = static_cast<uint8_t>(id) % 4;
753 IFindex = (offset % 2) * 6 + (offset / 2) * 16;
754}
755
757{
758 D(assert((pStream != nullptr) && "DMAStreamGuard: pointer is null"));
759
760 return pStream;
761}
762
763} // namespace Boardcore
void __attribute__((naked)) DMA1_Stream0_IRQHandler()
Definition DMA.cpp:43
#define D(x)
Definition Debug.h:57
This class is responsible for streams acquisition, streams release and interrupt handling.
Definition DMA.h:155
DMAStreamGuard acquireStreamForPeripheral(DMADefs::Peripherals peripheral, std::chrono::nanoseconds timeout=std::chrono::nanoseconds::zero())
Try to acquire a stream that is connected to the specified peripheral.
Definition DMA.cpp:359
static DMADriver & instance()
Definition DMA.cpp:314
DMAStreamGuard acquireStream(DMADefs::DMAStreamId id, DMADefs::Channel channel, std::chrono::nanoseconds timeout=std::chrono::nanoseconds::zero())
Try to acquire the specified stream and initialize it with the correct channel.
Definition DMA.cpp:329
void IRQhandleInterrupt(DMADefs::DMAStreamId id)
Definition DMA.cpp:270
void releaseStream(DMADefs::DMAStreamId id)
Definition DMA.cpp:402
bool tryStream(DMADefs::DMAStreamId id)
Definition DMA.cpp:320
Simple RAII class to handle DMA streams.
Definition DMA.h:544
DMAStream * operator->()
Definition DMA.cpp:756
This class represents the actual DMA stream. It can be used to setup, start and stop DMA transactions...
Definition DMA.h:219
bool getHalfTransferFlagStatus()
Returns the last read status of the half transfer flag.
Definition DMA.h:326
bool timedWaitForTransferComplete(std::chrono::nanoseconds timeout_ns)
Wait for the transfer complete signal. The caller waits for the corresponding interrupt,...
Definition DMA.cpp:587
void clearDirectModeErrorFlag()
Definition DMA.h:377
void resetTransferCompleteCallback()
Definition DMA.cpp:661
void disable()
Stop the DMA transaction (if running). This is equivalent to killing the transaction: DO NOT expect t...
Definition DMA.cpp:554
void clearFifoErrorFlag()
Definition DMA.h:375
void clearTransferErrorFlag()
Definition DMA.h:370
void clearAllFlags()
Clear all the flags for the selected stream in the DMA ISR register (LISR or HISR depending on the se...
Definition DMA.h:386
int getCurrentBufferNumber()
Returns the number of the buffer currently in use when in double buffer mode.
Definition DMA.cpp:703
bool getTransferCompleteFlagStatus()
Returns the last read status of the transfer complete flag.
Definition DMA.h:331
void setup(DMATransaction &transaction)
Setup the stream with the given configuration.
Definition DMA.cpp:427
void resetErrorCallback()
Definition DMA.cpp:671
bool timedWaitForHalfTransfer(std::chrono::nanoseconds timeout_ns)
Wait for the half transfer complete signal. The caller waits for the corresponding interrupt,...
Definition DMA.cpp:578
void clearTransferCompleteFlag()
Definition DMA.h:365
void setErrorCallback(std::function< void()> callback)
Definition DMA.cpp:666
void resetHalfTransferCallback()
Definition DMA.cpp:654
void setTransferCompleteCallback(std::function< void()> callback)
Definition DMA.cpp:656
bool setNumberOfDataItems(const uint16_t nBytes)
Set the number of bytes to be exchanged during a dma transaction. Useful in case you don't want to ch...
Definition DMA.cpp:684
void enable()
Activate the stream. As soon as the stream is enabled, it serves any DMA request from/to the peripher...
Definition DMA.cpp:536
void waitForTransferComplete()
Wait for the transfer complete signal. The caller waits for the corresponding interrupt,...
Definition DMA.cpp:565
void readFlags()
Reads the current flags status.
Definition DMA.cpp:673
void setHalfTransferCallback(std::function< void()> callback)
Definition DMA.cpp:649
void waitForHalfTransfer()
Wait for the half transfer complete signal. The caller waits for the corresponding interrupt,...
Definition DMA.cpp:556
void clearHalfTransferFlag()
Definition DMA.h:360
void setChannel(const DMADefs::Channel channel)
Select the channel to be used by the stream during the transactions.
Definition DMA.cpp:698
bool enablePeripheralClock(void *peripheral)
Enables a peripheral clock source from the APB1 and APB2 peripheral buses.
Definition ClockUtils.h:155
const IRQn_Type irqNumberMapping[]
Mapping between DMAStreamId and the corresponding irq number. This is needed because irq number value...
Definition DMADefs.cpp:60
Peripherals
All the peripherals connected to dma.
Definition DMADefs.h:130
Channel
Channels selectable for each dma stream.
Definition DMADefs.h:106
const std::multimap< Peripherals, std::pair< DMAStreamId, Channel > > mapPeripherals
Maps the peripherals to the dma streams (and the corresponding channel) that are connected with.
This file includes all the types the logdecoder script will decode.
This is the configuration struct for a DMA transaction.
Definition DMA.h:42
bool enableFifoErrorInterrupt
Definition DMA.h:130
bool enableHalfTransferInterrupt
Definition DMA.h:106
uint16_t numberOfDataItems
Definition DMA.h:82
bool enableTransferErrorInterrupt
Definition DMA.h:116
volatile void * secondMemoryAddress
Definition DMA.h:81
volatile void * dstAddress
Definition DMA.h:80
volatile void * srcAddress
Definition DMA.h:79
bool doubleBufferMode
Enables double buffer mode.
Definition DMA.h:97
bool enableDirectModeErrorInterrupt
Definition DMA.h:143
Direction direction
Definition DMA.h:75
bool enableTransferCompleteInterrupt
Definition DMA.h:98
bool circularMode
Enables circular buffer mode.
Definition DMA.h:90