Audio Analysis on Zephyr
Real-time audio analysis on the Nucleo G474RE using Zephyr RTOS, CMSIS-DSP, and hardware-triggered ADC sampling at 44.1 kHz.
Technologies Used
Motivation
I built this project to learn Zephyr RTOS by doing something more involved than blinking an LED. I've used FreeRTOS before and wanted to understand how Zephyr handles devicetree, Kconfig, and the kernel primitives. This project ended up touching all of those plus direct STM32 LL/HAL register work, which was a good way to see where Zephyr's abstractions end and the hardware begins.
Hardware
| Board | ST Nucleo G474RE |
| MCU | STM32G474RE (Cortex-M4F, 170 MHz, FPU) |
| Audio Input | Analog signal on PA0 (Arduino A0) |
| Console | LPUART1 via onboard ST-Link VCP |
| ADC Trigger | TIM6 TRGO at 44,098.6 Hz |
How It Works
TIM6 overflows at ~44.1 kHz and triggers an ADC1 conversion via hardware TRGO. DMA transfers each sample into a ping-pong buffer (2 × 1024 samples). On half-transfer and transfer-complete interrupts, a semaphore wakes the processing thread, which runs a 1024-point real FFT using CMSIS-DSP and sends the results over UART.
TIM6 (44.1 kHz) → ADC1 conversion → DMA → ping-pong buffer
|
DMA half/full IRQ
|
proc_thread wakes
|
FFT + RMS + peak detect
|
UART outputThe Cortex-M4F at 170 MHz handles a 1024-point float FFT in well under a millisecond. Thread analyzer shows 98% idle time - the CPU barely breaks a sweat.
What I Learned
Devicetree and Kconfig - Devicetree describes what hardware exists. Kconfig enables software features. They answer different questions and you need both.
Where Zephyr stops and HAL starts - Zephyr's ADC API doesn't expose hardware timer triggering. For the TIM6 → ADC1 trigger routing and DMA setup, I had to use STM32 LL functions directly.
DMA ping-pong buffering - One contiguous buffer, DMA in circular mode, half-transfer and transfer-complete interrupts. While one half fills, the CPU processes the other. No memcpy, just pointer swapping.
What's Next
This project is still in active development. More updates to come.
Source Code
The full source is available on my Gitea instance:
git.pjanik.ca/philip/audio-analysis