Как работает stm32-gdbpy-scenario

Один сценарий — один прогон — один проверяемый итог. Python внутри GDB доходит до функции, читает или временно меняет переменную, проверяет наблюдаемую реакцию прошивки и возвращает всё как было. Без фреймворка: нужны GDB с Python, GDB-сервер и Python на хосте. Для коротких действий GDB не нужен вовсе — стоп, старт, сброс и чтение адреса выполняются одной командой, в том числе на удалённом стенде по SSH.

Путь сценария

подготовка работа с платой эмулятор итог и вмешательство
1. Подготовка до действия
Почти все провалы — до воздействия: не тот GDB, не та плата, ядро стоит.

GDB с Python

принимается только GDB, выполнивший python print(6 * 7)

run_scenario.py --check-gdb
и

Отпечаток стенда

пробник, узел и DEV_ID совпадают с прошлыми прогонами

ocd.py state read 0xE0042000
и

Бюджет

таймауты сервера и GDB, потолок итераций, ожидание по тикам цели

--timeout 60
2. run_scenario.py поднимает сервер и запускает GDB
Свободный порт, готовность по журналу сервера, уборка только своих процессов.

OpenOCD

ST-Link или J-Link (transport select swd), локально

--openocd-config ...
или

J-Link GDB Server

сервер SEGGER, имя МК из базы SEGGER

--jlink-device AT32F403ACGU7
или

Узел стенда

сервер на узле через nohup, SSH-туннель, после прогона — kill своего pid

--ssh user@stand
GDB

Сценарий gdb-py

шаблон: check, reach, read, write, monitor, record

gdb -nx -batch app.elf -ex "source ..."

Без платы

Renode поднимает GDB-сервер с моделью платы; тот же сценарий, итог помечается «emulator».

--renode-platform board.repl
3. Итог и возврат
Итог пишется всегда, в finally; записанное возвращается и проверяется чтением.

run.json

проверки, наблюдения, окружение, время, последний шаг

status, checks, records, restored
код

PASS / FAIL / ERROR / TIMEOUT

0 — PASS, 1 — провал проверки, 2 — исключение, невозвращённая переменная или зависание

годится для CI
плата

Работает дальше

OpenOCD: continue &, detach; J-Link: monitor go, disconnect

не оставлять в halt

Порядок внутри сценария

СбросНа плате GDB подключается к работающей прошивке: сначала monitor reset halt, иначе reach("main") зависнет.
ИсходноеПрочитать то, что будет сравниваться.
ДействиеОдна запись, вызов или достижение точки останова.
НаблюдаемоеСледствие, ради которого действие делалось, а не «записали».
СоседнееТо, что меняться не должно, не изменилось.
ВозвратЗаписанное возвращено и проверено чтением.

Команды без GDB

ДействиеOpenOCDJ-Link Commander
readmdw, ядро не останавливаетсяmem32, тоже на ходу
haltсохраняется после выходаотпускается при выходе
resumeв новом сеансе только после haltg; для работающего ядра «already running»
reset-haltreset haltr
reset-runreset runr, g
python scripts/ocd.py --ssh user@stand --target stm32f4x \
    --serial <серийник> state read 0xE0042000
python scripts/jlink.py --ssh user@stand --device AT32F403ACGU7 \
    --serial <номер> halt state resume

Чтение адреса одной строкой

ssh user@stand "openocd -f interface/stlink.cfg \
  -c 'adapter serial <серийник>' -f target/stm32f4x.cfg \
  -c init -c 'mdw 0xE0042000' -c shutdown 2>&1 | grep -i '^0x'"
# 0xe0042000: 10006431
СпособВремя
одноразовый сеанс, локально0,3 с
одноразовый сеанс по SSH0,7–1,9 с
работающий OpenOCD, socat на узле~0,5 с
туннель и Tcl-порт (ocd.py --tcl)~0,4 с; локально 0,1 с

Что важно понимать

Запись — не потреблениеВ примере новый период кадров действует только со следующего запланированного кадра: первый интервал после записи остаётся 100 мс.
Проверять наблюдаемоеКлюч питания — намерение прошивки, работу тракта показывает только трафик.
J-Link пишет точки во FlashБез monitor flash breakpoints = 0 J-Link GDB Server ставит программные точки останова записью во Flash. Запускатель включает это сам.
Сброс и прошивка — вмешательствоЧтение памяти ядро не останавливает, а halt, сброс и запись Flash меняют работу платы. На силовой плате — только после проверки, что стенд тестовый.
Пробник по USB-адресуST-Link V2 со старой прошивкой отдаёт нечитаемый серийник: --adapter-usb-location 7-1.1.3.
Windows и портыФиксированный порт может попасть в диапазон, зарезервированный системой; запускатель берёт порт, выданный ОС.

Насколько проверено

Проверено на стендах 28.10.2026

  • BlackPill F411CE локально (Windows) и по SSH: команды, сценарий по адресам, копия Flash, прошивка зонда, сценарий зонда, возврат образа с совпавшим хешем
  • F401CC и Blue Pill F103C8 по SSH: то же
  • Nucleo F030R8 и F429ZI (ST-Link V2 по USB-адресу) по SSH: команды и сценарий по адресам
  • AT32F403A за J-Link по SSH: JLinkExe и OpenOCD, сценарий через J-Link GDB Server и OpenOCD

CI и открытые вопросы

  • CI: пример зонда в Renode и четыре исхода шаблона (PASS, FAIL, ERROR с возвратом, TIMEOUT)
  • однократное нулевое чтение сразу после прошивки — причина не установлена, готовность проверяется переменной прошивки
  • прошивка AT32 через OpenOCD не проверялась: драйвер Flash не опознал МК

Описание навыка (SKILL.md) и скрипты · версия 1.2.0