{"id":7335,"date":"2021-07-07T08:37:49","date_gmt":"2021-07-07T15:37:49","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=7335"},"modified":"2023-05-11T08:59:35","modified_gmt":"2023-05-11T15:59:35","slug":"debugging-the-pio-module-on-raspberry-pi-pico","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/raspberry\/pico\/pio\/debugger\/","title":{"rendered":"Debugging the PIO module on Raspberry Pi Pico"},"content":{"rendered":"<p>This tutorial shows how use VisualGDB to debug the PIO module on RP2040 (Raspberry Pi Pico). We will start with cloning the basic &#8220;hello_pio&#8221; sample, modify it to have a non-trivial PIO state machine program, and will show how to use VisualGDB to step the PIO state machine.<\/p>\n<p>Before you begin, install VisualGDB 5.6 or later and make sure you are using the Custom edition or higher.<\/p>\n<ol>\n<li>Start Visual Studio, and locate the VisualGDB Raspberry Pi Pico Project Wizard in the <strong>Create a new project<\/strong> dialog:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/01-raspi.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7336\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/01-raspi.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>Enter the name and location for your project, then click &#8220;Create&#8221; to launch the VisualGDB-specific part of the wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/02-piodbg.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7337\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/02-piodbg.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>In this tutorial we will be cloning the <strong>hello_pio<\/strong> sample from the SDK, so proceed with the &#8220;Create a new project&#8221; selection:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/03-new.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7338\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/03-new.png\" alt=\"\" width=\"856\" height=\"693\" \/><\/a><\/li>\n<li>On the next page of the wizard select the ARM toolchain and pick the latest version of the Pico SDK: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/04-sdk.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7339\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/04-sdk.png\" alt=\"\" width=\"856\" height=\"693\" \/><\/a><\/li>\n<li>On the <strong>Project Sample<\/strong> page select the <strong>hello_pio<\/strong> sample under the <strong>pio<\/strong> category. You can use the filter to easily filter out samples that don&#8217;t have &#8220;pio&#8221; in the name: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/05-hello.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7340\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/05-hello.png\" alt=\"\" width=\"856\" height=\"693\" \/><\/a><\/li>\n<li>Power on your Raspberry Pi Pico board and make sure it&#8217;s connected to an SWD debugger. See <a href=\"https:\/\/visualgdb.com\/documentation\/embedded\/raspberry\/pico\/swd\/\">this page<\/a> for detailed instructions on SWD setup. Once everything is connected, VisualGDB will automatically detect the debug settings: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/06-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7341\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/06-debug.png\" alt=\"\" width=\"856\" height=\"693\" \/><\/a><\/li>\n<li>Press &#8220;Finish&#8221; to generate the project. Note that initially, Solution Explorer won&#8217;t show the PIO files because the Pico SDK does not report them out-of-the-box. To fix that, press the &#8220;Patch SDK&#8221; button in the tooltip shown by VisualGDB, or patch the SDK manually as described on <a href=\"https:\/\/visualgdb.com\/documentation\/picosdk\/patching\/\">this page<\/a>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/07-patch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7342\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/07-patch.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>Once the SDK has been patched, VisualGDB will show the PIO files in Solution Explorer and will highlight the PIO assembly syntax inside them. Try setting a breakpoint inside the loop in <strong>main()<\/strong> and starting a debug session. Once the breakpoint is hit, use the <strong>Debug-&gt;Windows-&gt;PIO Debugger<\/strong> command to open the PIO debugger: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/08-running.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7343\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/08-running.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a>Normally, the PIO debugger tries to be as non-intrusive as possible. Even when the CPU is stopped at a breakpoint, the PIO will continue running and the PIO debugger will show it.<\/li>\n<li>Click at the &#8220;Halt and begin debugging&#8221; link in the PIO Debugger window. VisualGDB will suggest doing another patch to the SDK to track down each PIO instruction to a source line in the corresponding <strong>.pio<\/strong> file. You can proceed with patching the SDK automatically, or do it manually as shown <a href=\"https:\/\/visualgdb.com\/documentation\/picosdk\/patching\/\">here<\/a>:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/09-patch.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7344\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/09-patch.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>Once the SDK has been patched, and the project has been updated to include the profiler framework, start debugging it again and let the breakpoint in the main loop hit. Click &#8220;halt and begin debugging&#8221; in the PIO debugger window again. This time VisualGDB will show the values of the PIO registers and will highlight the current PIO instruction in the <strong>.pio<\/strong> files as long as the highlighting is enabled via the button on the toolbar:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/10-highlight.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7345\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/10-highlight.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>You can step the PIO separately from the main CPU using the &#8220;step&#8221; button on the toolbar, or do multiple steps at a time using a button at the bottom of the PIO debugger: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/11-stepped.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7346\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/11-stepped.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>Note that the PIO is stuck at the &#8216;pull&#8217; instruction because the CPU has not fed any data into it. You can simply step over the call to <strong>pio_sm_put_blocking()<\/strong> to let the CPU send one data word to the PIO. To prevent the PIO from being resumed together with the CPU, click at the button to the bottom right of the PIO debugger and select &#8220;<strong>When the CPU is resumed =&gt; Keep Stopped<\/strong>&#8220;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/12-stop.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7347\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/12-stop.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>Now you can step over the call to <strong>pio_sm_put_blocking()<\/strong> and the PIO will remain stopped at the &#8216;pull&#8217; instruction:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/over-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7358\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/over-1.png\" alt=\"\" width=\"1229\" height=\"795\" \/><\/a><\/li>\n<li>Now you can step the PIO to record how it responds to the newly received data. Press the &#8220;Step&#8221; button in the PIO debugger window twice and observe how the state machine goes through the <strong>out<\/strong> instruction, changing the value of PINS:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/13-out.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7348\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/13-out.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>The PIO debugger always keeps history of the PIO state after each step. You can use the back\/forward buttons in the PIO debugger to display the previous states of the PIO:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/14-goback.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7349\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/14-goback.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>Running both CPU and PIO state machines one step at a time works well when the PIO is used as an output. However, it it depends on some rapidly changing external signal that cannot be easily paused, this won&#8217;t work. To support debugging such scenarios VisualGDB allows overriding the input signals routed into the PIO. We will demonstrate it on a simple example. Modify the PIO program to load the value of <strong>PINS<\/strong> into the <strong>X<\/strong> register and run the program again. Use the same trick with stepping over <strong>pio_sm_put_blocking() <\/strong>to let the PIO run one full loop and observe how the value of the X register is changed after running the <strong>mov x, pins<\/strong> instruction: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/15-pulled.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7350\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/15-pulled.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>For the sake of the demonstration, let&#8217;s assume that the input #29 is some external clock and we want to check how the PIO responds when it is set to 1. Step the PIO until it reaches the <strong>mov x, pins<\/strong> instruction again and click on the &#8220;override&#8221; button under <strong>PINS_IN -&gt; [29]<\/strong>: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/16-override-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7361\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/16-override-2.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a>Configure VisualGDB to replace the signal on pin #29 with a periodic clock. See how the new value will be immediately displayed in the second half of last cycle and how the toolbar will indicate that 1 signal has been overridden.<\/li>\n<li>If you step over the &#8220;<strong>mov x, pins<\/strong>&#8221; instruction now, the value of X will have the <strong>0x20000000<\/strong> bit set, as if pin #29 had a value of 1:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/17-x.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7352\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/17-x.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a>Overriding the signals does not affect the actual physical state of the pins. It only changes the value seen by the PIO (and any other peripherals inside the chip). The pins remain configured as inputs or outputs, depending on the previous configuration.<\/li>\n<li>You can quickly switch between different sets of test signals by saving signal override configuration to XML files, and loading them back later:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/18-list.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7353\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/18-list.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a>Note that loading overrides from a file resets their phase (i.e. all patterns and clocks will start from the beginning at the clock cycle when the override configuration was loaded).<\/li>\n<li>Note that in the previous run the PIO debugger started at the &#8220;<strong>pull<\/strong>&#8221; instruction and never recorded the first &#8220;<strong>mov x, pins<\/strong>&#8220;. This happened because the PIO executed that instruction before the PIO debugger had a chance to stop it. We will now show how to override this behavior and step the PIO programs from the very beginning. First of all, move the call to <strong>pio_sm_set_enabled()<\/strong> from <strong>hello.pio<\/strong> to <strong>hello.c<\/strong>. Then set a breakpoint on that call: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/19-inactive.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7354\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/19-inactive.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>Once the breakpoint hits, the PIO will be configured and ready to be started, but not running yet. Instead of letting <strong>pio_sm_set_enabled()<\/strong>, click the &#8220;Explicitly start one or more state machines&#8221; link in the PIO debugger, then select state machine #0 and click &#8220;Start&#8221;: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/20-start.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7355\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/20-start.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a><\/li>\n<li>VisualGDB will start the PIO and record its operation from the first instruction: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/21-overridden.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7356\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/06\/21-overridden.png\" alt=\"\" width=\"1229\" height=\"798\" \/><\/a>Note that if you configure the PIO Debugger to keep the PIO stopped, and step over the <strong>pio_sm_set_enabled()<\/strong> call, it will still start the PIO, preventing VisualGDB from capturing its state. You can override this by right-clicking at the next code line after the call to <strong>pio_sm_set_enabled()<\/strong> and selecting &#8220;Set Next Statement&#8221; to force the CPU to skip that call.<\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how use VisualGDB to debug the PIO module on RP2040 (Raspberry Pi Pico). We will start with<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[27],"tags":[233,231],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7335"}],"collection":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/comments?post=7335"}],"version-history":[{"count":3,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7335\/revisions"}],"predecessor-version":[{"id":8133,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7335\/revisions\/8133"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=7335"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=7335"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=7335"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}