Issues with DMAChannels

Just done a quick test, and all appears to be well for my use case :) I've been able to remove the machinations with dma_channel_allocated_mask, and audio and async display updates continue to co-exist peacefully.
 
Time for some hackery...
I wanted my code (that uses pre-emptible channels) to work with either the "new" DMA begin function (that has two arguments) or the original, so I made some templates:
Code:
template <typename C>
void DMABEGIN(C& dma, void (DMAChannel::*)(bool, bool)) {
  dma.begin(true, true);
}
template <typename C>
void DMABEGIN(C& dma, void (DMAChannel::*)(bool)) {
  dma.begin(true);
}
Then instead of calling begin() directly I use this:
Code:
DMAChannel ch(false);
...
DMABEGIN(ch, &DMAChannel::begin);
and the compiler magically works out whether to invoke the one or two parameter version. Templated functions means an error won't be thrown when the two-parameter version of begin() doesn't exist because that template won't be instantiated.
 
I think I've discovered a very big oversight in the audio library that is contributing to the "I2S loves to underrun when DMA is delayed" issue.
This is where the transmit watermark is set. Here's a quote from the reference manual:
The transmit FIFO request flag sets when the number of entries in any of the enabled
transmit FIFOs is less than or equal to the transmit FIFO watermark configuration and
clears when the number of entries in each enabled transmit FIFO is greater than the
transmit FIFO watermark configuration.
See the problem here? The watermark is being set at the minimum level - so I2S isn't requesting DMA until it's practically empty. In fact if you check the I2S-based SPDIF output modules, they use a value of 0 meaning they're basically running on empty the entire time.

The transmit FIFO watermark should be high so that the TX FIFO is kept as full as possible.
 
The transmit FIFO watermark should be high so that the TX FIFO is kept as full as possible.
Wouldn't this increase latency somehow? Some project needs minimum latency, others might need more tolerance to DMA underruns, so maybe the FIFO watermark should be somewhat configurable, preferably?

Marc
 
The latency of 1 audio block is already there: data is copied from the audioblock into a temporary buffer, which then gets DMA'd to I2S as it requests it.

What it looks like to me is that code from Teensy 3.x was blindly reused for Teensy 4.x despite the watermark setting operating differently.
 
Another fun bug discovered:
- create a static DMAChannel object, using the "DMAChannel(bool allocate)" method with allocate set to false. No initialization is performed, the members of the class will be set to zero (static memory is cleared at device startup).
- call release() on the object. DMA Channel 0 gets nuked despite not being owned by this DMAChannel instance.

The same thing can be triggered with dynamically allocated DMAChannel instances, except in that case the channel that gets nuked is random since it depends on the previous contents of the allocated memory. Note that delete'ing an instance causes the destructor to automatically call release().

The fix: set the default value for the "channel" class member to DMA_NUM_CHANNELS.
 
Back
Top