December 22, 2023

STM32H747I-DISCO "Discovery kit with STM32H747XI MCU" -- openocd and tcl

For the first time I am starting to make direct use of OpenOCD.

The "program" command

I use this routinely in my Makefiles via a line like this:
OCDCFG = -f /usr/share/openocd/scripts/board/stm32h747i-disco.cfg
flash:  debug.elf
        openocd $(OCDCFG) -c "program debug.elf verify reset" -c "exit"
The documentation states that "debug is a Tcl script". This has always made me curious and I have looked in vain for "debug.tcl". I finally got annoyed (or curious) enough to look really hard. There is no debug.tcl. You won't find the tcl code at all unless you fetch the openocd sources. If you do, you will find it in:
src/flash/startup.tcl
Here you will see "proc program" with arguments as documented. Mystery solved.

One option is interesting, and not what I expected, namely "preverify". It checks if the image is already in flash and avoids needlessly reflashing it if it is already there.

I'll also note that when I use openocd in conjunction with gdb in some way, I avoid the "make flash" entry in my Makefile. It won't work if an openocd instance is already running and it is somewhat of a nuisance to kill and restart that. So I use the openocd telnet window and type:

program debug.elf preverify verify
I omit the reset and leave it there ready for gdb to set breakpoints and continue or step.

Some comments on Tcl

As I use it more and itch for some kind of "front-end" I have come to a realization. OpenOCD incorporates Tcl. In a sense you can flip this around and say that OpenOCD is Tcl, with debugging features built into it. I find myself somewhat surprised at being excited by this, because I have learned to hate and despise Tcl. I have burned every Tcl book I ever owned.

However, for almost the first time I have yet to encounter it, this is actually the exact purpose for which Tcl was invented. The idea was for it to be a small language that could be embedded into other software. Somewhere along the line the tail began to wag the dog and Tcl began being used as a general purpose programming language. This was never what it was designed for and was a very bad thing. No doubt none of this would have happened without the Tk toolkit, which made the Tcl/Tk combination an extremely quick and easy way to develop graphical interfaces. There was a point in time when this was unique, but very soon Perl, and not much later Python began being used for such things and Tcl was a miserable choice when put up alongside these.

I won't apologize to the Tcl die-hards (if there are any left) for any of this. But this perspective does make me feel better about being excited to find Tcl integrated into OpenOCD. The OpenOCD manual has a section (chapter 23 in one edition) called "Tcl crash course" that is very good. Remember, everything is a string.

Maybe the most infuriating thing about Tcl is there are no infix operators. We are ignoring of course "expr", but to make the point remember than in Tcl you cannot say "x = 5", you say "set x 5". And remember that x is a string.

Here is a quick example where I use tcl over the "telnet localhost 4444" connection for my current project:

> set ram 0x24000000
0x24000000
> read_memory $ram 32 4
0x64eaf 0x64eae 0xdeadbeef 0xdeadbeef
> proc ramshow {} { read_memory 0x24000000 32 4 }
ramshow
> ramshow
0x64eaf 0x64eae 0xdeadbeef 0xdeadbeef
Here we are defining Tcl variables and procedures (which act like macros) "on the fly". These will go away when we restart openocd. We can put commands into a file, but the needs to be located in the same directory where openocd (not telnet) is launched from.
So I put these commands into the file h.tcl
proc ramshow {} { read_memory 0x24000000 32 4 }
ramshow
Then in the telnet window I type:
source h.tcl
0x64eaf 0x64eae 0xdeadbeef 0xdeadbeef
ramshow
I am just scratching the surface, but you can start to see what is possible.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org