From 8305adf917b4659e06a8baf29065ef0162be0d14 Mon Sep 17 00:00:00 2001 From: Eduard Iten Date: Sun, 15 Feb 2026 20:40:06 +0100 Subject: [PATCH] Improved audio lib error handling and aborting playback --- firmware/apps/_samples/audio/src/main.c | 15 +++++++++++---- firmware/libs/audio/Kconfig | 2 +- firmware/libs/audio/src/audio.c | 17 ++++++++++++++--- 3 files changed, 26 insertions(+), 8 deletions(-) diff --git a/firmware/apps/_samples/audio/src/main.c b/firmware/apps/_samples/audio/src/main.c index 23eec65..3a9588a 100644 --- a/firmware/apps/_samples/audio/src/main.c +++ b/firmware/apps/_samples/audio/src/main.c @@ -2,6 +2,7 @@ #include #include #include +#include LOG_MODULE_REGISTER(MMS, LOG_LEVEL_INF); @@ -27,10 +28,16 @@ int main(void) LOG_INF("Triggering first sound..."); audio_play_sound("s1"); - audio_play_sound("dead"); - audio_play_sound("g1"); + k_sleep(K_MSEC(100)); + audio_stop(); + LOG_INF("Triggering second sound after abort..."); + audio_play_sound("s1"); + + k_sleep(K_MSEC(100)); + // Directly stop the I2S peripheral to simulate an abrupt stop that might occur with a DMA failure or similar issue. This will cause the next playback attempt to hit the slab timeout and trigger the I2S reset logic in the audio thread. + NRF_I2S0->TASKS_STOP = 1; + NRF_I2S0->ENABLE = 0; + LOG_INF("Triggering third sound after failure simulation..."); audio_play_sound("s1"); - audio_play_sound("dead"); - audio_play_sound("g1"); return 0; } diff --git a/firmware/libs/audio/Kconfig b/firmware/libs/audio/Kconfig index 512c4b8..d4c7f1a 100644 --- a/firmware/libs/audio/Kconfig +++ b/firmware/libs/audio/Kconfig @@ -38,7 +38,7 @@ if AUDIO config AUDIO_BLOCK_SIZE int "Audio Block Size (bytes)" default 1024 - range 256 4096 + range 256 8192 help Set the size of each audio block in bytes. Larger blocks can reduce CPU overhead but increase latency. Default is 1024 bytes. diff --git a/firmware/libs/audio/src/audio.c b/firmware/libs/audio/src/audio.c index 15afb67..eea45cd 100644 --- a/firmware/libs/audio/src/audio.c +++ b/firmware/libs/audio/src/audio.c @@ -56,7 +56,6 @@ void audio_thread_fn(void *p1, void *p2, void *p3) bool trigger_started = false; if (k_msgq_get(&audio_msgq, &file_path, K_FOREVER) == 0) { - abort_playback = false; if (fs_open(&file, file_path, FS_O_READ) < 0) @@ -72,8 +71,19 @@ void audio_thread_fn(void *p1, void *p2, void *p3) while (!abort_playback) { void *mem_block; - if (k_mem_slab_alloc(&audio_slab, &mem_block, K_MSEC(10)) < 0) - continue; + if (k_mem_slab_alloc(&audio_slab, &mem_block, K_MSEC(100)) < 0) + { + LOG_ERR("audio: slab timeout (I2S stall? DMA failure?) - skipping sound and resetting I2S..."); + i2s_trigger(i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP); + audio_init(); + break; + } + if (abort_playback) + { + LOG_DBG("thread: playback aborted while waiting for memory block."); + k_mem_slab_free(&audio_slab, mem_block); + break; + } int16_t *data_ptr = (int16_t *)mem_block; const uint32_t max_mono_samples = CONFIG_AUDIO_BLOCK_SIZE / 4; @@ -240,5 +250,6 @@ void audio_stop(void) { abort_playback = true; k_msgq_purge(&audio_msgq); + i2s_trigger(i2s_dev, I2S_DIR_TX, I2S_TRIGGER_DROP); LOG_DBG("Playback stop requested, message queue purged"); } \ No newline at end of file