Direct Memory Access (DMA)
Circle supports Direct Memory Access (DMA) using the platform DMA controller of the Raspberry Pi. This is implemented in the class CDMAChannel.
Note
Currently only memory copy DMA transfers using “large address” DMA4 engines are supported on the Raspberry Pi 5. Any dynamic DMA channel allocation (non-explicit channel number) will use one of these engines.
CDMAChannel
#include <circle/dmachannel.h>
-
class CDMAChannel
-
CDMAChannel::CDMAChannel(unsigned nChannel, CInterruptSystem *pInterruptSystem = 0)
Creates an instance of
CDMAChanneland allocates a channel of the platform DMA controller.nChannelmust beDMA_CHANNEL_NORMAL(normal DMA engine),DMA_CHANNEL_LITE(lite (or normal) DMA engine),DMA_CHANNEL_EXTENDED(“large address” DMA4 engine, on Raspberry Pi 4 and 5 only) or an explicit channel number (0-15).pInterruptSystemis a pointer to the instance ofCInterruptSystemand is only needed for interrupt operation.
-
void CDMAChannel::SetupMemCopy(void *pDestination, const void *pSource, size_t nLength, unsigned nBurstLength = 0, boolean bCached = TRUE)
Setup a DMA memory copy transfer from
pSourcetopDestinationwith lengthnLength.nBurstLength> 0 increases the speed, but may congest the system bus.bCacheddetermines, if the source and destination address ranges are in cached memory.
-
void CDMAChannel::SetupIORead(void *pDestination, u32 nIOAddress, size_t nLength, TDREQ DREQ)
Setup a DMA read transfer from the I/O port
nIOAddresstopDestinationwith lengthnLength.DREQpaces the transfer from these devices:
DREQSourceNone (no wait)
DREQSourceEMMC
DREQSourcePCMRX
DREQSourceSMI
DREQSourceSPIRX
DREQSourceUARTRX
-
void CDMAChannel::SetupIOWrite(u32 nIOAddress, const void *pSource, size_t nLength, TDREQ DREQ)
Setup a DMA write transfer to the I/O port
nIOAddressfrompSourcewith lengthnLength.DREQpaces the transfer to these devices:
DREQSourceNone (no wait)
DREQSourceEMMC
DREQSourcePCMTX
DREQSourcePWM
DREQSourcePWM1 (on Raspberry Pi 4 only)
DREQSourceSMI
DREQSourceSPITX
DREQSourceUARTTX
-
void CDMAChannel::SetupMemCopy2D(void *pDestination, const void *pSource, size_t nBlockLength, unsigned nBlockCount, size_t nBlockStride, unsigned nBurstLength = 0)
Setup a 2D DMA memory copy transfer of
nBlockCountblocks ofnBlockLengthlength frompSourcetopDestination. SkipnBlockStridebytes after each block on destination. Source is continuous. The destination cache, if any, is not touched.nBurstLength> 0 increases speed, but may congest the system bus. This method can be used to copy data to the framebuffer and is not supported withDMA_CHANNEL_LITE.
-
void CDMAChannel::SetCompletionRoutine(TDMACompletionRoutine *pRoutine, void *pParam)
Sets a DMA completion routine for interrupt operation.
pRoutineis called, when the transfer is completed.pParamis a user parameter, which is handed over to the completion routine.TDMACompletionRoutinehas the following prototype:
void TDMACompletionRoutine (unsigned nChannel, boolean bStatus, void *pParam);
nChannel is the channel number. bStatus is TRUE, if the transfer completed successfully.
-
void CDMAChannel::Start(void)
Starts the DMA transfer, which has been setup before.
-
boolean CDMAChannel::Wait(void)
Waits for the completion of the DMA transfer (for synchronous non-interrupt operation without completion routine). Returns
TRUE, if the transfer was successful.
-
boolean CDMAChannel::GetStatus(void)
Returns
TRUE, if the last completed transfer was successful.
DMA buffers
#include <circle/synchronize.h>
-
DMA_BUFFER(type, name, num)
Defines a buffer with
nameandnumelements oftypeto be used for DMA transfers.See doc/dma-buffer-requirements.txt for more information on DMA buffers.
Cache maintenance
#include <circle/synchronize.h>
-
void CleanAndInvalidateDataCacheRange(uintptr nAddress, size_t nLength)
Cleans and invalidates a memory range in the data cache.