{"id":4355,"date":"2018-09-19T20:00:08","date_gmt":"2018-09-19T18:00:08","guid":{"rendered":"https:\/\/msalamon.pl\/?p=4355"},"modified":"2025-12-27T20:35:16","modified_gmt":"2025-12-27T19:35:16","slug":"discover-what-the-built-in-st-link-programmer-on-stm32-nucleo-boards-can-do","status":"publish","type":"post","link":"https:\/\/msalamon.pl\/en\/discover-what-the-built-in-st-link-programmer-on-stm32-nucleo-boards-can-do\/","title":{"rendered":"Discover What the Built-In ST-LINK Programmer on STM32 Nucleo Boards Can Do"},"content":{"rendered":"\n<p>I might be repeating myself, but ST\u2019s kits are great. With every board we get a fully functional ST-Link programmer. Well, almost fully, but it covers 100% of the needs of the microcontroller mounted in the kits. Do you know all its functionalities? I could bet you don\u2019t<\/p>\n\n\n\n<!--more-->\n\n\n\n<p>, but I also assume advanced users are reading this, so I won\u2019t risk it \ud83d\ude09<\/p>\n\n\n\n<h1 class=\"wp-block-heading\">What is ST-Link<\/h1>\n\n\n\n<p>In short, it\u2019s a programmer compatible with ST\u2019s MCUs. ST-Link by default is an integral part of the <a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=stlinkv2&amp;utm_content=Text\">Nucleo kits<\/a>, but you can break it off and use it as a separate unit. Unfortunately, <a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/stm-nucleo-64\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=stlinkv2&amp;utm_content=Text\">Nucleo-32<\/a> is an exception and we can\u2019t physically separate the ST-Link from the main part. It\u2019s similar with Discovery boards \u2014 you also won\u2019t extract the programmer. Owning a few Nucleo boards, I have a stock of programmers for myself and my kids for life.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/?utm_source=blog&amp;utm_medium=banner&amp;utm_campaign=stlinkv2&amp;utm_content=nucleo\"><img loading=\"lazy\" decoding=\"async\" width=\"1200\" height=\"400\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg\" alt=\"\" class=\"wp-image-1593\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner.jpg 1200w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-300x100.jpg 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-1024x341.jpg 1024w, https:\/\/msalamon.pl\/wp-content\/uploads\/2020\/07\/Nucleo-64-baner-768x256.jpg 768w\" sizes=\"auto, (max-width: 1200px) 100vw, 1200px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>What can this little beast do? Many <em>features<\/em> are described in the documentation concerning programmers integrated with evaluation kits. Additionally, in the general documentation for Nucleco kits there\u2019s a bit more. I recommend reading these documents.<\/p>\n\n\n\n<p><a data-e-disable-page-transition=\"true\" class=\"download-link\" title=\"\" href=\"https:\/\/msalamon.pl\/download\/287\/?tmstv=1766862102\" rel=\"nofollow\" id=\"download-link-287\" data-redirect=\"false\"><br>\n\tTN1235 &#8211; Overview of the ST-LINK embedded in STM32 MCU Nucleo<\/a>\n<\/p>\n\n\n\n<p><a data-e-disable-page-transition=\"true\" class=\"download-link\" title=\"\" href=\"https:\/\/msalamon.pl\/download\/293\/?tmstv=1766862102\" rel=\"nofollow\" id=\"download-link-293\" data-redirect=\"false\"><br>\n\tSTM32 Nucleo<\/a>\n<\/p>\n\n\n\n<p>When approaching your unit for the first time, it\u2019s worth updating the firmware in the programmer. You can do this using <strong>ST-Link Utility<\/strong>. You can download the latest version <a href=\"https:\/\/www.st.com\/en\/development-tools\/stsw-link004.html\" target=\"_blank\" rel=\"noopener\">from ST\u2019s website<\/a>. Unfortunately, you need an account to download anything from them. The entire operation is very simple. Start the tool and connect a <a href=\"https:\/\/sklep.msalamon.pl\/kategoria-produktu\/dev-boardy\/stm32-nucleo\/?utm_source=blog&amp;utm_medium=article&amp;utm_campaign=stlinkv2&amp;utm_content=Text\">Nucleo<\/a> or another board with an ST-Link. Then from the top menu select <em>ST-Link<\/em> &gt;&gt; <em>Firmware Update.<\/em><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/Firmware_update_1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"480\" height=\"200\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/Firmware_update_1.png\" alt=\"\" class=\"wp-image-290\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/Firmware_update_1.png 480w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/Firmware_update_1-300x125.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/Firmware_update_1-24x10.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/Firmware_update_1-36x15.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/Firmware_update_1-160x67.png 160w\" sizes=\"auto, (max-width: 480px) 100vw, 480px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/FIrmware_update_2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"487\" height=\"344\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/FIrmware_update_2.png\" alt=\"\" class=\"wp-image-291\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/FIrmware_update_2.png 487w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/FIrmware_update_2-300x212.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/FIrmware_update_2-24x17.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/FIrmware_update_2-36x25.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/FIrmware_update_2-113x80.png 113w\" sizes=\"auto, (max-width: 487px) 100vw, 487px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>After clicking <em>Device Connect<\/em>, the program should detect the programmer connected to the computer. <em>Firmware Version<\/em> is the current firmware that sits in the programmer. Below is the latest version that\u2019s available. In my case, it\u2019s the same as on the device. Clicking <em>Yes<\/em> starts the update procedure.<br>\n<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Programming<\/h2>\n\n\n\n<p>If you read the documentation carefully, you already know some features of the ST-Link. Its most important and basic function is undoubtedly programming the microcontroller. By connecting the Nucleo as a whole or other boards with an integrated ST-Link, we can upload our program to the MCU. You can do this via <em>ST-Link Utility<\/em> by pointing to the compiled binary with the firmware, or directly in the SW4STM32 environment, which is recommended by ST and which I use.<\/p>\n\n\n\n<p>A cool \u201cgimmick\u201d is programming by dropping the binary onto the mass storage device under which the ST-Link mounts in the operating system. This method is dictated by the assumptions of the <em>mbed<\/em> project. Imagine you are in the field at a customer site, you don\u2019t have your toolchain because your computer died, but someone sent you a binary with a bug fix. Thanks to the programmer mounting like a pendrive, you copy the binary onto it from a borrowed laptop or even from a phone with OTG support and\u2026 done. The chip is programmed. Great, isn\u2019t it? I use this method very rarely, but I see potential in it.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/stlink_pinout.png\"><img loading=\"lazy\" decoding=\"async\" width=\"159\" height=\"204\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/stlink_pinout.png\" alt=\"\" class=\"wp-image-292\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/stlink_pinout.png 159w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/stlink_pinout-19x24.png 19w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/stlink_pinout-28x36.png 28w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/stlink_pinout-62x80.png 62w\" sizes=\"auto, (max-width: 159px) 100vw, 159px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>I mentioned earlier breaking off the ST-Link from Nucleo boards. After such a procedure, we can program any chips by connecting through the CN4 connector. To make this possible, you also need to remove the jumpers from CN2. By removing these jumpers, you can also program external chips without breaking the ST-Link off the Nucleo. The CN4 connector has a standard pinout:<\/p>\n\n\n\n<p><strong>Note. Pin 1 is not used to power the programmed circuit! We connect this pin to the power supply of the programmed MCU so that the ST-Link can match it.<\/strong> Thanks to this, we can program chips at very low operating voltages. Even though the ST-Link note added to the Nucleo kits says it won\u2019t work below 3 V \u2014 I successfully programmed and debugged chips powered at 1.8 V.<\/p>\n\n\n\n<p>I always skip pin 6 \ud83d\ude09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Debugging<\/h2>\n\n\n\n<p>Besides programming, we can truly debug the code. I remember how on AVR I always struggled with a debug LED that was set somewhere in the code as a trap. It had its charm and I still like to do it sometimes. The problem appears when, for example, the processor runs, communication looks correct, but still the program refuses to work properly. With a LED you won\u2019t peek at variable values in RAM.<\/p>\n\n\n\n<p>Likewise, you won\u2019t stop the program at any point with a LED. But you can from the debugging level. You set so-called <em>breakpoints<\/em> that will stop the execution of the program when the MCU reaches them. It\u2019s an incredibly powerful tool for solving problems, and problems are even 80% of writing code. Unless someone prefers the rubber duck method (<a href=\"https:\/\/pl.wikipedia.org\/wiki\/Metoda_gumowej_kaczuszki\" target=\"_blank\" rel=\"noopener\">link<\/a>). I, of course, have my duck on the desk \ud83d\ude09<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">UART communication<\/h2>\n\n\n\n<p>ST-Link is simultaneously a UART &lt;=&gt; USB converter. It creates a virtual COM port in our computer\u2019s operating system. Thanks to this, we can print whatever we want to the terminal on our PC. Not only print, because we can also receive from the PC. Great stuff. For this purpose, UART2 located on pins PA2 and PA3 is used.<\/p>\n\n\n\n<p>Just like programming, using the UART &lt;=&gt; USB conversion is possible outside the evaluation boards. This is possible via the CN3 connector, to which we feed the microcontroller\u2019s UART. However, there isn\u2019t a convenient jumper to disconnect it like in the case of programming. To use UART externally without breaking the ST-Link off, you need to desolder jumpers SB13 and SB14 located on the bottom of the PCB.<\/p>\n\n\n\n<h2 class=\"wp-block-heading\">Semihosting<\/h2>\n\n\n\n<p>You probably haven\u2019t heard of this. I myself learned about it quite recently. What if you wanted to print something to the computer, but you don\u2019t have any free UART or USB interface because everything is occupied by peripherals in the device? No chance, right? And yet! The so-called <em>semihosting<\/em> comes to the rescue. It\u2019s a feature that prints to gdb, so you only use it in debug mode. Unfortunately, it only works one way, but during debugging that\u2019s mainly the direction we use \u2014 we send to the PC. Another drawback is the significant slowdown of the MCU\u2019s program execution, so you have to disable this method in the target microcontroller program. Failing to start the MCU in debug mode will also prevent proper operation if <em>semihosting<\/em> is used. How to configure it and how to use it? Let\u2019s do it!<\/p>\n\n\n\n<p>You need a special assembly function in the code that writes to the ST-Link interface.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">void send_command(int command, void *message) {\n\t#ifdef DEBUG\n\t__asm(\"mov r0, %[cmd];\"\n\t\"mov r1, %[msg];\"\n\t\"bkpt #0xAB\"\n\t\t:\n\t\t: [cmd] \"r\" (command), [msg] \"r\" (message)\n\t\t: \"r0\", \"r1\", \"memory\");\n\t#endif\n}<\/pre>\n\n\n\n<p>As you can see, I wrapped this function in an #ifdef. Thanks to this, I can quickly disable <em>semihosting<\/em> if I don\u2019t want to use it. There\u2019s also all the surrounding code in the form of printing functions.<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">#define INT_DIGITS 19 \/* enough for 64 bit integer *\/\n\nchar *itoa(int i)\n{\n\tstatic char buf[INT_DIGITS + 2];\n\tchar *p = buf + INT_DIGITS + 1; \/* '\\0' *\/\n\tif (i &amp;gt;= 0) {\n\t\tdo\n\t\t{\n\t\t\t*--p = '0' + (i % 10);\n\t\t\ti \/= 10;\n\t\t} while (i != 0);\n\t\treturn p;\n\t}\n\telse { \/* i &amp;lt; 0 *\/\n\t\tdo \n\t\t{\n\t\t\t*--p = '0' - (i % 10);\n\t\t\ti \/= 10;\n\t\t} while (i != 0);\n\t\t*--p = '-';\n\t}\n\treturn p;\n}\n\nvoid prints( const char* str )\n{\n\n\tuint32_t len = strlen(str);\n\tuint32_t i = 0;\n\n\tfor( i = 0; i &amp;lt; len; i+=4)\n\t{\n\n\t\tuint32_t buflen = 4;\n\t\tif( i+4 &amp;gt;= len ) buflen = len-i;\n\t\tsize_t m[] = { 2\/*stderr*\/, (size_t)str, buflen\/sizeof(char) };\n\t\tsend_command(0x05\/* some interrupt ID *\/, m);\n\t\tstr+=4;\n\t}\n}\n\nvoid printc( char c )\n{\n\tchar buf[2];\n\n\tbuf[0] = c;\n\tbuf[1] = 0;\n\n\tprints(buf);\n}\n\nvoid printi( int32_t i )\n{\n\tprints( itoa(i) );\n}\n\nchar *convert(unsigned int num, int base)\n{\nstatic char Representation[]= \"0123456789ABCDEF\";\n\tstatic char buffer[50];\n\tchar *ptr;\n\n\tptr = &amp;amp;buffer[49];\n\t*ptr = '\\0';\n\n\tdo\n\t{\n\t\t*--ptr = Representation[num%base];\n\t\tnum \/= base;\n\t}while(num != 0);\n\n\treturn(ptr);\n}\n\nvoid print(char* format, ...)\n{\n\n\tchar *traverse;\n\tunsigned int i;\n\tchar *s;\n\tdouble d;\n\n\tva_list arg;\n\n\tva_start(arg, format);\n\n\t\/\/\/ Pack buf per 4 characters (last is always NULL)\n\tchar buf[5];\n\tmemset(buf, 0, 5);\n\tint t = 0;\n\n\tfor(traverse = format; *traverse != '\\0'; traverse++)\n\t{\n\t\tif (*traverse != '%')\n\t\t{\n\t\t\tif( t == 5 )\n\t\t\t{\n\t\t\t\tprints(buf);\n\t\t\t\tmemset(buf, 0, 5);\n\t\t\t\tt = 0;\n\t\t\t}\n\n\t\t\tbuf[t%5] = *traverse;\n\t\t\tt++;\n\t\t\tcontinue;\n\t\t}\n\n\t\tprints(buf);\n\t\tmemset(buf, 0, 5);\n\t\tt = 0;\n\n\t\ttraverse++;\n\n\t\t\/\/\/ Module 2: Fetching and executing arguments\n\t\tswitch(*traverse)\n\t\t{\n\t\t\t\/\/\/ Fetch char argument\n\t\t\tcase 'c' : i = va_arg(arg,int);\n\t\t\t\tprintc(i);\n\t\t\t\tbreak;\n\n\t\t\t\/\/\/ Fetch Decimal\/Integer argument\n\t\t\tcase 'd' : i = va_arg(arg,int);\n\t\t\t\tif(i&amp;lt;0)\n\t\t\t\t{\n\t\t\t\t\ti = -i;\n\t\t\t\t\tprintc('-');\n\t\t\t\t}\n\t\t\t\tprints(convert(i,10));\n\t\t\t\tbreak;\n\n\t\t\t\/\/\/ Fetch floating point argument\n\t\t\tcase 'f' : d = va_arg(arg, double);\n\t\t\t\tif(d&amp;lt;0)\n\t\t\t\t{\n\t\t\t\t\td = -d;\n\t\t\t\t\tprints(\"-\");\n\t\t\t\t}\n\t\t\t\ti = (unsigned int)d;\n\t\t\t\tprints(convert(i, 10));\n\t\t\t\tprintc('.');\n\n\t\t\t\td = d - i;\n\t\t\t\tif (d*10.0 &amp;lt; 1.0)\n\t\t\t\t\tprintc('0');\n\t\t\t\tif (d*100.0 &amp;lt; 1.0)\n\t\t\t\t\tprintc('0');\n\n\t\t\t\t\/\/\/ Round to 3 decimal places\n\t\t\t\tprints(convert((int)round(d*1000.0), 10));\n\t\t\t\tbreak;\n\n\t\t\t\/\/\/ Fetch Octal representation\n\t\t\tcase 'o': i = va_arg(arg,unsigned int);\n\t\t\t\tprints(convert(i,8));\n\t\t\t\tbreak;\n\n\t\t\t\/\/\/ Fetch string\n\t\t\tcase 's': s = va_arg(arg,char *);\n\t\t\t\tprints(s);\n\t\t\t\tbreak;\n\n\t\t\t\/\/\/ Fetch Hexadecimal representation\n\t\t\tcase 'x': i = va_arg(arg,unsigned int);\n\t\t\t\tprints(convert(i,16));\n\t\t\t\tbreak;\n\t\t}\n\t}\n\n\tprints(buf);\n\tmemset(buf, 0, 5);\n\n\tva_end(arg);\n}\n\n[\/cc]<\/pre>\n\n\n\n<p>When we already have the code ready, we need to configure SW4STM32 to receive messages in gdb. Open the debug profile configurations.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_1.png\"><img loading=\"lazy\" decoding=\"async\" width=\"627\" height=\"201\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_1.png\" alt=\"\" class=\"wp-image-297\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_1.png 627w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_1-300x96.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_1-24x8.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_1-36x12.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_1-160x51.png 160w\" sizes=\"auto, (max-width: 627px) 100vw, 627px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>In the <em>Startup<\/em> tab of the <g class=\"gr_ gr_25 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling\" id=\"25\" data-gr-id=\"25\">by<\/g> you <g class=\"gr_ gr_23 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"23\" data-gr-id=\"23\">profile<\/g> <g class=\"gr_ gr_26 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling\" id=\"26\" data-gr-id=\"26\">add<\/g><\/p>\n\n\n\n<pre class=\"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\n<\/pre>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2.png\"><img loading=\"lazy\" decoding=\"async\" width=\"786\" height=\"633\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2.png\" alt=\"\" class=\"wp-image-298\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2.png 786w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2-300x242.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2-768x619.png 768w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2-24x19.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2-36x29.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_2-99x80.png 99w\" sizes=\"auto, (max-width: 786px) 100vw, 786px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p>in the <g class=\"gr_ gr_24 gr-alert gr_spell gr_inline_cards gr_run_anim ContextualSpelling ins-del multiReplace\" id=\"24\" data-gr-id=\"24\">field<\/g> Run Commands.<br>\n<\/p>\n\n\n\n<p><strong>Remember to comment out the code for semihosting if you\u2019re not using it.<\/strong> You can do this, for example, with a simple <em>#define<\/em> as I mentioned above.<\/p>\n\n\n\n<p>After completing these steps, we can print in the code, e.g., for testing in the main program loop between sending a message over UART and the cyclic LED blink:<\/p>\n\n\n\n<pre class=\"EnlighterJSRAW\" data-enlighter-language=\"c\" data-enlighter-theme=\"\" data-enlighter-highlight=\"\" data-enlighter-linenumbers=\"\" data-enlighter-lineoffset=\"\" data-enlighter-title=\"\" data-enlighter-group=\"\">while (1)\n{\n\/* USER CODE END WHILE *\/\n\n\/* USER CODE BEGIN 3 *\/\n  uint8_t message[] = \"UART over ST-Link \\n\\r\";\n  HAL_UART_Transmit(&amp;amp;huart2, message, sizeof(message)-1, 100);\n\n  print(\"Semihosting test \\n\");\n  HAL_GPIO_TogglePin(LED_GPIO_Port, LED_Pin);\n  HAL_Delay(500);\n}\n\n\/* USER CODE END 3 *\/<\/pre>\n\n\n\n<p>&nbsp;<\/p>\n\n\n\n<p>Running the program in debug mode generates cyclic prints of the test message to the gdb console.<\/p>\n\n\n<div class=\"wp-block-image\">\n<figure class=\"aligncenter\"><a href=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_3.png\"><img loading=\"lazy\" decoding=\"async\" width=\"555\" height=\"220\" src=\"http:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_3.png\" alt=\"\" class=\"wp-image-299\" srcset=\"https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_3.png 555w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_3-300x119.png 300w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_3-24x10.png 24w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_3-36x14.png 36w, https:\/\/msalamon.pl\/wp-content\/uploads\/2018\/08\/semihosting_3-160x63.png 160w\" sizes=\"auto, (max-width: 555px) 100vw, 555px\" \/><\/a><\/figure>\n<\/div>\n\n\n<p><\/p>\n\n\n\n<p>Admit it, this is great. You don\u2019t need a free UART for simple debugging \u2014 ST-Link, which you always have, is enough!<\/p>\n\n\n\n<p>If you liked this post, like it or share it further. I\u2019ll be very grateful for any activity.<\/p>\n\n\n\n<p>As usual, the source code used in the post can be found on GitHub: <a href=\"https:\/\/github.com\/lamik\/ST-Link_demo\" target=\"_blank\" rel=\"noopener\">link<\/a><\/p>\n\n\n\n<p>If you noticed any error, disagree with something, or simply think you\u2019d like to discuss this topic, write a comment. Remember that the discussion should be polite and in accordance with the rules of the Polish language.<\/p>\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;4355&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;Discover What the Built-In ST-LINK Programmer on STM32 Nucleo Boards Can Do&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>I might be repeating myself, but ST\u2019s kits are great. With every board we get a fully functional ST-Link programmer. Well, almost fully, but it covers 100% of the needs of the microcontroller mounted in the kits. Do you know all its functionalities? I could bet you don\u2019t<\/p>\n","protected":false},"author":1,"featured_media":2980,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":"","_links_to":"","_links_to_target":""},"categories":[160],"tags":[176,174],"class_list":["post-4355","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-stm32","tag-programming","tag-stm32"],"_links":{"self":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4355","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=4355"}],"version-history":[{"count":3,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4355\/revisions"}],"predecessor-version":[{"id":4469,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/posts\/4355\/revisions\/4469"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media\/2980"}],"wp:attachment":[{"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/media?parent=4355"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/categories?post=4355"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/msalamon.pl\/en\/wp-json\/wp\/v2\/tags?post=4355"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}