Close

stm32g0, openocd, and mecrisp stellaris - part 3

Andrew ClappAndrew Clapp wrote 11/17/2021 at 00:04 • 4 min read • Like

Let's suppose that you have written your code, and written it to to memory of the chip, and you now have a chip you can power off and restart and it comes up and does something useful for you in your prototype circuit.  Well, you basically have created a binary that lives in memory on the chip.  If you just read a copy off, you can write it to another chip and you're on your way to production automation.

I bootstrapped this whole process by first writing the mecrisp binary to the chip.  I used st-flash as such:

st-flash erase

st-flash write ~/work/projects/mecrisp/mecrisp-stellaris-stm32g031f4.bin 0x8000000

st-flash reset

You must remember to erase the chip first with some utilities, so I always do it just in case the write command does not.  Once reset, the chip is running forth.  You can now use e4thcom or whatever your preference is to connect to it via serial and begin programming.  Once you have it programmed, you can read off a binary to flash to other chips.

st-flash read ~/work/projects/mecrisp/adc-v.bin 0x8000000 16K

st-flash reset

Now I have a binary image of a programmed forth instance that comes up and measures my voltage at the ADC.  I can program other micros to do the same thing.  I can move my programmer, stllinkv2 or whatever you have, to another micro, and now I can flash that new one, and it will be a clone of all the working code so far.

st-flash write ~/work/projects/mecrisp/adc-v.bin 0x8000000

 This is about where some things started to go awry for me.  Option Bytes.  I wanted to read the option bytes and check to see what some of the default settings were compared to what the datasheet says they should be.  I could not get st-flash to spit out the right stuff.  Furthermore, I wanted to program/read/check more than one chip at a time.  The contraption we have built actually has two micros on it that do different things.  I could not get st-flash to correctly index more than one st-linkv2 consistently across my various build/dev/prog environments, a linux pc, a raspberry pi 3, and a pi 4, etc.  But here are the ways you would do this in theory.

Option Byte
st-flash --area=optcr1 read 

# red
echo "flashing red"
st-flash erase --serial 55FF66064887575412270787 adc-a.bin 0x8000000
st-flash write --serial 55FF66064887575412270787 adc-a.bin 0x8000000
# ./st-flash reset
# gold
echo "flashing gold"
st-flash erase --serial 151115002C135437334D4E00 adc-v.bin 0x8000000
st-flash write --serial 151115002C135437334D4E00 adc-v.bin 0x8000000
# ./st-flash reset

 Enter openocd.  It's what everybody's using, but in my laziness, hubris, and impatience, I had previously failed to muster the required activation energy to hurdle the learning curve.  Then I stumbled across this in a search:  OpenOCD for STM32G0 and STM32G4

Next thing you know, I started reading the openocd user's guide.  And it has been very much the best solution for a number of tasks.  There's a bit of a learning curve, but I assure you it is worth it.  Here's what I ended up with, maybe it will save you some time.  First my first config file for openocd:

source [find /usr/local/share/openocd/scripts/interface/stlink.cfg]
source [find /usr/local/share/openocd/scripts/target/stm32g0x.cfg]
gdb_memory_map enable
gdb_flash_program enable
init
reset_config trst_and_srst
jtag configure stm32g0x.jrc -event setup "jtag tapenable stm32g0x.cpu"
jtag tapisenabled stm32g0x.cpu
dap create CPU -chain-position stm32g0x.cpu

Next, the tailored version, one for each programmer, here's one: "openocd-1.cfg".  Some of the items are commented out.  And I'm still not exactly 100% sure if all these lines do what I want/think or if they are all necessary.  But it's working, so there's that.

source [find /usr/local/share/openocd/scripts/interface/stlink.cfg]
source [find /usr/local/share/openocd/scripts/target/stm32g0x.cfg]
gdb_memory_map enable
gdb_flash_program enable

hla_serial "\x55\x3f\x66\x06\x48\x3f\x57\x54\x12\x27\x07\x3f"
gdb_port disabled
tcl_port disabled
telnet_port disabled
#gdb_port 3333
#tcl_port 6666
#telnet_port 4444

init
#reset_config trst_and_srst
jtag configure stm32g0x.jrc -event setup "jtag tapenable stm32g0x.cpu"
dap create CPU -chain-position stm32g0x.cpu

I did still use st-info to find the serial numbers for my st-linkv2 programmers.

et:bin$ ./st-info  --probe
Found 2 stlink programmers
 serial:     553f6606483f57541227073f
 hla-serial: "\x55\x3f\x66\x06\x48\x3f\x57\x54\x12\x27\x07\x3f"
 flash:      16384 (pagesize: 2048)
 sram:       8192
 chipid:     0x0466
 descr:      G030/G031/G041
 serial:     151115002c135437334d4e00
 hla-serial: "\x15\x11\x15\x00\x2c\x13\x54\x37\x33\x4d\x4e\x00"
 flash:      16384 (pagesize: 2048)
 sram:       8192
 chipid:     0x0466
 descr:      G030/G031/G041

By using a 2nd config file with a different hla_serial (and different port numbers), I can directly choose which st-linkv2 I'm working with.  Here is a short script that programs two different chips with two distinct binary images.

echo "programming voltage chip"
openocd -d0 -f openocd-1.cfg -c "program adc-v.bin 0x08000000 verify reset exit"
echo ""
echo "programming current chip"
openocd -d0 -f openocd-2.cfg -c "program adc-a.bin 0x08000000 verify reset exit

One other surprise to me was the speed at which it programs.  It's visibly faster than st-flash.  Program two micros with code verification and a reset in under a second.

et:option-bytes$ time ./prog-1
Open On-Chip Debugger 0.10.0+dev-00937-g8021aef90 (2021-11-03-16:13)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

target halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x00003660 msp: 0x20000330
** Programming Started **
Warn : block write succeeded
** Programming Finished **
** Resetting Target **
shutdown command invoked
Open On-Chip Debugger 0.10.0+dev-00937-g8021aef90 (2021-11-03-16:13)
Licensed under GNU GPL v2
For bug reports, read
        http://openocd.org/doc/doxygen/bugs.html
debug_level: 1

target halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x00003660 msp: 0x20000330
** Programming Started **
Warn : block write succeeded
** Programming Finished **
** Resetting Target **
shutdown command invoked

real    0m0.992s
user    0m0.113s
sys     0m0.153s

 Now that's pretty slick and I'm happy with it.  The environment is fast, pretty compact, and it comes with some good "bells and whistles" like actually verifying the code on the chip.

Like

Discussions