25#include <kernel/logging.h>
46 asm volatile(
"bl _Z20DMA1_Stream0_IRQImplv");
61 asm volatile(
"bl _Z20DMA1_Stream1_IRQImplv");
75 asm volatile(
"bl _Z20DMA1_Stream2_IRQImplv");
90 asm volatile(
"bl _Z20DMA1_Stream3_IRQImplv");
104 asm volatile(
"bl _Z20DMA1_Stream4_IRQImplv");
117 asm volatile(
"bl _Z20DMA1_Stream5_IRQImplv");
130 asm volatile(
"bl _Z20DMA1_Stream6_IRQImplv");
143 asm volatile(
"bl _Z20DMA1_Stream7_IRQImplv");
156 asm volatile(
"bl _Z20DMA2_Stream0_IRQImplv");
169 asm volatile(
"bl _Z20DMA2_Stream1_IRQImplv");
182 asm volatile(
"bl _Z20DMA2_Stream2_IRQImplv");
210 asm volatile(
"bl _Z20DMA2_Stream4_IRQImplv");
220#if !defined(STM32F767xx) && !defined(STM32F429xx)
226 asm volatile(
"bl _Z20DMA2_Stream5_IRQImplv");
240 asm volatile(
"bl _Z20DMA2_Stream6_IRQImplv");
250#if !defined(STM32F767xx) && !defined(STM32F429xx)
256 asm volatile(
"bl _Z20DMA2_Stream7_IRQImplv");
275 stream.clearAllFlags();
278 if (stream.halfTransferCallback && stream.halfTransferFlag)
279 stream.halfTransferCallback();
281 if (stream.transferCompleteCallback && stream.transferCompleteFlag)
282 stream.transferCompleteCallback();
284 if (stream.errorCallback &&
285 (stream.transferErrorFlag || stream.fifoErrorFlag ||
286 stream.directModeErrorFlag))
288 stream.errorCallback();
292 if (stream.waitingThread)
293 IRQwakeupThread(stream);
296void DMADriver::IRQwakeupThread(
DMAStream& stream)
299 stream.waitingThread->wakeup();
303 if (stream.waitingThread->IRQgetPriority() >
304 miosix::Thread::IRQgetCurrentThread()->IRQgetPriority())
306 miosix::Scheduler::IRQfindNextThread();
311 stream.waitingThread =
nullptr;
322 Lock<FastMutex> l(mutex);
326 return streams.count(
id) == 0;
331 std::chrono::nanoseconds timeout)
333 Lock<FastMutex> l(mutex);
336 while (streams.count(
id) != 0)
338 if (timeout == std::chrono::nanoseconds::zero())
344 auto res = cv.timedWait(l, timeout.count());
346 if (res == TimedWaitResult::Timeout)
355 std::pair<DMADefs::DMAStreamId, DMAStream>(
id,
DMAStream(
id, channel)));
362 const auto availableStreams =
365 Lock<FastMutex> l(mutex);
370 for (
auto it = availableStreams.first; it != availableStreams.second;
376 if (streams.count(
id) == 0)
379 streams.insert(std::pair<DMADefs::DMAStreamId, DMAStream>(
385 if (timeout == std::chrono::nanoseconds::zero())
391 auto res = cv.timedWait(l, timeout.count());
393 if (res == TimedWaitResult::Timeout)
404 Lock<FastMutex> l(mutex);
406 if (streams.count(
id) != 0)
413DMADriver::DMADriver()
420 constexpr int resetValue = 0x0f7d0f7d;
421 DMA1->HIFCR = resetValue;
422 DMA1->LIFCR = resetValue;
423 DMA2->HIFCR = resetValue;
424 DMA2->LIFCR = resetValue;
429 currentSetup = transaction;
435 while (registers->CR & DMA_SxCR_EN)
439 registers->CR |=
static_cast<uint32_t
>(transaction.
direction);
440 registers->CR |=
static_cast<uint32_t
>(transaction.
priority);
442 registers->CR |= DMA_SxCR_CIRC;
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;
457 registers->CR |= DMA_SxCR_MINC;
459 registers->CR |= DMA_SxCR_PINC;
461 registers->M0AR =
reinterpret_cast<uint32_t
>(transaction.
srcAddress);
462 registers->PAR =
reinterpret_cast<uint32_t
>(transaction.
dstAddress);
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;
475 registers->CR |= DMA_SxCR_PINC;
477 registers->CR |= DMA_SxCR_MINC;
479 registers->PAR =
reinterpret_cast<uint32_t
>(transaction.
srcAddress);
480 registers->M0AR =
reinterpret_cast<uint32_t
>(transaction.
dstAddress);
485 registers->CR |= DMA_SxCR_DBM;
490 bool enableInterrupt =
false;
494 registers->CR |= DMA_SxCR_HTIE;
495 enableInterrupt =
true;
500 registers->CR |= DMA_SxCR_TCIE;
501 enableInterrupt =
true;
506 registers->CR |= DMA_SxCR_TEIE;
507 enableInterrupt =
true;
512 registers->FCR |= DMA_SxFCR_FEIE;
513 enableInterrupt =
true;
518 registers->CR |= DMA_SxCR_DMEIE;
519 enableInterrupt =
true;
526 NVIC_SetPriority(irqNumber, 8);
527 NVIC_ClearPendingIRQ(irqNumber);
528 NVIC_EnableIRQ(irqNumber);
532 NVIC_DisableIRQ(irqNumber);
539 halfTransferFlag =
false;
540 transferCompleteFlag =
false;
541 transferErrorFlag =
false;
542 fifoErrorFlag =
false;
543 directModeErrorFlag =
false;
551 registers->CR |= DMA_SxCR_EN;
558 waitForInterruptEventImpl(
567 waitForInterruptEventImpl(
571 transferCompleteFlag, -1);
580 return waitForInterruptEventImpl(
588 std::chrono::nanoseconds timeout_ns)
590 bool ret = waitForInterruptEventImpl(
594 transferCompleteFlag, timeout_ns.count());
604void DMAStream::invalidateCache()
627 constexpr uint8_t CACHE_LINE_SIZE = 32;
631 uintptr_t alignedPtr =
632 (uintptr_t)currentSetup.
dstAddress & ~(CACHE_LINE_SIZE - 1);
635 uintptr_t diff = (uintptr_t)currentSetup.
dstAddress - alignedPtr;
645 SCB_InvalidateDCache_by_Addr((uint32_t*)alignedPtr, alignedSize);
651 halfTransferCallback = callback;
658 transferCompleteCallback = callback;
663 transferCompleteCallback =
nullptr;
668 errorCallback = callback;
675 uint8_t flags = *ISR >> IFindex;
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;
687 if ((registers->CR & DMA_SxCR_EN) != 0)
694 registers->NDTR = nBytes;
700 registers->CR |=
static_cast<uint32_t
>(channel);
705 return (registers->CR & DMA_SxCR_CT) != 0 ? 2 : 1;
709 : id(id), currentChannel(channel)
715 registers =
reinterpret_cast<DMA_Stream_TypeDef*
>(
716 DMA1_BASE + 0x10 + 0x18 *
static_cast<uint8_t
>(id));
733 registers =
reinterpret_cast<DMA_Stream_TypeDef*
>(
734 DMA2_BASE + 0x10 + 0x18 * (
static_cast<uint8_t
>(id) - 8));
752 int offset =
static_cast<uint8_t
>(id) % 4;
753 IFindex = (offset % 2) * 6 + (offset / 2) * 16;
758 D(assert((pStream !=
nullptr) &&
"DMAStreamGuard: pointer is null"));
void __attribute__((naked)) DMA1_Stream0_IRQHandler()
This class is responsible for streams acquisition, streams release and interrupt handling.
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.
static DMADriver & instance()
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.
void IRQhandleInterrupt(DMADefs::DMAStreamId id)
void releaseStream(DMADefs::DMAStreamId id)
bool tryStream(DMADefs::DMAStreamId id)
Simple RAII class to handle DMA streams.
This class represents the actual DMA stream. It can be used to setup, start and stop DMA transactions...
bool getHalfTransferFlagStatus()
Returns the last read status of the half transfer flag.
bool timedWaitForTransferComplete(std::chrono::nanoseconds timeout_ns)
Wait for the transfer complete signal. The caller waits for the corresponding interrupt,...
void clearDirectModeErrorFlag()
void resetTransferCompleteCallback()
void disable()
Stop the DMA transaction (if running). This is equivalent to killing the transaction: DO NOT expect t...
void clearFifoErrorFlag()
void clearTransferErrorFlag()
void clearAllFlags()
Clear all the flags for the selected stream in the DMA ISR register (LISR or HISR depending on the se...
int getCurrentBufferNumber()
Returns the number of the buffer currently in use when in double buffer mode.
bool getTransferCompleteFlagStatus()
Returns the last read status of the transfer complete flag.
void setup(DMATransaction &transaction)
Setup the stream with the given configuration.
void resetErrorCallback()
bool timedWaitForHalfTransfer(std::chrono::nanoseconds timeout_ns)
Wait for the half transfer complete signal. The caller waits for the corresponding interrupt,...
void clearTransferCompleteFlag()
void setErrorCallback(std::function< void()> callback)
void resetHalfTransferCallback()
void setTransferCompleteCallback(std::function< void()> callback)
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...
void enable()
Activate the stream. As soon as the stream is enabled, it serves any DMA request from/to the peripher...
void waitForTransferComplete()
Wait for the transfer complete signal. The caller waits for the corresponding interrupt,...
void readFlags()
Reads the current flags status.
void setHalfTransferCallback(std::function< void()> callback)
void waitForHalfTransfer()
Wait for the half transfer complete signal. The caller waits for the corresponding interrupt,...
void clearHalfTransferFlag()
void setChannel(const DMADefs::Channel channel)
Select the channel to be used by the stream during the transactions.
bool enablePeripheralClock(void *peripheral)
Enables a peripheral clock source from the APB1 and APB2 peripheral buses.
const IRQn_Type irqNumberMapping[]
Mapping between DMAStreamId and the corresponding irq number. This is needed because irq number value...
Peripherals
All the peripherals connected to dma.
Channel
Channels selectable for each dma stream.
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.
bool enableFifoErrorInterrupt
bool enableHalfTransferInterrupt
uint16_t numberOfDataItems
bool enableTransferErrorInterrupt
volatile void * secondMemoryAddress
volatile void * dstAddress
volatile void * srcAddress
bool doubleBufferMode
Enables double buffer mode.
bool enableDirectModeErrorInterrupt
bool enableTransferCompleteInterrupt
bool circularMode
Enables circular buffer mode.