-
Notifications
You must be signed in to change notification settings - Fork 1.2k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Pico2W crashes when sequentially streaming mp3 from URLs #9983
Comments
This could be due to the gSPI clock getting divided by 3 for this board. See micropython#16057. To eliminate this as a possibility, try changing |
Thanks, I will try. |
No change, this did not help. |
@bablokb Thanks for giving that a try. I was able to reproduce on a Pimoroni Pico Plus 2W with a debug build. MP3 playback is hanging up in an interrupt loop involving
|
I made a change in #9980 which was fixing a different crash involving picodvi. I don't think it would fix this, but you might try an artifact build from from that PR. |
Same failure with the artifact from #9980.
|
@eightycc Thanks for the analysis. Just to learn something for the future: how do I get the backtrace? Is it automatic with creating a build with |
The backtrace is from the GDB command |
The interrupt loop and the state of the DMA section are interesting. CircuitPython overrides |
This is not a good idea and I want to fix this. There is discussion in #9868 about this, and #9980 uses that routine. As a first step for solving #9868, I want to make DMA0 be the shared DMA used for multiple purposes. I am awaiting some reworked tests to test #9980. After that, I'll switch to using Right now that routine has to be changed for each piece of functionality that uses DMA0 irq's. I haven't looked at this issue in any detail. Is there a simple addition to the fixed routine now that you can add? |
Since the pending interrupts didn't appear in |
From the "I can't fix it, but I can bypass it with one of these" department: The void __not_in_flash_func(isr_dma_0)(void) {
for (size_t i = 0; i < NUM_DMA_CHANNELS; i++) {
uint32_t mask = 1 << i;
if ((dma_hw->ints0 & mask) == 0) {
continue;
}
// Clear any forced interrupts for this channel.
if ((dma_hw->intf0 & mask) != 0) {
dma_hw->intf0 &= ~mask;
}
// acknowledge interrupt early. Doing so late means that you could lose an
// interrupt if the buffer is very small and the DMA operation
// completed by the time callback_add() / dma_complete() returned. This
// affected PIO continuous write more than audio.
dma_hw->ints0 = mask;
if (MP_STATE_PORT(playing_audio)[i] != NULL) {
audio_dma_t *dma = MP_STATE_PORT(playing_audio)[i];
// Record all channels whose DMA has completed; they need loading.
dma->channels_to_load_mask |= mask;
background_callback_add(&dma->callback, dma_callback_fun, (void *)dma);
}
if (MP_STATE_PORT(background_pio)[i] != NULL) {
rp2pio_statemachine_obj_t *pio = MP_STATE_PORT(background_pio)[i];
rp2pio_statemachine_dma_complete_write(pio, i);
}
}
} |
|
Maybe related? I added code in #9680 to acknowledge a previous pending interrupt in state machine background write befor setting the interrupt enabled flag.. I never determined why the IRQ flag was pending, and it wasn't clear whether I was hiding a deeper problem. |
Yes, this fixed it, thanks! I built a new version and tested with the real application as well. |
@bablokb Good to know. The root cause is missing code to handle the case where the MP3 decoder fails to synchronize with the first buffer of the stream. This leads to a cascade of errors that eventually hangs in an interrupt loop. To actually fix the bug I'm detecting the error and throwing an "Audio source error" from the player when it occurs. Your code will need to catch and retry for this case. I'll be submitting a PR shortly. |
CircuitPython version
Code/REPL
Behavior
Description
The program automatically cycles through a number of web-streams from internet radio (in the real application the user presses buttons to switch stations). After a few URLs, the Pico2W just disconnects and needs a hard reset for a restart. Behavior is random, sometime it fails after three streams, sometimes later. Switching streams seems to be the problem, playing a single stream for an extended time works without problems for all of the example URLs.
Note that you don't need real I2S hardware to reproduce the error. Also, the program works fine on an ESP32-S3.
Some speculations: maybe the network-stack of the Pico2W does not cleanup resources and fails after a while. Or it produces illegal data during close and this trips the MP3Decoder.
Additional information
No response
The text was updated successfully, but these errors were encountered: