На первый взгляд очень простая задача, но когда работаешь с микроконтроллером через какой-нибудь gdb стаб/openocd, а память в которую подгружаем файл на самом деле флеш память микроконтроллера, (например, stm32) возникают нюансы. Решил собрать все шаманства в одном посте.
Итак, загрузку файла в память штатно gdb может делать двумя командами: load и restore. Если gdb подцепляется к openocd серверу, то у нас также есть пара команд монитора для программирования флеша.
- load — понимает только elf файлы, подгружает все секции по адресам, в т.ч. во флеш.
- restore — может загружать bin файлы по произвольному адресу. Но в случае попытки прогрузить во флеш-память кидает ошибку.
- monitor flash write_bank — поддерживается только если мы подключаемся через OpenOCD. Но может грузить бинарные файлы.
Неприятность заключается в том, что команда monitor flash write_bank доступна только если мы работаем через OpenOCD, а restore на опробованных мною комбинациях отладчик/таргет всегда кидал ошибку. В итоге оставалась только команда load.
Проблем никаких, если мы собираем прошивку сами, и у нас есть исходники. Проблемы начинаются, если нам нужно прописать во флешку данные (например, конфиг), или готовую, скачанную из интернета прошивку, которая доступна только в виде bin файла.
В этом случае потребуются шаманства, а именно сделать из .bin elf, при этом меняя адрес единственной в этом файле секции .data на адрес флеша, куда мы будем загружать файл. На примере stm32, это можно сделать вот таким вот заклинанием. Оно скушает app.bin и выплюнет нам app.elf
arm-none-eabi-objcopy -I binary -O elf32-littlearm —change-section-address=.data=0x8000000 -B arm -S app.bin app.elf
Для других архитектур/микроконтроллеров придется поменять адрес секции .data (выделено курсивом), выходную архитектуру и вариант (выделены жирным). objcopy тоже лучше использовать из состава тулчейна для этого микроконтроллера.
Прогрузка файла через gdb (На примере black magic probe) будет выглядеть так:
target extended-remote /dev/ttyACM0
mon swdp_scan
att 1
load app.elf
Если эта команда ругается на Error erasing flash with vFlashErase packet, (например, если перед этим мы стирали option bytes’ы), то надо передернуть питание целевого мк и сделать mon_swdpscan заново.