{"id":7218,"date":"2021-03-09T10:08:08","date_gmt":"2021-03-09T18:08:08","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=7218"},"modified":"2021-03-09T10:09:17","modified_gmt":"2021-03-09T18:09:17","slug":"debugging-i-mxrt-devices-with-openocd","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/imxrt\/flash\/","title":{"rendered":"Programming the FLASH memory of i.MXRT devices with OpenOCD"},"content":{"rendered":"<p>This tutorial shows how to debug the i.MXRT devices and program their FLASH memory using OpenOCD. We will show how to create an OpenOCD script that will handle the resetting of the chip properly, and then clone the <strong>fsl_romapi<\/strong> example from the i.MXRT SDK and will change it into an OpenOCD plugin for writing the FLASH memory. The FLASH plugins are supported by the <a href=\"https:\/\/github.com\/sysprogs\/openocd\/\">Sysprogs fork of OpenOCD<\/a>.<\/p>\n<p>In this tutorial we will use Visual Studio and VisualGDB to demonstrate everything, however the same steps will also work with any other environment that uses GCC and OpenOCD.<\/p>\n<ol>\n<li>Start Visual Studio and locate the VisualGDB Embedded Project Wizard:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/01-newprj-2.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7219\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/01-newprj-2.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>The first project we will create will be the <strong>fsl_romapi<\/strong> example showing how to use the i.MXRT ROM API to program the FLASH memory via FlexSPI. Pick the name and location for the project and click &#8220;Create&#8221;: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/02-name.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7220\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/02-name.png\" alt=\"\" width=\"1024\" height=\"680\" \/><\/a><\/li>\n<li>On the first page of the VisualGDB-specific part of the wizard, select &#8220;Create a new project -&gt; Embedded Application -&gt; Advanced CMake&#8221;: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/03-new.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7221\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/03-new.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>If you have not created any i.MXRT projects with VisualGDB before, create an SDK for your device using the <a href=\"https:\/\/mcuxpresso.nxp.com\/en\/welcome\">MCUXpresso SDK builder<\/a> (make sure it targets the GNU tools), download it, extract it to a folder of your choice and click &#8220;Import an MCUXpresso SDK&#8221; to import it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/04-import.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7222\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/04-import.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Once the SDK is imported, you can pick your i.MXRT device sfrom the list. Make sure you select the <strong>RAM<\/strong> linker script: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/05-path.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7223\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/05-path.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>On the Sample Selection page pick the <strong>fsl_romapi<\/strong> example and click &#8220;Next&#8221;:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/06-rom.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7224\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/06-rom.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Connect your board to the USB port. VisualGDB will automatically detect your debug interface and will suggest the matching OpenOCD configuration. The Sysprogs fork of OpenOCD already includes a basic configuration script for i.MXRT (not including the FLASH driver) that will be selected automatically. We will explain how to create your own script later in the tutorial: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/07-debug.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7225\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/07-debug.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Once you click &#8220;Finish&#8221;, VisualGDB will generate the project based on the selected sample. However, the generated project will use the linker script from the example itself (<strong>MIMXRT1052xxxxx_flexspi_nor.ld<\/strong>) instead of the default RAM script. Reset is by clearing the &#8220;Linker Script&#8221; setting under VisualGDB Project Properties:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/08-lds.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7226\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/08-lds.png\" alt=\"\" width=\"1188\" height=\"754\" \/><\/a><\/li>\n<li>This will revert to the <strong>MIMXRT1052xxxxx_ram.ld<\/strong> script and the project will now run directly from RAM:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/09-build.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7227\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/09-build.png\" alt=\"\" width=\"1190\" height=\"841\" \/><\/a><\/li>\n<li>In order to debug the i.MXRT device with OpenOCD without programming the FLASH memory, you need to create a corresponding OpenOCD script. You can use our <a href=\"https:\/\/github.com\/sysprogs\/openocd\/blob\/master\/tcl\/target\/imxrt.cfg\">existing script for i.MXRT<\/a>, or create a new one as shown below. First of all, the script needs to define a single ARM core debuggable via JTAG or SWD and specify the name\/location of RAM that will be used as a scratch buffer:\n<pre class=\"\">swj_newdap $_CHIPNAME cpu -irlen 4 -expected-id $_CPU_SWD_TAPID\r\ndap create $_CHIPNAME.dap -chain-position $_CHIPNAME.cpu\r\n\r\nset _TARGETNAME $_CHIPNAME.cpu\r\n\r\ntarget create $_TARGETNAME cortex_m -endian little -dap $_CHIPNAME.dap\r\n\r\n$_TARGETNAME configure -work-area-phys 0x20200000 \\\r\n                       -work-area-size 0x4000 \\\r\n                       -work-area-backup 0<\/pre>\n<p>The <strong>_CPU_SWD_TAPID<\/strong> variable can be set arbitrarily. OpenOCD will display a warning if it doesn&#8217;t match the actual ID of the chip, so you can update it later based on that warning.<\/li>\n<li>The i.MXRT devices do not support automatic halting after a system-reset via the SVD interface (SRST), so instead they need to be reset using the ARM Cortex reset request:\n<pre class=\"\">cortex_m reset_config sysresetreq\r\nreset_config none<\/pre>\n<p>The &#8220;<strong>reset_config none<\/strong>&#8221; line means that OpenOCD will not do a system-level reset itself and will only reset the core. However the &#8220;<strong>cortex_m reset_config sysresetreq<\/strong>&#8221; line makes sure that the core reset will actually reset the entire system.<\/li>\n<li>With the configuration shown above the &#8220;reset halt&#8221; and &#8220;reset init&#8221; commands will reset the chip right into the first instruction in the boot ROM, before the ROM gets a chance to initialize any peripherals. We can script OpenOCD to let the boot ROM run instead, and to wait until it jumps to the actual program. This can be done by examining the FLASH memory contents just before the reset (from the <strong>reset_init<\/strong> callback in Tcl) and setting a breakpoint at the entry point discovered from parsing the FLASH in the <strong>reset-deassert-post<\/strong> event handler. See our <a href=\"https:\/\/github.com\/sysprogs\/openocd\/blob\/master\/tcl\/target\/imxrt.cfg\">OpenOCD script for i.MXRT<\/a> for the full implementation of this functionality.<\/li>\n<li>Now we are ready to test out the FLASH programming example. Normally, it will print debugging output to the COM port connected to the on-board CMSIS-DAP debuggger. You can use the Raw Terminal window (requires VisualGDB Custom Edition) or any other terminal program to view it:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/10-comport.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7228\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/10-comport.png\" alt=\"\" width=\"967\" height=\"702\" \/><\/a><\/li>\n<li>Run the example and make sure it succeeds: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/11-ran.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7229\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/11-ran.png\" alt=\"\" width=\"1190\" height=\"841\" \/><\/a><\/li>\n<li>The example project programs a fixed page of the FLASH memory with fixed contents. However, if we restructure it into having separate functions for erasing and programming the memory, the <a href=\"https:\/\/github.com\/sysprogs\/openocd\/blob\/master\/src\/flash\/FLASHPlugin.c\">OpenOCD plugin interface<\/a> will be able to call these functions to program meaningful FLASH memory contents. The restructuring involves the following steps:\n<ol>\n<li>Add the <a href=\"https:\/\/github.com\/sysprogs\/flash_drivers\/tree\/master\/common\">common FLASH plugin sources<\/a> to the project.<\/li>\n<li>Remove the calls to <strong>BOARD_ConfigMPU()<\/strong> and <strong>BOARD_BootClockRUN()<\/strong> as they are not required for programming the memory.<\/li>\n<li>Call <strong>FLEXSPI_NorFlash_GetConfig()<\/strong> and <strong>ROM_FLEXSPI_NorFlash_ClearCache()<\/strong> directly from <strong>main()<\/strong>.<\/li>\n<li>Once FlexSPI has been initialized, call <strong>FLASHPlugin_InitDone()<\/strong>. This will signal to OpenOCD that the plugin has been initialized and is ready to run meaningful functions.<\/li>\n<li>Implement the <strong>FLASHPlugin_Probe()<\/strong>, <strong>FLASHPlugin_FindWorkArea()<\/strong>,\u00a0<strong>FLASHPlugin_EraseSectors()<\/strong> and <strong>FLASHPlugin_DoProgramSync()<\/strong> functions using the functions from the sample project. See our <a href=\"https:\/\/github.com\/sysprogs\/flash_drivers\/blob\/master\/imxrt\/IMXRT1050_HyperFLASH_ROMAPI\/main.cpp\">sample i.MXRT1050 implementation<\/a> for a ready-to-use example. We recommend chaning the main file extension to <strong>.cpp<\/strong> to avoid C\/C++ conflicts.<\/li>\n<li>Create a <a href=\"https:\/\/github.com\/sysprogs\/flash_drivers\/blob\/master\/imxrt\/IMXRT1050_HyperFLASH_ROMAPI\/FLASHPluginConfig.h\"><strong>FLASHPluginConfig.h<\/strong><\/a> file defining the <strong><span class=\"pl-en\">MINIMUM_PROGRAMMED_BLOCK_SIZE<\/span> <\/strong>macro. You can copy <strong><span class=\"pl-en\">FLASH_<\/span>xxx<\/strong> definitions from the original example.<\/li>\n<li>Optionally, call <strong>TestFLASHProgramming()<\/strong> from <strong>main()<\/strong> to test the programming logic in a debuggable environment.<\/li>\n<\/ol>\n<p>You can find complete plugin implementations for the i.MXRT1050 and i.MXRT1064 devices in our <a href=\"https:\/\/github.com\/sysprogs\/flash_drivers\/tree\/master\/imxrt\">GitHub repository<\/a>.<\/li>\n<li>After the restructuring is complete, try setting a breakpoint at the call to <strong>FLASHPlugin_InitDone()<\/strong> and debugging the project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/12-refactored.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7230\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/12-refactored.png\" alt=\"\" width=\"1190\" height=\"841\" \/><\/a><\/li>\n<li>The TestFLASHProgramming() function will automatically erase and program the first page of the FLASH memory using your implementations of <strong>FLASHPlugin_EraseSectors()<\/strong> and <strong>FLASHPlugin_DoProgramSync(). <\/strong>You can use it to verify that the memory gets programmed as expected:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/13-program.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7231\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/13-program.png\" alt=\"\" width=\"1190\" height=\"841\" \/><\/a><\/li>\n<li>Now that the plugin is ready, open the VisualGDB Embedded Project Wizard again and create another project based on the <strong>iled_blinky<\/strong> example: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/14-blink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7232\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/14-blink.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>This project will run from FLASH. In order to make OpenOCD program the FLASH memory, add the following command just before the &#8220;-c init&#8221; command:\n<pre class=\"\">flash bank imxrt plugin $FLASH_MEMORY_BASE 0 0 0 0 $(ProjectDir.forwardslashes)\/IMXRT1050_FLASH<\/pre>\n<p>Then, copy the ELF file of the built FLASH plugin (e.g. <strong>&lt;projects&gt;\\IMXRT1050_FLASH\\build\\VisualGDB\\Debug\\IMXRT1050_FLASH<\/strong>) to the directory of the new project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/15-driver.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7233\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/15-driver.png\" alt=\"\" width=\"967\" height=\"702\" \/><\/a><\/li>\n<li>When you start a debug session now, OpenOCD will automatically do the following:\n<ol>\n<li>Reset the device and let the boot ROM initialize the peripherals<\/li>\n<li>Load the FLASH plugin into the RAM<\/li>\n<li>Use the FLASH plugin to erase and program the memory (note that due to the way OpenOCD implements FLASH drivers, the plugin will get unloaded and loaded again between the erase and program operations).<\/li>\n<li>If the currently debugged project contained any RAM sections, OpenOCD would load them after unloading the FLASH plugin. In either case, the FLASH plugin will be completely unloaded before the application gets a chance to run and will never collide with it.<\/li>\n<li>Set the $pc register to the application&#8217;s entry point and let it run.<\/li>\n<\/ol>\n<p>As a result, the application you are debugging will seamlessly get programmed into FLASH and you will be able to debug it. You can use the &#8220;Verify FLASH memory contents&#8221; button to ensure all sections have been programmed correctly:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/16-programmed.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-7234\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2021\/03\/16-programmed.png\" alt=\"\" width=\"1190\" height=\"841\" \/><\/a><\/li>\n<\/ol>\n<p>&nbsp;<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to debug the i.MXRT devices and program their FLASH memory using OpenOCD. We will show how<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[89],"tags":[53,178,207],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7218"}],"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=7218"}],"version-history":[{"count":4,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7218\/revisions"}],"predecessor-version":[{"id":7238,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/7218\/revisions\/7238"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=7218"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=7218"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=7218"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}