Files
CelloEffects/AGENTS.md
T
thomasandClaude Sonnet 5.5 66bb319423 CubeMX: SPI4 + SDMMC1/FatFs + I2S6, audio BSP et debug VS Code (Linux)
Regeneration CubeMX (Appli) preparant le driver ST67W611M1 et la carte SD :
- SPI4 (PE12/13/14, CS PF8) + DMA GPDMA1 canaux 4/5, SPI_RDY (PD12/EXTI12),
  CHIP_EN (PD13) et BOOT (PD15) pour la X-NUCLEO-67W61M1 sur l'Arduino
- SDMMC1 + FatFs (appels d'init non generes dans main, IRQ SDMMC1 prio 14),
  PM14 en open-drain ; I2S6_CK sur PA5 pour liberer PC12 (SDMMC1_CK)
- HAL UART retire ; USE_BSP_COM_FEATURE=0
- Audio preserve : ADF 4/16/24, prio IRQ 2, DMA canal 0 en priorite haute,
  GPDMA1_Channel2_IRQHandler deplace dans audio_irq.c (hors fichiers generes),
  BSP_MX_I2S6_Init (renommage dans le BSP pour eviter le conflit avec CubeMX)
- Middlewares/ST/ST67W6X_Network_Driver, FatFs et sources HAL SPI/SD ajoutes
  (driver ST67 pas encore integre au build)

Build et debug sous Linux :
- gcc/toolchain-env.sh, gdbserver.sh, arm-gdb.sh : outils de STM32CubeIDE par
  glob ; flash.sh les retrouve ; ruby_compat.rb pour Ruby >= 3.2 (TouchGFX)
- makefile_appli : sources SD/SPI/FatFs/audio_irq ; chmod +x des .out TouchGFX
- Objets de build (*.o, *.d, *.su) retires de l'index (deja dans .gitignore)
- AGENTS.md : toolchain Linux, configs VS Code (cppdbg et ST stlinkgdbtarget),
  pieges de l'extension ST (.settings/ide.store.json, preRunCommands reset)

Verifie sur carte : audio OK, debug Appli/Boot OK.

Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>
2026-10-23 22:49:06 +02:00

15 KiB

AGENTS.md

Hardware

  • Board: STM32H7S78-DK evaluation board
  • MCU: STM32H7S78 (Cortex-M7 @ 480MHz)
  • Flash: 64 KB internal flash at 0x08000000 (Boot) + 128 MB external OctoSPI NOR flash at 0x70000000 (Appli code + TouchGFX assets)
  • RAM: 1 MB internal + external PSRAM (for Audio/Framebuffers)

Project Architecture

Dual-Boot Structure

This project uses a dual-project architecture:

Project Directory Purpose
Boot /Boot/ Bootloader - initializes hardware, loads application from external flash
Appli /Appli/ Main application - TouchGFX UI + audio processing

Flashing order: Boot must be flashed first (without loader), then Appli (with external loader). After flashing Appli, press NRST button to start.

Note: The Appli uses external memory (0x70000000) for TouchGFX assets and requires the external FlashLoader MX66UW1G45G_STM32H7S78-DK.stldr to program the external flash.

Project Setup

  • IDE: STM32CubeIDE with STM32CubeMX plugin
  • RTOS: FreeRTOS V10.5.1 (CMSIS-RTOS V2)
  • GUI: TouchGFX 4.26.1 with NemaGFX GPU acceleration
  • Language: C/C++
  • Build System: GCC Makefile (not CMake)

Key Constraints

  1. Dual-boot flashing sequence: Flash Boot first, then Appli (gcc/flash.sh all does both and hard-resets the board).
  2. External FlashLoader required: Use gcc/MX66UW1G45G_STM32H7S78-DK.stldr for programming external flash (0x70000000)
  3. Never edit Core/Src/ and Core/Inc/ directly - regenerate via STM32CubeMX instead
  4. High-speed audio acquisition (48kHz) - uses DMA for ADF1 (microphone) and audio codec
  5. External memory usage: Audio buffers (>900KB) stored in external PSRAM (section AudioLooperBuffer)
  6. TouchGFX architecture: Two-stage debug - debug Boot first, then Appli
  7. FreeRTOS heap size: Configured to 50KB in FreeRTOSConfig.h (heap_4)
  8. Interrupt priorities: Audio interrupts at priority 2 (high priority), touch/SD at 14-15
  9. Debug probe connection: always ap=1 mode=UR (STM32_Programmer_CLI) / -m 1 -k (ST-LINK_gdbserver). Without them the connection fails (DEV_TARGET_NOT_HALTED, Cannot connect to access port 1)
  10. No OpenOCD: the installed OpenOCD 0.12 has no STM32H7RS target; debug with ST-LINK_gdbserver (Cortex-Debug in VS Code)

Build & Flash

Toolchain (macOS, verified)

Tool Path
arm-none-eabi-gcc / -gdb 10.3 /usr/local/bin (in PATH)
STM32_Programmer_CLI /Applications/STMicroelectronics/programmer/STM32CubeProgrammer.app/Contents/MacOs/bin/STM32_Programmer_CLI (not in PATH; gcc/flash.sh finds it, override with $STM32_PROGRAMMER_CLI)
ST-LINK_gdbserver /Applications/STMicroelectronics/STM32CubeIDE.app/Contents/Eclipse/plugins/com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.macos64_*/tools/bin/ST-LINK_gdbserver
SVD /Applications/STMicroelectronics/programmer/STM32CubeProgrammer.app/Contents/MacOs/SVD/STM32H7S.svd
Probe on-board STLINK-V3 (USB)

TouchGFX 4.26.1 + STM32CubeMX are only needed to regenerate code.

On Linux, arm-none-eabi-gcc comes from STM32CubeIDE (~/st/stm32cubeide_*/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.*/tools/bin, GCC 14.3); ~/.bashrc adds it to PATH. The build also needs ruby (TouchGFX text/video conversion) and the executable bit on Appli/Middlewares/ST/touchgfx/framework/tools/{imageconvert,fontconvert}/build/linux/*.out. Build outputs (*.o, *.d, *.su in */TouchGFX/build and STM32CubeIDE/*/Debug) are git-ignored and untracked.

Build Commands

Run from the repository root (the makefiles cd to the root themselves):

make -C gcc -j8                          # Build Boot + Appli
make -C gcc -j8 -f makefile_boot all     # Boot only
make -C gcc -j8 -f makefile_appli all    # Appli only
make -C gcc clean                        # Clean
python3 gcc/gen_compile_commands.py      # Regenerate compile_commands.json (IntelliSense/clangd) after adding sources

Outputs:

  • Boot: Boot/TouchGFX/build/bin/target.elf|.hex (internal flash 0x08000000)
  • Appli: Appli/TouchGFX/build/bin/target.elf|.hex (external flash 0x70000000)

The "old Ruby version (2.6.10)" TouchGFX warning during the build is harmless.

Flashing Commands

Use gcc/flash.sh (wraps STM32_Programmer_CLI with ap=1 mode=UR and the external loader):

gcc/flash.sh boot     # Boot  -> internal flash (with verify)
gcc/flash.sh appli    # Appli -> external flash via gcc/MX66UW1G45G_STM32H7S78-DK.stldr (~20 s)
gcc/flash.sh all      # Boot then Appli (required order), then hard reset
gcc/flash.sh probe    # Check the ST-Link/board connection (no write)
gcc/flash.sh reset    # Hardware reset
gcc/flash.sh verify   # Dump 4 KB of 0x08000000 / 0x70000000 to /tmp/read_int.bin, /tmp/read_ext.bin
make -C gcc flash     # Build + flash both (calls gcc/flash.sh on macOS/Linux)

Equivalent raw commands:

STM32_Programmer_CLI -c port=SWD ap=1 mode=UR -d Boot/TouchGFX/build/bin/target.hex -v -hardRst
STM32_Programmer_CLI -c port=SWD ap=1 mode=UR -el gcc/MX66UW1G45G_STM32H7S78-DK.stldr \
  -d Appli/TouchGFX/build/bin/target.hex -hardRst

Only one tool can hold the ST-Link at a time: stop any debug session before flashing.

VS Code (.vscode/, git-ignored)

Linux setup (uses the ms-vscode.cpptools extension, no Cortex-Debug needed; tools come from STM32CubeIDE in ~/st):

  • gcc/toolchain-env.sh: sourced by the helpers below; adds arm-none-eabi-gcc/gdb to PATH and exports ST_GDBSERVER / ST_PROGRAMMER_BIN (globs, so CubeIDE updates do not break it).
  • gcc/gdbserver.sh <boot|appli>: starts ST-LINK_gdbserver -p 61234 --swd --halt -m 1 -k -cp <programmer> (+ -el external loader for appli). Kills a stale server first.
  • gcc/arm-gdb.sh: wrapper around arm-none-eabi-gdb (VS Code miDebuggerPath cannot glob).
  • tasks.json: Build All (default, Ctrl+Shift+B) / Boot / Appli, Clean, Flash Boot/Appli/All, Build + Flash All, Board: Probe/Reset/Verify, gdbserver: Boot|Appli (background), Debug prep: ... (build + gdbserver, used as preLaunchTask), Kill gdbserver, Generate compile_commands.json.
  • launch.json (cppdbg, miDebuggerServerAddress: localhost:61234): Debug Boot (build, load, monitor reset, hw break on main), Debug Appli (build, load via the external loader, reset, stops at Appli main()), Debug Appli (no flash) (reset only).
  • launch.json also has three stlinkgdbtarget configs (they need deviceName: STM32H7S7L8H6H = CMSIS pack variant / Mcu.CPN, and deviceCore: Cortex-M7; the ST extension cannot infer them for this Makefile project) (ST Debug Boot / Appli / Appli (no flash)) for the STMicroelectronics VS Code extensions (stm32cube-ide-debug-stlink-gdbserver, -registers, -rtos): they start their own ST-LINK server from ~/.local/share/stm32cube/bundles (no gdbserver: task needed), and give the peripheral Registers view (SVD ~/STMicroelectronics/STM32Cube/STM32CubeProgrammer/SVD/STM32H7S.svd), the FreeRTOS threads view (serverRtos, ARM_CM7) and Live Watch. Validated headless (DAP driven by script: server, RTOS proxy, GDB client and Live Watch all start; flash load not exercised). Required, git-ignored file .settings/ide.store.json at the repo root: {"device": "STM32H7S7L8H6H", "core": "Cortex-M7", "tz": "TZ-disabled"}. The extension looks for it by walking up from the ELF directory; without it the ST-LINK server step is silently skipped and launch fails with "No GDB Server running" ("project settings not found" in the log). The ST configs need "preRunCommands": ["monitor reset"]: after load the extension starts at the ELF Reset_Handler, but external flash is only memory-mapped once Boot has run, so without the reset Appli faults on its first instruction (SIGTRAP in Boot's handler, black screen). Other notes: the extension's CMSIS pack root ~/.local/share/stm32cube/packs should contain STMicroelectronics/stm32h7xx_dfp/1.3.0; the ST Debug Appli (no flash) variant only has a symbol file, so it sets program (the RTOS proxy needs the ELF; without it the proxy dies and GDB times out).
  • settings.json / extensions.json: IntelliSense from compile_commands.json.

macOS keeps the Cortex-Debug (servertype: stlink) setup described under "Debugging". pkill -x ST-LINK_gdbserver does NOT work (process name truncated to 15 chars): use pkill -f '[S]T-LINK_gdbserver'.

Keep AGENTS.md, .vscode/tasks.json, .vscode/launch.json and gcc/flash.sh consistent when changing any build/flash/debug command.

Debugging

Boot must already be in internal flash (gcc/flash.sh boot): at reset the core runs Boot, which maps the XSPI memories and jumps to Appli main() at 0x70000000.

VS Code: run "Debug Appli" (F5). No NRST press needed.

Command line:

GDBSRV=$(ls -d /Applications/STMicroelectronics/STM32CubeIDE.app/Contents/Eclipse/plugins/com.st.stm32cube.ide.mcu.externaltools.stlink-gdb-server.macos64_*/tools/bin | tail -1)/ST-LINK_gdbserver
"$GDBSRV" -p 61234 --swd --halt -m 1 -k \
  -cp /Applications/STMicroelectronics/programmer/STM32CubeProgrammer.app/Contents/MacOs/bin \
  -el gcc/MX66UW1G45G_STM32H7S78-DK.stldr

