I'm having a problem related to Teensyduino's DMAChannels/eDMA module and am curious to hear any suggestions.
My project is for the T4. I have display driver code that constantly uses a pair of DMAChannels to render data. These channels are "bursty" - they activate infrequently to transfer large amounts of data from one part of memory to another.
I also have an I2S DAC connected (a PCM5102 but that's not particularly relevant) driven by the Audio library using an AudioOutputI2S object. This also uses a DMAChannel to feed the SAI TDR register as required to maintain continuous playback.
The problem: when the bursty DMA channels activate, they are given priority over the audio DMA channel. This lasts long enough that the audio output underruns (which the audio library doesn't attempt to handle) and it shuts off completely. The entire Audio library stops functioning due to the updates not being triggered.
The DMA channels operate in fixed priority mode. Higher channel numbers by default are given priority over lower ones. The DMAChannels are more-or-less initialized statically, which means their order is up to the whim of the compiler.
Inevitably the AudioOutputI2S object seems to get initialized first, meaning its DMAChannel ends up using channel 0 with the lowest priority.
It's a protected member of the class so it's inaccessible without breaking the API, meaning I can't use the DMAPriorityOrder() functions to give it higher priority than the display DMA channels.
The DMA engine has individual registers for setting each channel's priority, but you can't touch them once the DMA engine has been initialized without running the risk of triggering a priority conflict error (they are 8-bit registers and every channel must have a unique value).
The DMAChannel library only manages the lowest 16 channels; there are another 16 channels above those, but there is no API method to allocate them. If you use them you run the risk of stomping on someone else's code. Plus the upper 16 channels belong to group 1 while the lower 16 channels are all group 0, and group 1 by default has higher priority while I want my display channels to be lower priority.
I could reverse this by rewriting the DMA_CR register to switch the channel group priorities. But if another DMAChannel is initialized after this, it will reinitialize the DMA_CR register to the default setting (group 1 back to higher priority over group 0). Likewise for reconfiguring DMA_CR to active round-robin mode rather than fixed priority mode.
So in short, I'm stuck. I want my code to be portable and usable with other libraries, but the DMAChannel library isn't flexible enough and will potentially stomp on any workarounds I try to use.
My project is for the T4. I have display driver code that constantly uses a pair of DMAChannels to render data. These channels are "bursty" - they activate infrequently to transfer large amounts of data from one part of memory to another.
I also have an I2S DAC connected (a PCM5102 but that's not particularly relevant) driven by the Audio library using an AudioOutputI2S object. This also uses a DMAChannel to feed the SAI TDR register as required to maintain continuous playback.
The problem: when the bursty DMA channels activate, they are given priority over the audio DMA channel. This lasts long enough that the audio output underruns (which the audio library doesn't attempt to handle) and it shuts off completely. The entire Audio library stops functioning due to the updates not being triggered.
The DMA channels operate in fixed priority mode. Higher channel numbers by default are given priority over lower ones. The DMAChannels are more-or-less initialized statically, which means their order is up to the whim of the compiler.
Inevitably the AudioOutputI2S object seems to get initialized first, meaning its DMAChannel ends up using channel 0 with the lowest priority.
It's a protected member of the class so it's inaccessible without breaking the API, meaning I can't use the DMAPriorityOrder() functions to give it higher priority than the display DMA channels.
The DMA engine has individual registers for setting each channel's priority, but you can't touch them once the DMA engine has been initialized without running the risk of triggering a priority conflict error (they are 8-bit registers and every channel must have a unique value).
The DMAChannel library only manages the lowest 16 channels; there are another 16 channels above those, but there is no API method to allocate them. If you use them you run the risk of stomping on someone else's code. Plus the upper 16 channels belong to group 1 while the lower 16 channels are all group 0, and group 1 by default has higher priority while I want my display channels to be lower priority.
I could reverse this by rewriting the DMA_CR register to switch the channel group priorities. But if another DMAChannel is initialized after this, it will reinitialize the DMA_CR register to the default setting (group 1 back to higher priority over group 0). Likewise for reconfiguring DMA_CR to active round-robin mode rather than fixed priority mode.
So in short, I'm stuck. I want my code to be portable and usable with other libraries, but the DMAChannel library isn't flexible enough and will potentially stomp on any workarounds I try to use.