Skip to content

Commit 5dc2b16

Browse files
authored
Merge pull request #8123 from jepler/issue8121-workaround
rp2040: Avoid screeches due to audio underflow during flash writes
2 parents 324ecc2 + 3853661 commit 5dc2b16

File tree

3 files changed

+28
-0
lines changed

3 files changed

+28
-0
lines changed

ports/raspberrypi/audio_dma.c

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -388,6 +388,27 @@ bool audio_dma_get_paused(audio_dma_t *dma) {
388388
return (control & DMA_CH0_CTRL_TRIG_EN_BITS) == 0;
389389
}
390390

391+
uint32_t audio_dma_pause_all(void) {
392+
uint32_t result = 0;
393+
for (size_t channel = 0; channel < NUM_DMA_CHANNELS; channel++) {
394+
audio_dma_t *dma = MP_STATE_PORT(playing_audio)[channel];
395+
if (dma != NULL && !audio_dma_get_paused(dma)) {
396+
audio_dma_pause(dma);
397+
result |= (1 << channel);
398+
}
399+
}
400+
return result;
401+
}
402+
403+
void audio_dma_unpause_mask(uint32_t channel_mask) {
404+
for (size_t channel = 0; channel < NUM_DMA_CHANNELS; channel++) {
405+
audio_dma_t *dma = MP_STATE_PORT(playing_audio)[channel];
406+
if (dma != NULL && (channel_mask & (1 << channel))) {
407+
audio_dma_resume(dma);
408+
}
409+
}
410+
}
411+
391412
void audio_dma_init(audio_dma_t *dma) {
392413
dma->buffer[0] = NULL;
393414
dma->buffer[1] = NULL;

ports/raspberrypi/audio_dma.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,4 +89,7 @@ void audio_dma_pause(audio_dma_t *dma);
8989
void audio_dma_resume(audio_dma_t *dma);
9090
bool audio_dma_get_paused(audio_dma_t *dma);
9191

92+
uint32_t audio_dma_pause_all(void);
93+
void audio_dma_unpause_mask(uint32_t channel_mask);
94+
9295
#endif // MICROPY_INCLUDED_RASPBERRYPI_AUDIO_DMA_OUT_H

ports/raspberrypi/supervisor/internal_flash.c

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
#include "lib/oofatfs/ff.h"
4040
#include "shared-bindings/microcontroller/__init__.h"
4141

42+
#include "audio_dma.h"
4243
#include "supervisor/flash.h"
4344
#include "supervisor/usb.h"
4445

@@ -97,9 +98,12 @@ void port_internal_flash_flush(void) {
9798
}
9899
// Make sure we don't have an interrupt while we do flash operations.
99100
common_hal_mcu_disable_interrupts();
101+
// and audio DMA must be paused as well
102+
uint32_t channel_mask = audio_dma_pause_all();
100103
flash_range_erase(CIRCUITPY_CIRCUITPY_DRIVE_START_ADDR + _cache_lba, SECTOR_SIZE);
101104
flash_range_program(CIRCUITPY_CIRCUITPY_DRIVE_START_ADDR + _cache_lba, _cache, SECTOR_SIZE);
102105
_cache_lba = NO_CACHE;
106+
audio_dma_unpause_mask(channel_mask);
103107
common_hal_mcu_enable_interrupts();
104108
}
105109

0 commit comments

Comments
 (0)