{"id":4184,"date":"2022-01-26T13:31:11","date_gmt":"2022-01-26T12:31:11","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4184"},"modified":"2025-12-27T15:53:40","modified_gmt":"2025-12-27T14:53:40","slug":"semihosting-on-stm32-as-an-interesting-option-for-debugging","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/semihosting-on-stm32-as-an-interesting-option-for-debugging\/","title":{"rendered":"Semihosting on STM32 as an Interesting Option for Debugging"},"content":{"rendered":"\n<p class=\"wp-block-paragraph\">If we think about debugging, what comes to mind? Breakpoints, stepping through code, but above all printing. When dealing with microcontrollers, most often we send messages to the serial console terminal on the PC. We use one of the UART interfaces for this. What if we don\u2019t have that UART? There\u2019s one clever mechanism. It\u2019s called Semihosting.<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">What is Semihosting on STM32?<\/h1>\n\n\n\n<p class=\"wp-block-paragraph\">It is <strong>one of the available debugging methods<\/strong> for programs on a microcontroller. The mechanisms used for this are<strong> built into the<\/strong> ARM cores. So semihosting is available not only on STM32.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The idea is to replace standard input and output on the microcontroller. In our systems we have neither a screen with a console nor a keyboard. However, that doesn\u2019t mean we can\u2019t use them.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Semihosting allows you to <strong>use your computer\u2019s resources as standard input and output<\/strong> for the microcontroller. What resources? The console and the keyboard.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">All of this happens thanks to <strong>special instructions<\/strong> in the microcontroller that trigger system exceptions (e.g., the SVC instruction \u2013 SuperVisor Call). <strong>Such an exception is intercepted by appropriate functions and the hardware debugger.<\/strong> It can now redirect data from the microcontroller <strong>straight to our computer and vice versa<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">On the PC side, this is received by the software that started debugging the code on the microcontroller. It provides the console and keyboard for use precisely through this \u201ctunnel\u201d.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Required microcontroller pins<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Now the best part. Which microcontroller pins are used for such communication?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Exactly the same ones as in \u201cclassic\u201d debugging. <strong>These are SWCLK and SWDIO.<\/strong> Nothing more!<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>We don\u2019t have to change the hardware configuration.<\/strong> Heck! We don\u2019t have to \u201cwaste\u201d a UART interface just to print something to the console for debugging purposes.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>This is a huge advantage of Semihosting.<\/strong> UART eats 2 pins, and SWV one \u2013 SWO. If you have a constrained project where you don\u2019t have any free pins, you already have an \u201cinterface\u201d for printing logs from the program\u2019s operation.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So let\u2019s move on to configuring this Semihosting.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Test platform<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">As a test board I used the <a href=\"https:\/\/sklep.msalamon.pl\/?s=stm32u5&amp;post_type=product&amp;dgwt_wcas=1&amp;&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=semihosting&amp;utm_content=Text\"><strong>Discovery B-U585I-IOT02A<\/strong><\/a> kit. It\u2019s a board with the newest baby from STMicroelectronics, i.e. <strong>STM32U5<\/strong>. <a href=\"https:\/\/msalamon.pl\/nowa-rodzina-mikrokontrolerow-do-iot-stm32u5\/\">I recently wrote about their capabilities.<\/a><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Currently I\u2019m using this platform on <strong>Live Streams<\/strong>, which I run regularly <strong>on Tuesdays at 18:00 on my <a href=\"https:\/\/www.youtube.com\/c\/msalamon\" target=\"_blank\" rel=\"noopener\">YouTube<\/a><\/strong> (the content is in Polish).<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Most important info!&nbsp;<\/strong>This method is identical for all STM32 microcontrollers (and not only them). If you have a different chip, everything will look the same.<\/p>\n\n\n\n<figure class=\"wp-block-image size-large is-style-default\"><a href=\"https:\/\/sklep.msalamon.pl\/?s=stm32u5&amp;post_type=product&amp;dgwt_wcas=1&amp;&amp;utm_source=blog&amp;utm_medium=article&amp;utm_campaign=semihosting&amp;utm_content=Text\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"341\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/12\/STM32U5-baner-1024x341.png\" alt=\"\" class=\"wp-image-2032\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/12\/STM32U5-baner-1024x341.png 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/12\/STM32U5-baner-300x100.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/12\/STM32U5-baner-768x256.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/12\/STM32U5-baner.png 1200w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">Configuring Semihosting on STM32<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Let\u2019s get to the specifics. How do you set up Semihosting on STM32? There are a few steps.<\/p>\n\n\n\n<h4 class=\"wp-block-heading\">1. The right software debugger<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">You need to choose the right debugger on the computer side. <strong>That will be OpenOCD.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Unfortunately, <strong>the default ST-Link GDB does not support<\/strong> Semihosting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You set the debugging configuration during the first debug run. If you\u2019ve already done it, under the bug icon you have <em><strong>Debug Configurations<\/strong><\/em>.<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_debug_config.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"566\" height=\"255\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_debug_config.jpg\" alt=\"\" class=\"wp-image-2055\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_debug_config.jpg 566w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_debug_config-300x135.jpg 300w\" sizes=\"auto, (max-width: 566px) 100vw, 566px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Now, as <em><strong>Debug Probe&nbsp;<\/strong><\/em><strong>set ST-Link (OpenOCD).<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_openocd.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"593\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_openocd-1024x593.jpg\" alt=\"\" class=\"wp-image-2056\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_openocd-1024x593.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_openocd-300x174.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_openocd-768x445.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_openocd.jpg 1157w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">2. Enabling an external library via the linker<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">For the program to know how to use, for example, system exceptions in order to use Semihosting, you need to include an external library. It\u2019s a precompiled library, so you do it only <strong>at the linker stage<\/strong>.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you enter parameters manually, then <strong>add to the linker options<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">-l rdimon --specs=rdimon.specs<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">If, like me, you use STM32CubeIDE, then add it in the appropriate linker options:<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Project &gt; Properties &gt; C\/C++ Build &gt; Settings &gt; MCU GCC Linker<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">In <strong>Libraries<\/strong> add <strong><em>rdimon.<\/em><\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_lib.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"532\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_lib-1024x532.jpg\" alt=\"\" class=\"wp-image-2053\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_lib-1024x532.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_lib-300x156.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_lib-768x399.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_lib.jpg 1213w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">In <strong>Miscellaneous<\/strong> enter:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">-specs=rdimon.specs<\/pre>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_misc.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"1024\" height=\"532\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_misc-1024x532.jpg\" alt=\"\" class=\"wp-image-2054\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_misc-1024x532.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_misc-300x156.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_misc-768x399.jpg 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_linker_misc.jpg 1213w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">3. Excluding syscalls.c from compilation<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">STM32CubeMX generates a <strong>default syscalls.c file<\/strong>. It contains <strong>empty system call functions.<\/strong> They\u2019re there for us to use if we wanted to write something ourselves, e.g. semihosting or something similar.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">We most likely won\u2019t do that ourselves. Additionally, the same functions are included externally via what we attached to the linker.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There will be a clash. That means the compiler may tell us that we have some duplicate definitions. <strong>You need to exclude this file from compilation.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You could delete it, but\u2026 it will come back after regenerating files with CubeMX. <strong>You need to exclude it completely.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Right-click on this file &gt; Properties &gt; check the box \u201cExclude resource from build\u201d<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_syscall_exclude..jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"813\" height=\"285\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_syscall_exclude..jpg\" alt=\"\" class=\"wp-image-2058\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_syscall_exclude..jpg 813w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_syscall_exclude.-300x105.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_syscall_exclude.-768x269.jpg 768w\" sizes=\"auto, (max-width: 813px) 100vw, 813px\" \/><\/a><\/figure>\n\n\n\n<h4 class=\"wp-block-heading\">4. Initialization in the microcontroller program<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">We\u2019ve already configured everything on the microcontroller side. Now in our program it remains to <strong>call the initialization function<\/strong> for Semihosting\u2014just like we initialize any interface before using it.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">This is done with the function:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">initialise_monitor_handles();<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">It\u2019s enough to <strong>add it in main before the main loop.<\/strong> We can do this even before initializing HAL. Then we\u2019ll be able to send something to the console even before the whole HAL comes up.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">So that the compiler doesn\u2019t complain that it doesn\u2019t know it, <strong>you must add its prototype<\/strong> with an extern annotation (in the rdimon library) somewhere at the top of the file.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">extern void initialise_monitor_handles(void);<\/pre>\n\n\n\n<h4 class=\"wp-block-heading\">5. Enabling semihosting when starting debugging<\/h4>\n\n\n\n<p class=\"wp-block-paragraph\">On the microcontroller side we\u2019re done. Let\u2019s finish the PC side.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Here, similarly to STM32<strong> you need to initialize Semihosting.<\/strong> This is done <strong>at the moment debugging starts<\/strong>, i.e. when launching the OpenOCD session. You need to give it a command so it knows that we\u2019re semihosting.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You need to <strong>go back into the debug session settings<\/strong> of your project. This time, what we\u2019re interested in is in the Startup tab. There is a field <strong>\u201cInitialization Commands\u201d.<\/strong> These commands will be executed when bringing up the debug session.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Enter here:<\/strong><\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">monitor arm semihosting enable<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">You now have everything you need to use Semihosting!<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">How to use Semihosting?<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">We\u2019re done with the configuration, so how do we use this mechanism?<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>If you don\u2019t have it, you must include the &lt;stdio.h&gt; file in your project.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">If you did everything the way I described, then now you simply <em><strong>use the printf function<\/strong><\/em>.&nbsp;<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">There is only one important rule. <strong>Every message sent via Semihosting must end with the \u2018\\n\u2019 character.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Just as if you were printing to the console on a PC, now you print from the microcontroller. Where will these strings go? To the console from which OpenOCD was launched. If you did it in STM32CubeIDE, it\u2019s the console at the bottom.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int main(void)\n{\n  \/* USER CODE BEGIN 1 *\/\n\tinitialise_monitor_handles();\n\n\tprintf(\"Semihosting test\\n\");\n  \/* USER CODE END 1 *\/<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">As you can see, I inserted the Semihosting code right after entering main and immediately want to print something. What will be the effect?<\/p>\n\n\n\n<figure class=\"wp-block-image\"><a href=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_printf.jpg\"><img loading=\"lazy\" decoding=\"async\" width=\"997\" height=\"356\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_printf.jpg\" alt=\"\" class=\"wp-image-2062\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_printf.jpg 997w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_printf-300x107.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_printf-768x274.jpg 768w\" sizes=\"auto, (max-width: 997px) 100vw, 997px\" \/><\/a><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">It works. My test string appeared in the console.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Note that among the red messages from OpenOCD we got <em><strong>\u201csemihosting is enabled\u201d<\/strong><\/em>. That means everything is fine.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>I also said we can use our PC keyboard, right?<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The scanf(\u2026) function reads standard input, i.e. what we type into the console. It is a blocking function and waits for Enter from the keyboard.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">By adding these lines to the program:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int main(void)\n{\n  \/* USER CODE BEGIN 1 *\/\n\tint32_t Value;\n\n\tinitialise_monitor_handles();\n\n\tprintf(\"Semihosting test\\n\");\n\n\tprintf(\"Type a integer: \\n\");\n\tscanf(\"%ld\", &amp;Value);\n\tprintf(\"You typed %ld\\n\", Value);\n\n  \/* USER CODE END 1 *\/<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">We get a program flow that requires user interaction. The program stops and waits for you to provide it with an integer in the console. Don\u2019t forget Enter! <strong>The text we type from the keyboard has a greenish-turquoise color.<\/strong><\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"761\" height=\"305\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_scanf.jpg\" alt=\"\" class=\"wp-image-2064\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_scanf.jpg 761w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_scanf-300x120.jpg 300w\" sizes=\"auto, (max-width: 761px) 100vw, 761px\" \/><\/figure>\n\n\n\n<h2 class=\"wp-block-heading\">File operations<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Using this approach we can not only use the console, but also <strong>files on our computer!<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">The following functions are used for this:<\/p>\n\n\n\n<ul class=\"wp-block-list\">\n<li>fopen() \u2013 opens a file<\/li>\n\n\n\n<li>fprintf() \u2013 writes to a file<\/li>\n\n\n\n<li>fscanf() \u2013 reads from a file<\/li>\n\n\n\n<li>fclose() \u2013 closes a file<\/li>\n<\/ul>\n\n\n\n<p class=\"wp-block-paragraph\">There are more functions in stdio.h, but these are the most important.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can provide the file path relatively\u2014then it refers to the location from which the program is run.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also provide it as an absolute path. You use paths from your computer. <strong>Just don\u2019t point to drive C<\/strong>, because you\u2019ll run into administrator permissions and the MCU will end up in <strong>Hard Fault<\/strong> \ud83d\ude42<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Example:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW EnlighterJSRAW\" data-enlighter-language=\"generic\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">int main(void)\n{\n  \/* USER CODE BEGIN 1 *\/\n\tFILE *FilePtr;\n\n\tinitialise_monitor_handles();\n\n\tFilePtr = fopen(\"d:\\\\semi\\\\test.txt\", \"w\");\n\n\tfprintf(FilePtr, \"Test semihosting\");\n\n\tfclose(FilePtr);\n  \/* USER CODE END 1 *\/<\/pre>\n\n\n\n<p class=\"wp-block-paragraph\">The program is supposed to open a file (create it if it doesn\u2019t exist), write text, and close it. <strong>Always remember to close files after using them!<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Running such a program with the path I provided, I got a new file \ud83d\ude42<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"863\" height=\"271\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_file..jpg\" alt=\"\" class=\"wp-image-2066\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_file..jpg 863w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_file.-300x94.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_file.-768x241.jpg 768w\" sizes=\"auto, (max-width: 863px) 100vw, 863px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\">Inside, of course, was what I wrote in the microcontroller program.<\/p>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><img loading=\"lazy\" decoding=\"async\" width=\"321\" height=\"149\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_file_inside.jpg\" alt=\"\" class=\"wp-image-2067\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_file_inside.jpg 321w, https:\/\/msalamon.pl\/wp-content\/uploads\/2022\/01\/semihosting_file_inside-300x139.jpg 300w\" sizes=\"auto, (max-width: 321px) 100vw, 321px\" \/><\/figure>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>I see potential here in the \u201cother direction\u201d, i.e. from a file on the PC to the microcontroller.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can write some algorithm on the microcontroller, and inject test data from a file on the computer! This can have huge applications.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Summary<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">Semihosting is <strong>a very interesting alternative to debugging via printing.<\/strong> It allows us to <strong>replace UART.<\/strong> It makes it much easier to implement things like connecting a keyboard or pulling data from a file on the computer.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">I didn\u2019t mention anything about the <strong>downsides<\/strong>, and I think it <strong>has one important one.<\/strong> This solution <strong>is very slow.<\/strong> Try running printing in a loop without any delay and you\u2019ll see that there isn\u2019t such a storm of characters as, for example, with UART.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">For this reason <strong>Semihosting won\u2019t be suitable where high log throughput speed is required.<\/strong> However, these will be specific use cases. <strong>There\u2019s no need to demonize this speed.<\/strong> For learning or a simple project, it may turn out that this speed is sufficient.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">You can also introduce a logging level and, for example, send only more important messages or only those you currently need.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>Among the advantages, I would definitely mention the minimal number of pins needed for operation.<\/strong> You could say it\u2019s zero, because you always have the debugger connected anyway.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">STM32 Course for Beginners<\/h2>\n\n\n\n<p class=\"wp-block-paragraph\">As early as <strong>February 16 the best STM32 programming course for Beginners returns!<\/strong> This is already the fourth edition! (the course content is in Polish)<\/p>\n\n\n\n<p class=\"wp-block-paragraph\">It\u2019s a <strong>complete A-to-Z program<\/strong> in which you will learn STM32 microcontroller programming. You will get to know its interfaces and <strong>you will be able to use them correctly and in a non-blocking way.<\/strong><\/p>\n\n\n\n<p class=\"wp-block-paragraph\">Don\u2019t miss the chance! The next edition will probably be only in the second half of 2022.<\/p>\n\n\n\n<p class=\"wp-block-paragraph\"><strong>So far, over 470 people have taken part in the course!<\/strong><\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Sign up for the waiting list at <a href=\"https:\/\/kursstm32.pl\/\" target=\"_blank\" rel=\"noopener\">https:\/\/kursstm32.pl\/<\/a> (the content is in Polish)<\/h2>\n\n\n\n<figure class=\"wp-block-image size-full is-style-default\"><a href=\"https:\/\/kursstm32.pl\/\" target=\"_blank\" rel=\"noopener\"><img loading=\"lazy\" decoding=\"async\" width=\"820\" height=\"194\" src=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/02\/Kurs-STM32-roz.jpg\" alt=\"\" class=\"wp-image-1834\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/02\/Kurs-STM32-roz.jpg 820w, https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/02\/Kurs-STM32-roz-300x71.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2021\/02\/Kurs-STM32-roz-768x182.jpg 768w\" sizes=\"auto, (max-width: 820px) 100vw, 820px\" \/><\/a><\/figure>\n\n\n<div class=\"kk-star-ratings kksr-auto kksr-align-left kksr-valign-bottom\"\n    data-payload='{&quot;align&quot;:&quot;left&quot;,&quot;id&quot;:&quot;4184&quot;,&quot;slug&quot;:&quot;default&quot;,&quot;valign&quot;:&quot;bottom&quot;,&quot;ignore&quot;:&quot;&quot;,&quot;reference&quot;:&quot;auto&quot;,&quot;class&quot;:&quot;&quot;,&quot;count&quot;:&quot;0&quot;,&quot;legendonly&quot;:&quot;&quot;,&quot;readonly&quot;:&quot;&quot;,&quot;score&quot;:&quot;0&quot;,&quot;starsonly&quot;:&quot;&quot;,&quot;best&quot;:&quot;5&quot;,&quot;gap&quot;:&quot;0&quot;,&quot;greet&quot;:&quot;&quot;,&quot;legend&quot;:&quot;0\\\/5 - (0 votes)&quot;,&quot;size&quot;:&quot;24&quot;,&quot;title&quot;:&quot;Semihosting on STM32 as an Interesting Option for Debugging&quot;,&quot;width&quot;:&quot;0&quot;,&quot;_legend&quot;:&quot;{score}\\\/{best} - ({count} {votes})&quot;,&quot;font_factor&quot;:&quot;1.25&quot;}'>\n            \n<div class=\"kksr-stars\">\n    \n<div class=\"kksr-stars-inactive\">\n            <div class=\"kksr-star\" data-star=\"1\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"2\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"3\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"4\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" data-star=\"5\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n    \n<div class=\"kksr-stars-active\" style=\"width: 0px;\">\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n            <div class=\"kksr-star\" style=\"padding-right: 0px\">\n            \n\n<div class=\"kksr-icon\" style=\"width: 24px; height: 24px;\"><\/div>\n        <\/div>\n    <\/div>\n<\/div>\n                \n\n<div class=\"kksr-legend\" style=\"font-size: 19.2px;\">\n            <span class=\"kksr-muted\"><\/span>\n    <\/div>\n    <\/div>\n","protected":false},"excerpt":{"rendered":"<p>If we think about debugging, what comes to mind? Breakpoints, stepping through code, but above all printing. When dealing with microcontrollers, most often we send messages to the serial console terminal on the PC. We use one of the UART interfaces for this. What if we don\u2019t have that UART? [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":3709,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[175,176,174,177],"class_list":["post-4184","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-electronics","tag-programming","tag-stm32","tag-stm32cubemx"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4184","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/comments?post=4184"}],"version-history":[{"count":3,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4184\/revisions"}],"predecessor-version":[{"id":4187,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4184\/revisions\/4187"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/3709"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4184"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4184"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4184"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}