Note to self: How to flash .bin files via “raw” gdb

At the first glance, it’s a very easy task. However it has a number of less obvious pitfalls when you’re working with microcontrollers via some kind of gdb stub or openocd and the memory you’re actually uploading your .bin file is the flash memory of an MCU (e.g. stm32). I decided to gather the common pitfalls in a single blog post.

Typical starter kit: A Chinese stlinkv2 clone flashed as black magic probe and an stm32f4 discovery board

So gdb can upload data to the target via 2 common commands: load and restore. If gdb is connected to an openocd server, we also have a couple of monitor commands to work with flash.

  • load – can only upload elf format files. Loads all sections to their respective addresses, including flash.
  • restore – Can upload arbitrary bin file to an address. If we try to load to flash – we’ll get an error (at least via black magic probe).
  • monitor flash write_bank – supported only of we’re working using gdb/OpenOCD. But it can load binary files with no problems.

The problem is, that monitor flash write_bank is supported only if we’re working via OpenOCD (I was not), and restore command always gave me errors on the hardware/software combinations I’ve tried. The only remaining option left was load.

There’s no issue with that, if you’re compiling the project yourself – you’ll always have the elf file. Problems arise if you need to upload raw data (e.g. configuration) or a ready-to-use firmware you’ve downloaded from the internet as a bin file.

If that’s the case, we’ll need to make an elf from .bin file, adjusting the .data section load address as necessary (Normally, it should point to flash). Taking stm32 as the example, the magic spell to turn bin into elf will look like this:

arm-none-eabi-objcopy -I binary -O elf32-littlearm –change-section-address=.data=0x8000000 -B arm -S app.bin app.elf

For other MCUs/arhitectures you’ll need to change the address of .data section to point to flash (written in italic), output architecture and variant ( written in bold). It’s also better to use objcopy from your toolchain. Just in case you’re working with some weird/unsupported architecture.

Loading the file via gdb (black magic probe as the example) will look like this:

target extended-remote /dev/ttyACM0
mon swdp_scan
att 1
load app.elf

If you get an ‘Error erasing flash with vFlashErase packet’, (like, just after you’ve erased the option bytes), power-cycle the target mcu and run mon swdp_scan and att 1 again.

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.