rp2040: Avoid screeches due to audio underflow during flash writes

By pausing audio during flash writes, the worst screeching of #8121
is avoided. I don't consider this a full fix, but it greatly improves
the by far most common scenario in which the problem occurs.

Tested on rp2040 prop feather with a midi synth playing arpeggios. When
writing to the flash e.g., with
```
dd bs=512 count=32 if=/dev/zero of=/media/jepler/CIRCUITPY/boop
```
the audio goes "tap tap tap tap" during the flash write instead of the
squawking.

This isn't a 100% fix; it will still glitch out, including during USB
enumeration which must be taking a long time without servicing background
tasks. Add a delay if not usb-connected at startup ameliorates this
greatly.
This commit is contained in:
Jeff Epler 2023-06-26 10:33:41 -05:00
parent 7e6825daf6
commit b4be2317cb
No known key found for this signature in database
GPG Key ID: D5BF15AB975AB4DE
3 changed files with 28 additions and 0 deletions

View File

@ -388,6 +388,27 @@ bool audio_dma_get_paused(audio_dma_t *dma) {
return (control & DMA_CH0_CTRL_TRIG_EN_BITS) == 0;
}
uint32_t audio_dma_pause_all(void) {
uint32_t result = 0;
for (size_t channel = 0; channel < NUM_DMA_CHANNELS; channel++) {
audio_dma_t *dma = MP_STATE_PORT(playing_audio)[channel];
if (dma != NULL && !audio_dma_get_paused(dma)) {
audio_dma_pause(dma);
result |= (1 << channel);
}
}
return result;
}
void audio_dma_unpause_cookie(uint32_t cookie) {
for (size_t channel = 0; channel < NUM_DMA_CHANNELS; channel++) {
audio_dma_t *dma = MP_STATE_PORT(playing_audio)[channel];
if (dma != NULL && (cookie & (1 << channel))) {
audio_dma_resume(dma);
}
}
}
void audio_dma_init(audio_dma_t *dma) {
dma->buffer[0] = NULL;
dma->buffer[1] = NULL;

View File

@ -89,4 +89,7 @@ void audio_dma_pause(audio_dma_t *dma);
void audio_dma_resume(audio_dma_t *dma);
bool audio_dma_get_paused(audio_dma_t *dma);
uint32_t audio_dma_pause_all(void);
void audio_dma_unpause_cookie(uint32_t cookie);
#endif // MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H

View File

@ -39,6 +39,7 @@
#include "lib/oofatfs/ff.h"
#include "shared-bindings/microcontroller/__init__.h"
#include "audio_dma.h"
#include "supervisor/flash.h"
#include "supervisor/usb.h"
@ -97,9 +98,12 @@ void port_internal_flash_flush(void) {
}
// Make sure we don't have an interrupt while we do flash operations.
common_hal_mcu_disable_interrupts();
// and audio DMA must be paused as well
uint32_t cookie = audio_dma_pause_all();
flash_range_erase(CIRCUITPY_CIRCUITPY_DRIVE_START_ADDR + _cache_lba, SECTOR_SIZE);
flash_range_program(CIRCUITPY_CIRCUITPY_DRIVE_START_ADDR + _cache_lba, _cache, SECTOR_SIZE);
_cache_lba = NO_CACHE;
audio_dma_unpause_cookie(cookie);
common_hal_mcu_enable_interrupts();
}