arduino / arduino/ArduinoCore-samd

DMA I2S callback not triggering at high frequency

Open
#294 5 comments 0 reactions 2 assignees Claimed by @agdl View on GitHub
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.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.