November 18, 2023

Let's learn USB! -- openocd

OpenOCD has nothing specific to do with USB. It is just a tool we use to load code into our F103 boards.

I had the idea of using one of my Maple boards instead of a "blue pill". Part of this was intended to be the entertainment (if you can call it that) of using things I have laying around in my drawer). But there is a valid reason, and that is that by pulsing GPIO PC12, we can cause a USB disconnect. This would allow me to be lazy and avoid unplugging and replugging my USB cable each time I load new code.

The trick (if you want to call it that) with the Maple board is that mine have the DFU boot loader installed. This allows code to be loaded via USB if you have the tool "dfu-util" on your development system. See my "blink_maple" project where I use this in the Makefile. The DFU boot loader will live at 0x08000000 and runs on reset. You typically link your code to run at 0x08005000 and this all works out just fine. With this arrangement you don't need a ST-LINK device and can get things done with just a USB cable.

I don't want to use dfu-util (though maybe I could). I also don't want to overwrite the DFU loader. So I have two choices:

It I extract the DFU loader, I can keep the copy I extract and put it back later someday, should I want to. And with it safely backed up, I can just link my code to 0x08000000 and use the maple just like a blue pill.

Running openocd interactively

I have some old notes from when I did some experiments with the black pill: The way you work with openocd is a bit weird, you run it in the background and then connect to it via telnet on port 4444. So I type the following commands in two separate windows:
openocd -f /usr/share/openocd/scripts/interface/stlink.cfg -f /usr/share/openocd/scripts/target/stm32f1x.cfg
telnet localhost 4444
Actually I have a script "ocd" that runs the first command, which is handy. With openocd connected to my STLINK, it is busy blinking red/blue to let me know that it is happy. Now we can type commands to openocd, such as:
reset halt
dump_image maple_all.bin 0x08000000 0x20000
reset run
And there you go! The command to extract the maple boot loader.
To write an image back again, we use:
flash write_image erase bogus.bin 0x08000000
To run at a specified address, this works (if the processor is halted):
resume 0x08005000
Note that you must specify hex addresses using the C notation with a leading "0x".

OpenOCD via the command line

I use the following command line argument to run code that I link to 0x08000000.
-c "program baboon.elf verify reset exit"
Perhaps this would work to run code at 0x08005000?
-c "program baboon.elf verify resume 0x08005000 exit"
They say that "program" is not an openocd command, but rather it is a "jimtcl script". There really is a thing called "jimtcl", described as a small footprint tcl interpreter. I have looked for "program.tcl" but there is no such file on my system.

The Maple DFU loader

I dump the entire 128K flash (to 0x1ffff) and discover that the loader ends at 0xbf7f. But wait! This can't be true if user code gets loaded to 0x5000. Indeed, looking at it more carefully, the loader ends at 0x3dcf. It is blank (0xff) from there to 0x5000 and then there is user code from 0x5000 to 0xbf7f.

So it would be entirely safe for the DFU to load code to 0x08004000. Also we don't need to dump the entire 128K, just dumping to 0x4000 would get the loader (16K).

dump_image maple_dfu.bin 0x08000000 0x04000
So, we do that and now feel good about using a Maple board and overwriting the DFU loader.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org