December 22, 2023

STM32H747I-DISCO "Discovery kit with STM32H747XI MCU" -- debugging using openocd

I am busy writing a lot of code to set up clocks for the H747. I cannot use GPIO, never mind the serial console without setting up bus clocks. Bus clocks are derived from a PLL generated clock, so I need to set that up also. The trick is that I am writing a lot of code, and it is hard to imagine I will get it right the first time. But I have no way of getting any debug output (no LED to blink, no console). As I contemplated this, I realized that my openocd connection might provide a way to learn things.

A first attempt (that worked!)

I wrote a blink demo a few days ago and flashed it into the board. It does not work, presumably because I have a lot of work to do setting up the clocks, but what is it doing? Can I poke at it with openOCD?
I do the following (in two separate windows)
./ocd_start
telnet 4444
Then I do this:
halt
reg
I see the PC at 0x08000066, and this is in my delay/spin routine, which makes perfect sense. I use resume and halt to sample different moments and also see 0x0800006a, so the code is running, not just stalled. This tells me one important thing already. I was unsure if my code would just start running at 0x08000000 or if I needed a reset vector there. I put a reset vector there, and indeed that is the right thing to do.

Now, can we set a breakpoint? My makefile generates "blink.dump" that is a huge help in figuring out addresses and such. My "led_on()" routine is at 080000e0, so lets try that:

halt
> bp 0x080000e0 2
breakpoint set at 0x080000e0
resume
All well and good, but we never break.

Let's try to read memory and look at the stack:

read_memory 0x30047f00 32 64
0x5cc730ab 0xea4889a5 0xb259ebb9 0x24184520 0x6f7cdffd 0xf261ebac 0xd39a1f32 0xc3010e70 0x7eb06e5 0x2c946784 0x1b33aaac 0xe8e5167e 0x6fb7960f 0xc3608ca0 0x4c37f35d 0x92159af2 0xbd2e4eb6 0xa81a5ec1 0xe8bfaf9e 0xa3921cc4 0x76f67ecf 0xa6f9187c 0xe32f4bf9 0xcf1dc344 0x8f7ccf6e 0x6ec08405 0x4af13afb 0x2fb2da65 0xde777ec2 0x85293b8b 0xdd9929b2 0x92820a1c 0x6e5ffebc 0x2895c19e 0x6eb07e9b 0x3002840d 0xb4cb3e3a 0x24aa4618 0xfff9ac32 0x23018442 0x8d5fddc1 0x4baca1cd 0xb446acad 0x49513712 0x3b8fabab 0x62ee0560 0xd1b86751 0xfb755862 0x7bd69bd9 0x60924e64 0x3deeca85 0x4 0xb2a5a934 0x1 0x300 0xa0014 0xcd5d72da 0x58022000 0x30047ff0 0x1a711 0x30047ff8 0x30047ff8 0x0 0x8000057
This works, and the last few items look like real data. The display is hardly convenient or handy though. I find myself already thinking about working up some kind of GUI or at least a more helpful front end. Others have done so, using Tcl/Tk (the horror!), Qt, and even Python with various GUI toolkits.

Too bad Fedora no longer supplies arm-none-eabi-gdb

You can type "history"! There is a 231 page openOCD user guide, updated only 2 days ago! No mention of the "history" command in it, but experimenting shows that the arrow keys work both to go back in history and to edit commands.

Okular makes a pretty good PDF reader with search

A simple program

See my github repository for this if you want the source: The upshot of this is that I made (and fixed) a number of simple errors, even with only 62 lines of C code. But openocd was immensely helpful. And I can claim that I am running my own code on the H747 now! Even a simple GUI would be massively helpful and time saving. To work with my code using trial and error I must: Somewhat tedious, but entirely worth it. It is also too bad I cannot use command line editing to repeat and modify my command history. Honestly, openocd is fantastic, but it seems like a "back end" that is missing a front end. Like an assembler without a compiler. Of course you can get work done with just an assembler.

Breakpoints

They are a mystery. Openocd has a "bp" command, I have used it to set breakpoints (at least it says it has set them and just typing "bp" shows them). But they never break. My searches all lead me to people using gdb to set breakpoints and using openocd behind gdb. How can openocd set a breakpoint for code running from flash? Maybe it can't, but just isn't letting me know. Maybe I need to load my code to ram and run it if I want to set breakpoints. Or get gdb somehow.

Look at this:

I follow the instructions. I already have dnf-command installed, so:
dnf copr enable rleh/arm-none-eabi-gdb
dnf install arm-none-eabi-gdb
It works! I start it and "show version" gives me "GNU gdb (GDB) 14.1". I wish I could find the SRPM and/or contact the packager, but I cannot figure out how to do that.
Feedback? Questions? Drop me a line!

Tom's Computer Info / tom@mmto.org