# In another terminal
arm-none-eabi-gdb Appli/TouchGFX/build/bin/target.elf
(gdb) target extended-remote :61234
(gdb) load            # optional: programs 0x70000000 through the external loader
(gdb) monitor reset
(gdb) break main      # hardware breakpoint chosen automatically (0x70000000 is flash in the memory map)
(gdb) continue

STM32CubeIDE alternative: debug Boot, terminate (Ctrl+F2), debug Appli, Resume (F8), press NRST.

Sensors/Peripherals

Audio (Primary Function)

  • ADF1 - Digital microphone (PDM interface, 48kHz sample rate)
  • I2C1 - Audio codec (STM32 Audio BSP)
  • DMA2D/GPDMA1/HPDMA1 - Audio DMA channels

Display

  • LTDC - LCD-TFT controller
  • GPU2D (NemaGFX) - 2D acceleration
  • Display: 800x480 RGB565 (LTDC)

Storage & Communication

  • XSPI1 - External PSRAM (for audio buffers)
  • XSPI2 - External Flash (for TouchGFX assets)
  • I2C1 - Touch controller (FT5336), sensors

Touch Control

  • FT5336 - Capacitive touch controller
  • SPI - Touch interface
  • GPIO - Touch interrupt (TP_IRQ)

Audio Processing

