{"id":207,"date":"2013-02-23T01:19:51","date_gmt":"2013-02-23T08:19:51","guid":{"rendered":"http:\/\/www.mjblythe.com\/hacks\/?p=207"},"modified":"2021-12-22T00:01:01","modified_gmt":"2021-12-22T07:01:01","slug":"debugging-stm32-with-gdb-and-openocd","status":"publish","type":"post","link":"http:\/\/www.mjblythe.com\/hacks\/2013\/02\/debugging-stm32-with-gdb-and-openocd\/","title":{"rendered":"Debugging STM32 with GDB and OpenOCD"},"content":{"rendered":"<p><a href=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2013\/02\/Screenshot-from-2013-02-23-002810.png\"><img loading=\"lazy\" decoding=\"async\" class=\"size-full wp-image-208 alignnone\" alt=\"Screenshot from 2013-02-23 00:28:10\" src=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2013\/02\/Screenshot-from-2013-02-23-002810.png\" width=\"570\" height=\"479\" srcset=\"http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2013\/02\/Screenshot-from-2013-02-23-002810.png 644w, http:\/\/www.mjblythe.com\/hacks\/wp-content\/uploads\/2013\/02\/Screenshot-from-2013-02-23-002810-300x252.png 300w\" sizes=\"auto, (max-width: 570px) 100vw, 570px\" \/><\/a><\/p>\n<p>When developing my <a title=\"Valentine\u2019s day puzzle box\" href=\"http:\/\/www.mjblythe.com\/hacks\/2013\/02\/valentines-day-puzzle-box\/\">Valentine&#8217;s day puzzle box<\/a>, I found myself really wanting to single-step through some code to figure out where things were going wrong.\u00a0 Fortunately, the STM32F3 Discovery board that I was using supports on-chip debugging.\u00a0 Unfortunately, it wasn&#8217;t already integrated into the <a title=\"I\u2019m on Hack a Day!\" href=\"http:\/\/www.mjblythe.com\/hacks\/2013\/01\/im-on-hack-a-day\/\">template<\/a> that I was using for the project.<\/p>\n<p><!--more--><\/p>\n<p>This <a href=\"http:\/\/pulkomandy.tk\/_\/_Electronique\/_Discovering%20the%20STM32F3%20Discovery\">guide to the STM32F3<\/a> (also <a href=\"http:\/\/hackaday.com\/2012\/09\/27\/stm32-f4-discovery-tutorial-using-open-source-tools\/\">posted<\/a> on hackaday) has some information about debugging, but it wasn&#8217;t immediately clear to me what was going on.\u00a0 I eventually figured out that they were running OpenOCD in the background, then running a GDB session and telling it to attach to the port that OpenOCD had opened:<\/p>\n<pre>shell&gt; openocd -f \/usr\/local\/share\/openocd\/scripts\/board\/stm32f3discovery.cfg &amp;\r\nshell&gt; arm-none-eabi-gdb\r\n(gdb) target remote localhost 3333\r\n(gdb) file a.out\r\n(gdb)<\/pre>\n<p>This worked&#8230;kind of.\u00a0 GDB seemed to connect to OpenOCD, but I couldn&#8217;t use any useful GDB commands.\u00a0 I finally found the <a href=\"http:\/\/openocd.sourceforge.net\/doc\/html\/GDB-and-OpenOCD.html\">relevant OpenOCD documentation<\/a>, and things started to come together:<\/p>\n<pre>shell&gt; openocd -f \/usr\/local\/share\/openocd\/scripts\/board\/stm32f3discovery.cfg &amp;\r\nshell&gt; arm-none-eabi-gdb main.elf\r\n(gdb) target remote localhost:3333\r\nRemote debugging using localhost:3333\r\n...\r\n(gdb) monitor reset halt\r\n...\r\n(gdb) load\r\nLoading section .isr_vector, size 0x188 lma 0x8000000\r\nLoading section .text, size 0x4648 lma 0x8000188\r\nLoading section .data, size 0x4bc lma 0x80047d0\r\nStart address 0x80044dd, load size 19596\r\nTransfer rate: 18 KB\/sec, 4899 bytes\/write.\r\n(gdb) continue\r\nContinuing.\r\n...<\/pre>\n<p>This worked much better.\u00a0 Since the chip was halted, GDB responded to commands the way I expected.\u00a0 I was able to set breakpoints, single-step, print variable values&#8230;everything was great, but it was still too much repetitive typing to get it all set up.<\/p>\n<p>The solution was twofold.\u00a0 The same OpenOCD documentation page describes how GDB can run the OpenOCD command itself:<\/p>\n<pre> target remote | openocd -c \"gdb_port pipe; log_output openocd.log\"<\/pre>\n<p>I also found this in the GDB man page:<\/p>\n<pre>       -x FILE, -command=FILE\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 Execute GDB commands from file file.<\/pre>\n<p>Combining these meant that I could just have a list of commands in a file that would get GDB all set up:<\/p>\n<pre>shell&gt; cat gdb_cmds\r\ntarget remote | openocd -f \/usr\/share\/openocd\/scripts\/board\/stm32f3discovery.cfg -c \"gdb_port pipe; log_output openocd.log\"\r\nmonitor reset halt\r\nload\r\nshell&gt; arm-none-eabi-gdb -x gdb_cmds main.elf\r\n...\r\n(gdb)<\/pre>\n<p>And, just to make things even easier, I added a <code>debug<\/code> rule to the Makefile:<\/p>\n<pre>debug: $(PROJ_NAME).elf\r\n\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0\u00a0 $(GDB) -x extra\/gdb_cmds $(PROJ_NAME).elf<\/pre>\n<p>Now all I have to do is type <code>make debug<\/code>, and GDB starts up and initializes the board without me having to think about it!<\/p>\n<p>You can find my Makefile <a href=\"https:\/\/github.com\/mblythe86\/stm32f3-discovery-basic-template\/blob\/puzzle_box_1.0\/Makefile\">here<\/a>, and the gdb_cmds file <a href=\"https:\/\/github.com\/mblythe86\/stm32f3-discovery-basic-template\/blob\/puzzle_box_1.0\/extra\/gdb_cmds\">here<\/a>.\u00a0 (Or look at <a href=\"https:\/\/github.com\/mblythe86\/stm32f3-discovery-basic-template\/tree\/stm32f0-discovery-basic-template\">this branch<\/a> for the STM32F0 Discovery board.)<\/p>\n<hr \/>\n","protected":false},"excerpt":{"rendered":"<p>When developing my Valentine&#8217;s day puzzle box, I found myself really wanting to single-step through some code to figure out where things were going wrong.\u00a0 Fortunately, the STM32F3 Discovery board that I was using supports on-chip debugging.\u00a0 Unfortunately, it wasn&#8217;t already integrated into the template that I was using for the project.<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"footnotes":""},"categories":[3],"tags":[],"class_list":["post-207","post","type-post","status-publish","format-standard","hentry","category-f3-discovery"],"_links":{"self":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts\/207","targetHints":{"allow":["GET"]}}],"collection":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/comments?post=207"}],"version-history":[{"count":9,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts\/207\/revisions"}],"predecessor-version":[{"id":271,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/posts\/207\/revisions\/271"}],"wp:attachment":[{"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/media?parent=207"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/categories?post=207"},{"taxonomy":"post_tag","embeddable":true,"href":"http:\/\/www.mjblythe.com\/hacks\/wp-json\/wp\/v2\/tags?post=207"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}