From 9e69217ce5a14be06864f3ba208f21f4c82a6535 Mon Sep 17 00:00:00 2001 From: Claude Date: Sun, 11 Oct 2026 09:03:49 +0000 Subject: [PATCH] Configure audio on STM32F746G-DISCO: dmsai and dmwm8994 Load the WM8994 codec stack on the board: dmsai (SAI2 stream) and dmwm8994 with codec-with-touch.ini. That config joins the touch panel's I2C3 bus node instead of configuring I2C3 a second time, so touch and audio work at once. The nodes are /dev/wm8994 (codec controls and stereo PCM) and /dev/dmsai1 (the SAI stream the codec drives). Emulation: DMBOOT_RENODE_AUDIO_CAPTURE= loads the audio models of configs/renode/STM32F7_Audio.cs (SAI2, the WM8994 on I2C3 and a DMA2 with circular mode and half-transfer interrupts) and writes what the codec plays to the file as raw stereo s16le. DMA2 is replaced before the SD card setup, which connects to it by name. Without the option nothing changes in the Renode machine. Needs dmwm8994 with codec-with-touch.ini and dmsai/dmwm8994 releases that implement the dmdrvi 2.7 audio stream commands. Co-Authored-By: Claude Sonnet 5.5 Claude-Session: https://claude.ai/code/session_01Nr1HhezRY951yBxxTm1b65 --- configs/board/stm32f746g-disco/board.cmake | 13 +++++++++++++ configs/board/stm32f746g-disco/flash.dmd | 11 +++++++++++ configs/renode/STM32F7_Audio.cs | 11 +++++++---- configs/renode/renode.resc.in | 2 ++ docs/cmake-options.md | 1 + scripts/targets.cmake | 15 +++++++++++++++ 6 files changed, 49 insertions(+), 4 deletions(-) diff --git a/configs/board/stm32f746g-disco/board.cmake b/configs/board/stm32f746g-disco/board.cmake index d11be58..2997e61 100644 --- a/configs/board/stm32f746g-disco/board.cmake +++ b/configs/board/stm32f746g-disco/board.cmake @@ -30,3 +30,16 @@ set(DMBOOT_RENODE_SDCARD_DETECT_PIN 13) # emulation mode can write the frames it renders to a file (see # DMBOOT_RENODE_LCD_CAPTURE) set(DMBOOT_RENODE_LCD "sysbus.ltdc" CACHE STRING "Renode peripheral of the LCD controller") + +# Audio (WM8994 codec on I2C3 address 0x1A, fed by SAI2): Renode has neither +# peripheral, and its DMA2 has no circular mode or half-transfer interrupt, +# which the SAI stream needs - configs/renode/STM32F7_Audio.cs supplies all +# three. Emulation mode loads them when DMBOOT_RENODE_AUDIO_CAPTURE is set +# (see there); DMA2 is replaced by a model that moves peripheral-to-memory +# data like Renode's own, so the SD host still works. stands for the +# file the codec writes what it plays to. +set(DMBOOT_RENODE_AUDIO_MODEL "${CMAKE_SOURCE_DIR}/configs/renode/STM32F7_Audio.cs") +set(DMBOOT_RENODE_AUDIO_DMA "sysbus.dma2") +set(DMBOOT_RENODE_AUDIO_DMA_DESCRIPTION "dma2: DMA.STM32F7_AudioDMA @ sysbus 0x40026400 { [0-7] -> nvic@[56-60,68-70] }") +set(DMBOOT_RENODE_AUDIO_CODEC_DESCRIPTION "wm8994: Sound.WM8994 @ i2c3 0x1A { outputFile: \\\"\\\" }") +set(DMBOOT_RENODE_AUDIO_SAI_DESCRIPTION "sai2: Sound.STM32F7_SAI @ sysbus 0x40015C00 { codec: wm8994; DmaRequestA -> dma2@4; DmaRequestB -> dma2@6 }") diff --git a/configs/board/stm32f746g-disco/flash.dmd b/configs/board/stm32f746g-disco/flash.dmd index 8c664d8..7e336ad 100644 --- a/configs/board/stm32f746g-disco/flash.dmd +++ b/configs/board/stm32f746g-disco/flash.dmd @@ -63,3 +63,14 @@ dmlcdtft driver=board/stm32f746g-disco/lcd.ini # dmi2c dmft5336 driver=board/stm32f746g-disco/touch.ini +# +# Audio: the WM8994 codec - stereo headphone output and the board's digital +# microphone - on SAI2 (PCM, dmsai) with I2C3 for its registers. The config +# joins the touch panel's I2C3 bus node (touch.ini above) instead of +# configuring I2C3 again, so both work at once. The nodes are /dev/wm8994 +# (codec controls and stereo PCM) and /dev/dmsai1 (the raw SAI stream the codec +# drives); an application plays through /dev/wm8994 with the DMDRVI_IOCTL_AUDIO_* +# commands (dmdrvi 2.7). dmsai needs dmclk (SAI clock), dmdma (DMA2) and dmheap. +# +dmsai +dmwm8994 driver=board/stm32f746g-disco/codec-with-touch.ini diff --git a/configs/renode/STM32F7_Audio.cs b/configs/renode/STM32F7_Audio.cs index 213df18..5c487c6 100644 --- a/configs/renode/STM32F7_Audio.cs +++ b/configs/renode/STM32F7_Audio.cs @@ -21,9 +21,9 @@ // LRCLK/BCLK inversion) and writes the DAC1 samples it receives to OutputFile // as raw stereo s16le (silence while DAC1 is muted). // -// Not wired into renode.resc yet. To use it, add to the script before -// LoadELF (the codec node also needs dmsai/dmwm8994 in the firmware and the -// FT5336 touch config left out, since both own I2C3): +// Loaded by renode.resc when DMBOOT_RENODE_AUDIO_CAPTURE names a file (the +// board's board.cmake names the peripherals, scripts/targets.cmake writes the +// script lines): // // include @configs/renode/STM32F7_Audio.cs // sysbus Unregister sysbus.dma2 @@ -31,7 +31,10 @@ // machine LoadPlatformDescriptionFromString "wm8994: Sound.WM8994 @ i2c3 0x1A { outputFile: \"/tmp/codec.pcm\" }" // machine LoadPlatformDescriptionFromString "sai2: Sound.STM32F7_SAI @ sysbus 0x40015C00 { codec: wm8994; DmaRequestA -> dma2@4; DmaRequestB -> dma2@6 }" // -// and convert the capture with e.g. "sox -t raw -r 48000 -e signed -b 16 -c 2 /tmp/codec.pcm out.wav". +// DMA2 has to be replaced before anything that connects to it by name (the SD +// host). The codec shares I2C3 with the touch panel, as on the board +// (flash.dmd). Convert the capture with e.g. +// "sox -t raw -r 48000 -e signed -b 16 -c 2 /tmp/codec.pcm out.wav". // using System; using System.Collections.Generic; diff --git a/configs/renode/renode.resc.in b/configs/renode/renode.resc.in index 3c2492a..959696a 100644 --- a/configs/renode/renode.resc.in +++ b/configs/renode/renode.resc.in @@ -6,6 +6,8 @@ sysbus LoadELF @@CMAKE_BINARY_DIR@/renode_firmware.elf machine StartGdbServer 3333 +@DMBOOT_RENODE_AUDIO_SETUP@ + @DMBOOT_RENODE_SDCARD_SETUP@ @DMBOOT_RENODE_LCD_SETUP@ diff --git a/docs/cmake-options.md b/docs/cmake-options.md index 8dc02f3..89f1c58 100644 --- a/docs/cmake-options.md +++ b/docs/cmake-options.md @@ -29,6 +29,7 @@ These options are defined in the top-level `CMakeLists.txt` and control the over | `DMBOOT_RENODE_TAP` | STRING | *(empty)* | In emulation mode, host TAP interface (e.g. `tap0`) that the board's Ethernet controller (`DMBOOT_RENODE_ETHERNET`, set by the board config, e.g. `sysbus.ethernet` for `stm32f746g-disco`) is connected to through a Renode switch, so the host can reach the board over IP. Needs root and `/dev/net/tun`; empty leaves the Ethernet unconnected. | | `DMBOOT_RENODE_SDCARD` | FILEPATH | *(empty)* | In emulation mode, SD card image (e.g. one built by `scripts/make_sdcard_image.py`) inserted in the board's card slot (`DMBOOT_RENODE_SDMMC`, set by the board config, e.g. `sysbus.sdmmc` for `stm32f746g-disco`). The board's SD host is replaced with its own model (`configs/renode/STM32F7_SDMMC.cs`, compiled by Renode when it loads the script) and the card detect pin is driven low. Writes to the card are discarded when Renode exits; empty leaves the slot empty. | | `DMBOOT_RENODE_LCD_CAPTURE` | FILEPATH | *(empty)* | In emulation mode, file every frame the board's LCD controller (`DMBOOT_RENODE_LCD`, set by the board config, e.g. `sysbus.ltdc` for `stm32f746g-disco`) renders is written to whenever it changes: a header line `DMLCD ` followed by the raw pixels (see `configs/renode/lcd_capture.py.in`). Empty: frames are not captured. | +| `DMBOOT_RENODE_AUDIO_CAPTURE` | FILEPATH | *(empty)* | In emulation mode, file the board's audio codec (`stm32f746g-disco`: WM8994 on I2C3, fed by SAI2) writes what it plays to, as raw stereo 16-bit little-endian samples at the codec's rate (48 kHz). Setting it loads `configs/renode/STM32F7_Audio.cs`, which adds the SAI and the codec and replaces DMA2 with a model that has circular mode and half-transfer interrupts (Renode's has neither; the SD host keeps working). Needs the audio modules from `flash.dmd`. Empty: the audio peripherals are not modelled and the codec does not respond. | ## VFS Options diff --git a/scripts/targets.cmake b/scripts/targets.cmake index b6a2e47..4c64868 100644 --- a/scripts/targets.cmake +++ b/scripts/targets.cmake @@ -51,6 +51,21 @@ if(DMBOOT_RENODE_ETHERNET AND DMBOOT_RENODE_TAP) else() set(DMBOOT_RENODE_NETWORK "") endif() +# Play audio through the board's codec (if it names the models): the DMA2 +# controller is replaced with one that has circular mode and half-transfer +# interrupts, and the SAI and the WM8994 codec are added (see +# DMBOOT_RENODE_AUDIO_MODEL, a C# model Renode compiles when it loads the +# script). What the codec plays is written to a file as raw stereo 16-bit +# little-endian samples. The SD card setup below connects to DMA2 by name, so +# DMA2 has to be replaced first. +set(DMBOOT_RENODE_AUDIO_CAPTURE "" CACHE FILEPATH "File the board's audio codec writes what it plays to in emulation mode (raw stereo s16le); empty: the audio models are not loaded") +if(DMBOOT_RENODE_AUDIO_MODEL AND DMBOOT_RENODE_AUDIO_CAPTURE) + string(REPLACE "" "${DMBOOT_RENODE_AUDIO_CAPTURE}" _AUDIO_CODEC "${DMBOOT_RENODE_AUDIO_CODEC_DESCRIPTION}") + set(DMBOOT_RENODE_AUDIO_SETUP + "include @${DMBOOT_RENODE_AUDIO_MODEL}\nsysbus Unregister ${DMBOOT_RENODE_AUDIO_DMA}\nmachine LoadPlatformDescriptionFromString \"${DMBOOT_RENODE_AUDIO_DMA_DESCRIPTION}\"\nmachine LoadPlatformDescriptionFromString \"${_AUDIO_CODEC}\"\nmachine LoadPlatformDescriptionFromString \"${DMBOOT_RENODE_AUDIO_SAI_DESCRIPTION}\"") +else() + set(DMBOOT_RENODE_AUDIO_SETUP "") +endif() # Insert an SD card image in the board's card slot (if it names one): the # board's SD host is replaced with its model (DMBOOT_RENODE_SDMMC_MODEL, C# # Renode compiles when it loads the script), the image attached to it and the