Effects Chain (in order)

  1. Octaver - Dual-grain pitch shifting (-2, -1, +1, +2 octaves)
  2. Equalizer - 10-band graphic EQ (31 Hz - 16 kHz, -24..+24 dB)
  3. Overdrive - Distortion effect
  4. Saturation - Audio saturation
  5. Echo - Delay-based echo
  6. Reverb - Room reverb

Analysis

  • FFT: 2048-point real FFT (CMSIS-DSP)
  • Sample rate: 48kHz
  • Bins: 1024 (0-24kHz spectrum)
  • Peak detection: Frequency with maximum magnitude

Looping

  • Duration: Up to 5 seconds at 48kHz
  • Playback: 2x speed (raises pitch by octave)
  • Storage: External PSRAM (937.5KB buffer)

TouchGFX Architecture

Project Structure

Appli/
├── TouchGFX/
│   ├── App/                    # Application code (user created)
│   ├── assets/                 # Images, fonts, videos
│   ├── build/                  # Generated build files
│   ├── config/                 # Build configuration
│   ├── generated/              # Auto-generated code (DO NOT EDIT)
│   ├── gui/                    # Custom GUI code (views, presenters)
│   ├── simulator/              # Simulator files
│   └── target/                 # Target-specific code

GUI Screens

  • InitScreen - Splash screen (title + central button) -> Overview
  • Overview - Home screen: power toggle + master volume, 3x2 grid of effect cards (tap = open the effect screen, switch = enable/bypass), looper (hold to record, plays back x2), Spectrum button
  • Octaver, Equalizer, Overdrive, Saturation, Echo, Reverb - Effect tuning screens (common header: back, title, on/off; sliders with live value)
  • Oscillo - Spectrum analyzer (title "SPECTRE")

