{"id":6397,"date":"2020-07-01T17:55:36","date_gmt":"2020-07-02T00:55:36","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=6397"},"modified":"2022-03-14T08:20:03","modified_gmt":"2022-03-14T15:20:03","slug":"observing-itm-trace-output-from-arm-targets-with-segger-j-link","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/tutorials\/arm\/itm\/","title":{"rendered":"Observing ITM Trace Output from ARM Targets with Segger J-Link"},"content":{"rendered":"<p>This tutorial shows how to configure VisualGDB to view the debug output produced by ARM targets via the <strong><span class=\"pl-c1\">ITM_SendChar<\/span>()<\/strong> function. We will create a basic project for the nRF52840 device using Segger J-Link and will show how to configure VisualGDB to view the ITM output.<\/p>\n<p>ITM is a mechanism that allows sending arbitrary text directly to the debugger, reusing the regular JTAG\/SWD interface. It is supported by most ARM targets and works reliably with Segger J-Link probes when using the J-Link software. It is also theoretically supported by OpenOCD, however works less reliable.<\/p>\n<p>Note that for most scenarios, we recommend using our <a href=\"https:\/\/visualgdb.com\/tutorials\/arm\/semihosting\/\">Fast Semihosting<\/a> mechanism instead. It relies on background memory reads and works much faster than ITM, or any other tracing mechanisms.<\/p>\n<ol>\n<li>Start Visual Studio and select the VisualGDB Embedded Project Wizard. Then pick the name and location of the project:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/01-newprj.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6398\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/01-newprj.png\" alt=\"\" width=\"966\" height=\"624\" \/><\/a><\/li>\n<li>Proceed with creating a new embedded binary using MSBuild:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/02-msbuild.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6399\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/02-msbuild.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>On the next page select your toolchain and device. ITM tracing will work with most ARM-based targets. In this tutorial we will use the Nordic nRF52840 device, as its evaluation board includes an on-board J-Link debug probe:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/03-nordic.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6400\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/03-nordic.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Pick a sample project to clone. In this tutorial we will use the basic &#8220;<strong>LEDBlink (BSP)<\/strong>&#8221; sample: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/04-blink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6401\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/04-blink.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a><\/li>\n<li>Finally, choose the debug settings that work with your board. The ITM only works reliably with Segger J-Link, so make sure you are using the J-Link software:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/05-jlink.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6402\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/05-jlink.png\" alt=\"\" width=\"886\" height=\"693\" \/><\/a>For other debug methods, consider using the <a href=\"https:\/\/visualgdb.com\/tutorials\/arm\/semihosting\/\">Fast Semihosting<\/a> instead.<\/li>\n<li>Press &#8220;Finish&#8221; to generate a project based on the sample. Then add the following function to the main file and call it from <strong>main()<\/strong>:\n<pre class=\"\">static void ITMPrint(const char *pString)\r\n{\r\n    for (const char *p = pString; *p; p++)\r\n        ITM_SendChar(*p);\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/06-itmprint.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6403\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/06-itmprint.png\" alt=\"\" width=\"1075\" height=\"746\" \/><\/a><\/li>\n<li>If you just start debugging the project, the<strong> ITMPrint()<\/strong> function will work, however the output it produces will not be shown anywhere:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/07-noout.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6404\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/07-noout.png\" alt=\"\" width=\"1075\" height=\"746\" \/><\/a><\/li>\n<li>To enable reading of the ITM messages, run the <a href=\"https:\/\/wiki.segger.com\/How_to_use_SWO_with_GDB\">SWO EnableTarget<\/a> command in the GDB session window:\n<pre class=\"\">monitor SWO EnableTarget 0 0 1 0<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/08-swo.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6405\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/08-swo.png\" alt=\"\" width=\"1075\" height=\"746\" \/><\/a><\/li>\n<li>Now you can connect to the port <strong>2332<\/strong> on localhost using telnet to see the output from printf. You can find out the exact port number (normally, <strong>2332<\/strong>) in the J-Link window:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/port-1.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6411\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/port-1.png\" alt=\"\" width=\"1075\" height=\"746\" \/><\/a>Note that if you are using VisualGDB 5.5 or later, the output from <strong>JLinkGDBServerCL<\/strong> will be shown as one of the tabs inside the generic <strong>VisualGDB Output<\/strong> window that can be opened via a command under <strong>Debug-&gt;Windows<\/strong>.<\/li>\n<li>To make the ITM output appear in VisualGDB GUI, add the &#8220;monitor SWO EnableTarget 0 0 1 0&#8221; command to the post-target GDB commands: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/09-command.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6406\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/09-command.png\" alt=\"\" width=\"980\" height=\"625\" \/><\/a><\/li>\n<li>Then enable the raw terminal (Custom edition and higher) to connect to that port: <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/10-term.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6407\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/10-term.png\" alt=\"\" width=\"980\" height=\"625\" \/><\/a><\/li>\n<li>Now you will see the output from <strong>ITM_SendChar()\u00a0<\/strong>directly in Visual Studio: \u00a0 <a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/11-hello.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6408\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/11-hello.png\" alt=\"\" width=\"1075\" height=\"746\" \/><\/a><\/li>\n<li>If the output from the Segger J-Link does not match the characters passed to <strong>ITM_SendChar()<\/strong>, the automatic detection of the CPU and SWO frequencies may not be working (or the CPU frequency could be changed after it was detected). In this case you may need to specify the CPU and SWO frequency explicitly in the &#8220;monitor SWO EnableTarget&#8221; command as shown on <a href=\"https:\/\/wiki.segger.com\/J-Link_GDB_Server#SWO_EnableTarget\">this page<\/a>.<\/li>\n<li>You can also use the regular <strong>printf() <\/strong>call as long as you define a <strong>_write()<\/strong> function somewhere in your code:\n<pre class=\"\">extern \"C\" int _write(int fd, char *pBuffer, int size)\r\n{\r\n    for (int i = 0; i &lt; size; i++)\r\n        ITM_SendChar(pBuffer[i]);\r\n    return size;\r\n}<\/pre>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/12-leds.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-6409\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2020\/07\/12-leds.png\" alt=\"\" width=\"1075\" height=\"746\" \/><\/a><\/li>\n<\/ol>\n","protected":false},"excerpt":{"rendered":"<p>This tutorial shows how to configure VisualGDB to view the debug output produced by ARM targets via the ITM_SendChar() function.<\/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":[],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6397"}],"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=6397"}],"version-history":[{"count":5,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6397\/revisions"}],"predecessor-version":[{"id":7806,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/6397\/revisions\/7806"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=6397"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=6397"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=6397"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}