I'm not even exactly sure how to describe this problem, so please bear with me. I have a setup with two nRF52840s, one of them (call it B) functions as a peripheral server with two available connections, one for phone/host, one for the other unit, and the other (call it A) function as a central device with respect to the other unit and a peripheral device to the phone/host. I am having an issue where during a coordinated activity (the A unit and B unit play some audio via I2S after some signaling from the A unit) the B unit somewhat mysteriously seems to reset - but I never see it in the debugger. I'm using SES, and even though it's clear the the unit resets, I don't catch anything with the debugger.
So I decided to turn to Ozone since it is more powerful. I am pretty sure that the problem is somewhere in my I2S code. I have two buffers, one in RAM6 and one in RAM7, each 2176 bytes (the size of a page of the flash IC), in order to prevent bus contention. I fill both buffers before starting I2S, then I fill the released buffer using SPI from an external flash IC while the other one is playing. I decided to cordon off what I think is the offending code with a degenerate counter:
if (!p_released->p_tx_buffer) { // Code to assign next buffers } else { // The driver has just finished accessing the buffers pointed by // 'p_released'. They can be used for the next part of the transfer // that will be scheduled now. if (++count != SOME_VALUE) { // Set next buffers and start filling released buffer } else { // Set next buffers and start filling released buffer // Identical to above } }
Here is the behavior I am seeing:
- If I run without any breakpoints, I get about a second of audio, something like 60 buffers' worth, then a reset of the B unit - I hit no breakpoints (including vector catch on reset) in any fault or error handlers and the debugger is disconnected with an error message in Ozone telling me that the debugger was disconnected. In SES I see nothing at all even though the unit has clearly reset. Here are screenshots:
- If I put a breakpoint in the "else" block above, the audio plays fine until I hit the counter, can be many seconds of audio. If I use SES it will play all the way to the end of the audio clip.
- If I put a conditional breakpoint in the "if" block above and set a condition like "count == 200", the application enters the error handler (the default SDK app_error_fault_handler) with case NRF_FAULT_ID_SDK_ERROR (id = 0x4001), but there is no file name in the memory pointed to by p_info->p_file_name and line number is clearly invalid (values in the billions).
I'm not really sure what to do with this behavior. Clearly something is making the application work when I debug it a certain way, but I'm not sure how to figure out what that is. I am almost certain that at some point I have some sort of memory contention, but without being able to recreate it reliably and see what the values are at given breaks, it is very challenging to troubleshoot. Has anyone else seen similar? What did you do to get past it?
**EDIT**
I still am interested in how one might debug a situation like this, but I am starting to have a gut feeling. Is it possible that the I2S hasn't actually released the buffer pointed to by p_released at the time of the interrupt handler? I vaguely recall having seen someone mention this somewhere, but now I can't find it. If this is the case, it could be the source of our problem since I kick off filling the next buffer pretty quickly in the callback.