First things first
Semi-hosting is black magic. Or at least I thought so the first time I tried to get it up and going.
The basic idea follows the notion that engineers love to use printf() and scanf() functions alot in their debugging routines. They are however, the primary reason for code bloat. So why don’t we use the I/O of the host system that is debugging the application instead!
What semi-hosting does is pass along those I/O routines to the debugger that acts like a bridge between MCU and host I/O.
- Debugging with printf()
- Heavy I/O operations will not be found in final product
- Keyboard usage in development
- Only works while the debugger is attached and debugging
- Can add some strange behavior in runtime
For this example I’m going to use the Nucleo-F042K6 one of my favorite “goto” boards. Easily get started and try out any concept type of boards. The idea, however works on all boards.
For IDE I’m using Eclipse with the AC6 plugins, also known as “System Workbench for STM32 – Bare Metal Edition“.
The only thing we are “required” to have is to enable the “Serial Wired Debugging” in our project. If you are using CubeMX to generate your project it is under the SYS category in the peripheral tree.
This will enable our built in st-link debugger to be our I/O interface.
A good idea when we create a debugging configuration, is to create multiple configurations.
- One configuration that enables semihosting.
- Another configuration that is without semihosting. This alleviates the one of the disadvantages in that you can run the application without being in debugging mode.
To create a configuration with semi-hosting, first double click on the Ac6 STM32 Debugging label:
Select the newly created debugging profile and select the Startup tab:
In the field “Run Commands” add the following:
|1||monitor arm semihosting enable|
You can then create another profile named something like <project>_no_host with no modifications to the startup tab.
We also need to let the link know we are using semi-hosting by going into the project properties->C/C++ Build->Settings->MCU GCC Linker in the Miscellaneous->Linker flags and append the following to the linker flags:
|1||-specs=rdimon.specs -lc -lrdimon|
Finally, we need to initialize the I/O interface. This step is quite easy.
In the main.c file add the following prototype:
In the int main(void) function we are going to call this function.
Step 4. – Testing
You now can use printf() and other I/O stream functions to your hearts content:
When you first click the debug button, you should see the following at the bottom of the console output:
The magic words are “semihosting is enabled”.
When you click on the resume(F8) button, the code will run and your printf statements will appear in the console:
Did I miss anything?Share on Facebook