{"id":8203,"date":"2023-07-23T09:36:05","date_gmt":"2023-07-23T16:36:05","guid":{"rendered":"https:\/\/visualgdb.com\/w\/?p=8203"},"modified":"2023-07-26T13:12:10","modified_gmt":"2023-07-26T20:12:10","slug":"semihosting-and-standard-output-for-embedded-projects","status":"publish","type":"post","link":"https:\/\/visualgdb.com\/documentation\/semihosting\/","title":{"rendered":"Semihosting and Standard Output for Embedded Projects"},"content":{"rendered":"<p>This page describes how embedded projects handle standard output functions like <strong>printf() <\/strong>or <strong>puts()<\/strong>, and shows the relevant VisualGDB settings that control the behavior in this scenario.<\/p>\n<h1>Contents<\/h1>\n<ul>\n<li><a href=\"#overview\">Overview<\/a><\/li>\n<li><a href=\"#printf\">printf()<\/a><\/li>\n<li><a href=\"#write\">_write()<\/a>\n<ul>\n<li><a href=\"#toolchain\">Toolchain-supplied<\/a><\/li>\n<li><a href=\"#fastsemihosting\">Fast semihosting<\/a><\/li>\n<li><a href=\"#application\">Application-supplied<\/a><\/li>\n<\/ul>\n<\/li>\n<li><a href=\"#troubleshooting\">Troubleshooting<\/a>\n<ul>\n<li><a href=\"#undefined\">Undefined reference to _write()<\/a><\/li>\n<li><a href=\"#multiple\">Multiple definition of _write()<\/a><\/li>\n<li><a href=\"#notimpl\">&lt;symbol&gt; is not implemented and will always fail<\/a><\/li>\n<\/ul>\n<\/li>\n<\/ul>\n<h2><a id=\"overview\"><\/a>Overview<\/h2>\n<p>Assume that you are running the following code on an STM32 device:<\/p>\n<pre class=\"\">for (int i = 1;;i++)\r\n{\r\n    printf(\"Iteration %d, value = %f\\n\", i, i * 0.1F);\r\n}<\/pre>\n<p>Each time the <strong>printf()<\/strong> function gets invoked, the following events take place:<\/p>\n<ol>\n<li>The <strong>printf()<\/strong> implementation provided by newlib processes the format string and substitutes the values provided as arguments.<\/li>\n<li>It then calls the <strong>_write()<\/strong> function to physically output the formatted string\u00a0(e.g. <strong>&#8220;Iteration 1, value = 0.1\\n&#8221;<\/strong>).<\/li>\n<\/ol>\n<p>This separation is needed because the actual <strong>printf()<\/strong> logic is the same on every device you run it on, as long as they share the same CPU &#8211; translating &#8220;<strong>Iteration %d<\/strong>&#8221; to &#8220;<strong>Iteration 1<\/strong>&#8221; does not depend on whether the output is going to UART, USB or semihosting. The <strong>_write()<\/strong> function, in turn, doesn&#8217;t know how the written data was produced, and just outputs it &#8220;<strong>as is<\/strong>&#8221; to the destination.<\/p>\n<h2><a id=\"printf\"><\/a>The printf() implementation<\/h2>\n<p>The <strong>printf()<\/strong> function is implemented in the Newlib library (<a href=\"https:\/\/github.com\/bminor\/newlib\/blob\/master\/newlib\/libc\/stdio\/printf.c\">printf.c<\/a>) which is included in the <a href=\"https:\/\/developer.arm.com\/Tools%20and%20Software\/GNU%20Toolchain\">ARM toolchain<\/a>. To allow choosing between size and functionality, the ARM toolchain comes with 3 versions of <strong>printf()<\/strong>:<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 33.3333%;\">Version<\/td>\n<td style=\"width: 33.3333%;\">Floating Point support<\/td>\n<td style=\"width: 33.3333%;\">Size<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%;\">Regular (non-nano)<\/td>\n<td style=\"width: 33.3333%;\">Yes<\/td>\n<td style=\"width: 33.3333%;\">Largest<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%;\">Newlib-nano with FP support<\/td>\n<td style=\"width: 33.3333%;\">Yes<\/td>\n<td style=\"width: 33.3333%;\">Smaller<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 33.3333%;\">Newlib-nano<\/td>\n<td style=\"width: 33.3333%;\">No<\/td>\n<td style=\"width: 33.3333%;\">Smallest<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>The exact version to use can be selected via <strong>VisualGDB Project Properties -&gt; Embedded Project -&gt; C Library Type<\/strong>:<\/p>\n<p><a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/07\/prntf.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8205\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/07\/prntf.png\" alt=\"\" width=\"1013\" height=\"590\" \/><\/a>On the low level, this setting changes the specs file (e.g. <strong>&#8211;specs=nano.specs<\/strong>) passed to the linker. You can see the exact flags used in each case by looking at the <strong>&lt;toolchain directory&gt;\\toolchain.xml<\/strong> file.<\/p>\n<h2><a id=\"write\"><\/a>_write() implementations<\/h2>\n<p>Once the <strong>printf()<\/strong> function has completed formatting the string, it calls the <strong>_write()<\/strong> function to physically output the data to its destination. <strong>_write()<\/strong> is typically taken from one of the following places:<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 50%;\">Implementation<\/td>\n<td style=\"width: 50%;\">Destination<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Toolchain itself<\/td>\n<td style=\"width: 50%;\">Regular (slow) semihosting<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Fast Semihosting Framework<\/td>\n<td style=\"width: 50%;\">Fast Semihosting<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Application<\/td>\n<td style=\"width: 50%;\">Application-defined (e.g. UART)<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<h3><a id=\"toolchain\"><\/a>Toolchain-supplied _write()<\/h3>\n<p>The ARM toolchain itself can provide one of the 2 implementations of <strong>_write()<\/strong> and other similar functions that can be selected via <strong>VisualGDB Project Properties -&gt; Embedded Project -&gt; Implementations for _sbrk(), etc<\/strong>:<\/p>\n<table style=\"border-collapse: collapse; width: 100%;\" border=\"1\">\n<tbody>\n<tr>\n<td style=\"width: 50%;\">Setting<\/td>\n<td style=\"width: 50%;\">Effect<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">None<\/td>\n<td style=\"width: 50%;\">Calling <strong>printf()<\/strong> results in a link-time error<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Minimal (no semihosting)<\/td>\n<td style=\"width: 50%;\">Output of <strong>printf()<\/strong> is ignored<\/td>\n<\/tr>\n<tr>\n<td style=\"width: 50%;\">Support semihosting<\/td>\n<td style=\"width: 50%;\">Output of <strong>printf()<\/strong> routed to regular semihosting<\/td>\n<\/tr>\n<\/tbody>\n<\/table>\n<p>Toolchain-supplied implementations for <strong>_write()<\/strong> and other similar functions are declared as weak, i.e. enabling any other implementations shown below will automatically override them without causing any error.<\/p>\n<h3><a id=\"fastsemihosting\"><\/a>Fast Semihosting<\/h3>\n<p>As the regular semihosting is very slow (requires stopping the target after outputting each line), VisualGDB provides its own fast <a href=\"https:\/\/visualgdb.com\/tutorials\/arm\/semihosting\/\">semihosting mechanism<\/a>. It comes with its own implementation of <strong>_write()<\/strong> that can redirect <strong>printf()<\/strong> output to the fast semihosting mechanism. It can be enabled by referencing the <strong>Fast Semihosting and Embedded Profiler<\/strong> framework and checking &#8220;<strong>Redirect printf() to fast semihosting<\/strong>&#8221; (enabled by default):<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/07\/semihost.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8207\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/07\/semihost.png\" alt=\"\" width=\"1013\" height=\"590\" \/><\/a><\/p>\n<h3><a id=\"application\"><\/a>Application-supplied _write()<\/h3>\n<p>The application can provide its own implementation of <strong>_write()<\/strong> by using the template below (<strong>extern &#8220;C&#8221;<\/strong> is only needed if it&#8217;s located in a C++ file):<\/p>\n<pre class=\"\">extern \"C\" int _write(int fd, char *pBuffer, int size)\r\n{\r\n}<\/pre>\n<p>It would be typically located in one of the source files and will be automatically called by <strong>printf()<\/strong> with the relevant data and can output it to an arbitrary location (UART, USB, network, internal circular buffer, etc). You can use <a href=\"https:\/\/visualgdb.com\/documentation\/codeexplorer\/globals\/\">Code Explorer<\/a> to quickly locate the exact source file implementing it.<\/p>\n<h2><a id=\"troubleshooting\"><\/a>Troubleshooting<\/h2>\n<p>If the <strong>printf()<\/strong> function is not working as expected, you can check the map file (&lt;Project name&gt;.map) to find out which version of <strong>_write()<\/strong> was built into the application:<\/p>\n<pre class=\"\">.text           0x08000190     0x1eec\r\n                0x08000190                . = ALIGN (0x4)\r\n                0x08000190                _stext = .\r\n  *(.text*)\r\n.text._write   0x08001fa0       0x10 c:\/sysgcc\/arm-eabi\/&lt;...&gt;\\libnosys.a(write.o)\r\n                0x08001fa0                _write<\/pre>\n<p>In this example, it used <strong>_write()<\/strong> from <strong>libnosys.a<\/strong>, that corresponds to the &#8220;No semihosting&#8221; setting and discards all output.<\/p>\n<h3><a id=\"undefined\"><\/a>Undefined reference to _write()<\/h3>\n<p>This error happens when the code uses <strong>_printf()<\/strong> and has not enabled either of the <strong>_write()<\/strong> implementations. You can resolve it by checking the settings shown above and enabling one of them.<\/p>\n<h3><a id=\"multiple\"><\/a>Multiple definition of _write()<\/h3>\n<p>This error happens when the program contains multiple implementations of <strong>_write()<\/strong> (e.g. one defined in the application, and another one in the fast semihosting library). You can resolve it by choosing the implementation to use and disabling the extra ones.<\/p>\n<p>If you need the Fast Semihosting framework, but do not want to use its implementation of <strong>_write()<\/strong>, you can uncheck the &#8220;<strong>redirect printf() to fast semihosting<\/strong>&#8221; option shown below:<a href=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/07\/semihost.png\"><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-8207\" src=\"https:\/\/visualgdb.com\/w\/wp-content\/uploads\/2023\/07\/semihost.png\" alt=\"\" width=\"1013\" height=\"590\" \/><\/a><\/p>\n<h3><a id=\"notimpl\"><\/a>&lt;symbol&gt; is not implemented and will always fail<\/h3>\n<p>This warning is new in the 12.2 ARM toolchain and comes from the <strong>libnosys.a<\/strong> library. Each time you link your application with a version of system call from that library (e.g. <strong>_getpid()<\/strong>), the linker now shows a warning, even if it ends up discarding that system call later.<\/p>\n<p>These warnings do not indicate a problem (unless you are specifically trying to use one of the functions mentioned there) and can be safely ignored. They only indicate that this system call is a stub that always just returns an error code and doesn&#8217;t do anything else.<\/p>\n<p>If you would like to completely remove the warnings, you would need to patch the toolchain as shown below:<\/p>\n<ol>\n<li>Determine the exact <strong>libnosys.a<\/strong> file used by your application:\n<ol style=\"list-style-type: lower-alpha;\">\n<li>Check if the warning messages mention the path of any other <strong>.a<\/strong> file from the toolchain (e.g. if the warnings mention <strong>c:\/sysgcc\/arm-eabi\/bin\/..\/lib\/gcc\/arm-none-eabi\/12.2.1\/thumb\/v7e-m+fp\/hard\\libc_nano.a<\/strong>, the <strong>libnosys.a<\/strong> will be located in the same directory as <strong>libc_nano.a<\/strong>).<\/li>\n<li>If not, check the map file as shown <a href=\"#troubleshooting\">here<\/a><\/li>\n<\/ol>\n<\/li>\n<li>Make a backup copy of the <strong>libnosys.a <\/strong>file in case the next step damages it.<\/li>\n<li>Run the following command on the <strong>libnosys.a<\/strong> file:\n<pre class=\"\">arm-none-eabi-objcopy --remove-section \".gnu.warning.&lt;symbolN&gt;\" libnosys.a<\/pre>\n<p>Replace &lt;symbolN&gt; with the name of the symbols shown in the warnings (e.g. if the warning says &#8220;<strong>_fstat is not implemented and will always fail&#8221;<\/strong>, the section to remove is &#8220;<strong>.gnu.warning._fstat<\/strong>&#8220;). You can have multiple <strong>&#8211;remove-section &#8220;&lt;name&gt;&#8221;<\/strong> arguments in the same invocation of <strong>objcopy<\/strong>.<br \/>\nThis will remove the warning messages from the file, so the linker will no longer show them.<\/li>\n<\/ol>\n<p>You can also patch all versions of <strong>libnosys.a<\/strong> by first dumping the list of all files into a batch file (<strong>dir \/s \/b libnosys.a &gt; strip.bat<\/strong>) and then doing a regex-based find-and-replace with Notepad++ (e.g. <strong>(.*) =&gt; arm-none-eabi-objcopy &#8211;remove-section &#8220;.gnu.warning._close&#8221; \\1<\/strong>).<\/p>\n","protected":false},"excerpt":{"rendered":"<p>This page describes how embedded projects handle standard output functions like printf() or puts(), and shows the relevant VisualGDB settings<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"closed","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[197],"tags":[168],"_links":{"self":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8203"}],"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=8203"}],"version-history":[{"count":10,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8203\/revisions"}],"predecessor-version":[{"id":8220,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/posts\/8203\/revisions\/8220"}],"wp:attachment":[{"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/media?parent=8203"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/categories?post=8203"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/visualgdb.com\/w\/wp-json\/wp\/v2\/tags?post=8203"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}