arduino / arduino/ArduinoCore-samd
DMA I2S callback not triggering at high frequency
- Dominant language
- C
- Stars
- 502
- Forks
- 740
- PR merge metrics
- No merged PRs in 30d
Description
Hello,
We are using the I2S library in order to read data from an ICS43432 with a SAMD21 in order to develop applications for ambient noise frequency analysis, within the [SmartCitizen](https://github.com/fablabbcn/smartcitizen-kit-20) project.
We are facing an issue within the library that halts the _I2S_ receive process, due to a `DMA.onTransferComplete(_dmaChannel, I2SClass::onDmaTransferComplete);` callback not being raised after a DMA transfer. This provokes the doubleBuffer system to never be updated since neither the `I2S.read(buffer, size)` nor the `I2S.onTransferComplete()` functions go through the process of rising another `DMA.transfer` and therefore not returning anything. Here is the code in question:
```
int I2SClass::read(void* buffer, size_t size)
{
if (_state != I2S_STATE_RECEIVER) {
enableReceiver();
}
uint8_t enableInterrupts = ((__get_PRIMASK() & 0x1) == 0);
// disable interrupts,
__disable_irq();
int read = _doubleBuffer.read(buffer, size);
if (_dmaTransferInProgress == false && _doubleBuffer.available() == 0) {
// no DMA transfer in progress, start a receive process
_dmaTransferInProgress = true;
DMA.transfer(_dmaChannel, i2sd.data(_deviceIndex), _doubleBuffer.data(), _doubleBuffer.availableForWrite());
// switch to the next buffer for user output (will be empty)
_doubleBuffer.swap();
}
if (enableInterrupts) {
// re-enable the interrupts
__enable_irq();
}
return read;
}
```
In case of `_dmaTransferInProgress == true`, due to a faulty DMA callback, the I2S.read() always returns zeroes since no buffer is available after emptying the allocated `_doubleBuffer`. This issue takes place normally at _high sampling rates_ (our use case is 44.1kHz) for the microphone and, from our point of view, randomly. We assume though that since the `DMA.onTransferComplete` is triggered by a DMA software trigger, the `i2sd.data()` itself shouldn't be the rootcause, but this is just an assumption out of our lack of expertise about the I2S and DMA interactions in depth.
--> Therefore, we wonder if this issue can be due to a DMA callback failure itself? Is there a way we can check if this is the case and/or try to find if the data is being still received from the I2S? We will try to provide some debugging data from _gdb_ if possible, since the issue is a bit tricky to catch.
**NB**: This was also raised after testing out the ArduinoSound library in this [issue](https://github.com/arduino-libraries/ArduinoSound/issues/3), although further analysis of the event lead us to this point.
Thank you in advance!
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.