UI Conventions (keep when editing the GUI)

  • Never write files in Appli/TouchGFX/generated/: it is regenerated by TouchGFX Designer. Screens, widgets and interactions come from CelloEffects.touchgfx.
  • Custom look is done in user code only (Appli/TouchGFX/gui/): each XxxView::setupScreen() re-lays out the generated widgets and adds extra ones.
    • gui/include/gui/common/UiTheme.hpp: palette, per-effect accent color (ui::accent()), ui::Header, ui::ValueText (formatted value: show("%d %%", v), showDb(v)), ui::layoutEffectHeader(), ui::layoutParamRow()
    • gui/include/gui/common/EffectCard.hpp: home-screen effect card
    • The home grid lives in OverviewView; the generated buttonWithLabel1..6 of Overview are hidden on purpose.
  • A new screen must be created in TouchGFX Designer (so FrontendHeapBase and FrontendApplicationBase include it). A screen hand-written outside Designer is not in the screen heap and corrupts memory.
  • Texts: add them to Appli/TouchGFX/assets/texts/texts.xml (group UiRework); the build regenerates texts and fonts (T_<ID>). Typographies: Default 20 px, Medium 28 px, Large 40 px. Wildcard texts: VALUE_M_LEFT (Medium), VALUE_S_CENTER (Default); a character shown in a wildcard must be listed in the typography's WidgetWildcardCharacters.
  • Canvas widgets (Circle, Graph...) need a per-screen CanvasWidgetRenderer::setupBuffer() (see OverviewView, OscilloViewBase).

Memory Map

Key Sections

  • AudioLooperBuffer - External PSRAM (audio loop recording)
  • TouchGFX framebuffers - External PSRAM (LCD display)
  • Heap - Internal RAM (50KB FreeRTOS heap)
  • Stack - Internal RAM (task stacks)

External Memory

  • PSRAM: 8MB (XSPI1) - Audio buffers + framebuffers
  • Flash: 128MB (XSPI2) - TouchGFX assets (compressed images/fonts)
  • External FlashLoader: gcc/MX66UW1G45G_STM32H7S78-DK.stldr (required for programming external flash via STM32CubeProgrammer)

Data Logging

  • Format: CSV (to be implemented)
  • Storage: SD card via SPI (not currently implemented in main code)
  • FATFS: File system (available via Middlewares/ST)

Last updated: October 2026 Project: STM32H7S78-DK Audio Effects Processor with TouchGFX

Last fixed: October 18, 2026 (VS Code/CLI build-flash-debug verified on board: gcc/flash.sh, Cortex-Debug + ST-LINK_gdbserver)

Flashing Troubleshooting

Common Issues

  1. DEV_TARGET_NOT_HALTED / Cannot connect to access port 1 / gdbserver Target unknown error 32

    • Cause: missing access port or connect-under-reset option
    • Solution: ap=1 mode=UR (CLI) or -m 1 -k (ST-LINK_gdbserver), as used by gcc/flash.sh and .vscode/launch.json
  2. "Upload size is bigger than flash memory size"

    • Cause: reading beyond the 64 KB internal flash (0x08000000-0x08010000)
    • Solution: use a smaller read size
  3. External memory (0x70000000) not accessible

    • Cause: External FlashLoader not loaded
    • Solution: add -el gcc/MX66UW1G45G_STM32H7S78-DK.stldr (CLI and gdbserver)
  4. Application runs but display is blank

    • Cause: Appli not flashed in external memory correctly, or Boot missing
    • Solution: gcc/flash.sh all, then gcc/flash.sh verify
  5. ST-Link busy

    • Cause: a debug session or STM32CubeProgrammer GUI holds the probe
    • Solution: stop it, then retry
  6. nul files appear in the repo

    • Cause: Windows 2> nul redirections in gcc/include/cube_programmer.mk (now guarded with ifeq ($(OS),Windows_NT))