Semihosting is a technique to do printf()
debugging through an active debug connection. So instead using a physical connection like RS-232 or USB CDC, the connection to the host machine is through the debugger. This post is about enabling and using semihosting with gcc and newlib/newlib-nano in Freescale Eclipse based Kinetis Design Studio (KDS) using the GNU ARM Eclipse plugins.
Stack and Heap Size
Printf()
and the like use a lot of stack (typically a KByte, or even more). So in your project, make sure you have enough stack and heap allocated. With a Processor Expert project, you can increase the stack and heap size in the CPU component, ‘Build options’ tab. I recommend at least 0x400 for stack and 0xc00 for the heap:
If not using Processor Expert, then you need to check and update your linker file: There needs to be a __HeapBase and __HeapLimit symbol in it.
._user_heap_stack : { . = ALIGN(4); PROVIDE ( end = . ); PROVIDE ( _end = . ); __heap_addr = .; __HeapBase = .; . = . + __heap_size; __HeapLimit = .; . = . + __stack_size; . = ALIGN(4); } > m_data
The __heap_size and __stack_size are defined like this for me:
__heap_size = 0x0C00; /* required amount of heap */ __stack_size = 0x0400; /* required amount of stack */
Debugger Settings
In the debugger settings, you need to have support for semihosting enabled. I’m showing here the settings for Segger J-Link in the GNU ARM Eclipse plugins.
Enable ‘Allocate console for semihosting and SWO’ in the debugger tab:
In the ‘Startup’ tab, check the ‘Enable semihosting’ box:
💡 At the time of this post, semihosting is not yet supported by the P&E GDB Eclipse plugin, but I’m told that should be supported soon. The GNU ARM Eclipse OpenOCD debug panel have similar settings.
Usage in Application
To use printf()
, make sure you include
#include <stdio.h>Below is a simple test routine which writes 2000 characters in a loop:
int i; for(i=0;i<100;i++) { printf("Hello world!013456\r\n"); /* 20 characters */ } printf("***FINISHED***\n"); /* 2000 characters finished */Code and Data Size
Using
printf()
is not for free (see “Why I don’t like printf()“). Without usingprintf()
, I have this code size (see “text, data and bss: Code and Data Size Explained” for reading the numbers):arm-none-eabi-size --format=berkeley "semi.elf" text data bss dec hex filename 4196 44 4164 8404 20d4 semi.elfWith the above calls to
printf()
added, I get:arm-none-eabi-size --format=berkeley "semi.elf" text data bss dec hex filename 10076 2152 4396 16624 40f0 semi.elfSo this adds a lot of code and data overhead.
The above code size is with newlib and Kinetis Design Studio. Newlib is not ideal for embedded applications, so there is a newlib-nano which has a smaller footprint. For this I need to add the
-nanolibcoption to the linker settings:
With this, the footprint is still high, but reduced compared to standard newlib:
arm-none-eabi-size --format=berkeley "semi.elf" text data bss dec hex filename 7056 712 4348 12116 2f54 semi.elfPrinting Floating Point
By default, printing floating point is *not* enabled in newlib by default. To enable floating point printing, I need to add
-u _printf_floatto the linker options:
❗ In KDS, adding -u _printf_float adds about 7 KByte of code! So do not add it if you do not really need printing of float numbers.
With this, I can print float and doubles like
double d = 3.51; ... printf("double: %f\r\n", d);❗ To my knowledge, 64bit integer (long long) printing is *not* supported in newlib-nano.
Debugging
When debugging, there is now a ‘Semihosting and SWV’ entry in the debug view:
Clicking on that entry will show the semihosting Console view:
That ‘subview’ of the Console view is accessible with a small sub-menu too:
Summary
I usually avoid to use
printf()
at any price. But sometimes libraries come with it, and sometimes I need to jump over my shadow. Thenprintf()
can be useful sometimes, even if it comes with a high price in code size, RAM usage and stack usage.Happy Semihosting 🙂
For Cortex-M3/M4 projects generated with the GNU ARM Eclipse plug-ins you have even more options, you can select the output stream to be the semihosting STDOUT or DEBUG channel, and you can run the same code without the debugger connected, since the low level routine can detect when the debugger is not active and just return.
Also the name is distinct, you use trace_printf() for tracing, which allows printf() to be re-targetted to any other stream (for example a socket) to meet any application requirements.
LikeLike
> Semihosting is a technique to do printf() debugging through an active debug connection.
To be correct, this is only one of the features of semihosting. With advanced GDB servers like J-Link, you can use all the features specified in the ARM semihosting documentation, including reading/writing files from the host machine, getting the current time, passing a command line, getting the exit code back, etc.
These features are very useful for writing unit tests, that need to return the test results (usually as an XML file to be parsed by a continuous integration server, like Hudson/Jenkins).
When creating projects with the GNU ARM Eclipse plug-ins, it is possible to choose from three options:
– full semihosting (all POSIX read/write routed to host),
– re-targetting (read/write routed to application device) and
– no POSIX calls.
In addition to this, the trace_printf() can be routed to:
– ARM SWO,
– semihosting STDOUT (a buffered device, lines displayed at n)
– semihosting DEBUG (an unbuffered device, characters displayed one at a time).
LikeLike
Thanks Liviu for the clarification. I was actually wondering how to use ARM SWO, I will check on this.
LikeLike
I saw this was available in GNU ARM toolchain eclipse plugin with Jlink firmware from a while ago, wrote a post about it: 2014/03/debugging-arm-freescale-microcontrollers-with-j-link-gdb-server-and-gnu-arm-toolchain-gdb-with-semihosting-in-linux/ . Nice to know we can do this in KDS. I got the KDS better version but havent tested much, been into Physics lately.
LikeLike
Pingback: Tutorial: Nordic Semiconductor nRF24L01+ with the Freescale FRDM-K64F Board | MCU on Eclipse
Pingback: printf() and scanf() with GNU ARM Libraries | MCU on Eclipse
Pingback: printf() for the FRDM-K64F Board and Kinetis Design Studio | MCU on Eclipse
Pingback: Semihosting with GNU ARM Embedded (LaunchPad) and GNU ARM Eclipse Debug Plugins | MCU on Eclipse
Hello!
I’m trying to use semihosting to print stuff with P&E GDB (OpenSDA) in a FRDM-KL25Z board. (I could’nt manage to make prints using virtual serial port or other solutions). However I can only print a string with 103 characters. More than this (103,104, etc) it gives me an error (something weird, related to a SIGTRAP signal) and I can continue execution, and with even more (128, which is what I want) it simply doesn’t print anything. Do you think this is related to still poor support of semihosting by P&E debugger or with semihosting limitations?
Your website is great for any student working with Freescale microcontrollers, congratulations!
LikeLike
Hi Daniel,
thanks :-). I have not printed very long strings. But indeed, there is naturally a buffer limit inside semihosting. Are you sending that 104 character string with now \r\n in between (no line feeds)? I have not tried your case yet, but it could be as well the library provided in KDS. Have you seen the same thing with the Segger connection too?
LikeLike
Hello Erich,
I tried this solution with FRDM-KL25Z, GDB PE Micro Interface Debugging (OpenSDA USB). I followed carefully all the steps (heap size, enable semihosting, include ) starting from scratch with a new KDS project with PE.
But it prints to the console only the first character of each string. With your example, instead of Printing “Hello world!” 100 times and then “*** FINISHED ***!” in the console view I see just 100 lines with only “H” and then the “*” of the last string. What can be the reason?
Thank you in advance for your help.
LikeLike
Not sure what is causing this for you. Do you have a \n at the end of each string?
LikeLike
Thank you Erich. Yes, the \r\n is present at the end of the string: I used the exact code you gave as an example:
int i;
for(i=0;i<100;i++) {
printf("Hello world!013456\r\n"); /* 20 characters */
}
printf("***FINISHED***\n"); /* 2000 characters finished */
But in the console I get just:
H
H
… (100 times)
H
*
Strange behaviour…
If I find the reason I will post it here.
Thanks again!
Cheers,
Vittorio
LikeLike
Just for reference I found an explanation here: freescale community thread/324452
LikeLike
Pingback: Installing and using Kinetis Design Studio version 2 in Linux >> Karibe Muriuki
I tried out semihosting with the latest PE opensda firmware for KL05Z and it only prints the first character. I saw this is already discussed on another post on this blog, but for k64F board, and a physical serial port. I tried adding the isatty() function and adjusting stack and heap, no success.
Also, the serial port interface does not work for the KL05Z board with the latest PE firmware in Linux. Its enumerated well as /dev/ttyACM0, but it doesnt work. I am writing a summary of what works here: 2015/03/installing-and-using-kinetis-design-studio-version-2-in-linux
LikeLike
I cannot comment on Linx, but I can confirm that it works as expected on Windows?
LikeLike
have you tested with the KL05Z board? I will test the KL25Z board and see.
LikeLike
Yes, it works as expected. I have pushed my UART example for the FRDM-KL05Z here:
https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/KDS/FRDM-KL05Z/FRDM-KL05Z_PEx
My board information:
Board Name is: FRDM-KL05Z
MicroBoot Kernel Version is: 1.03
Bootloader Version is: 1.11
Installed Application: PEMicro FRDM-KL05Z Mass Storage/Debug App
Application Version is: 1.14
LikeLike
Pingback: Semihosting with GNU ARM Embedded (Launchpad) and Kinetis Design Studio | MCU on Eclipse
Pingback: Why I am not a fan of ARM’s Semihosting feature | bitknitting
Dear Erich
I changed the stack size and heap size as given here for my boot loader project. But it is throwing these errors while building.
c:/freescale/kds_2.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.8.0/../../../../arm-none-eabi/bin/ld.exe: Bootloader.elf section `._user_heap_stack’ will not fit in region `m_data’
c:/freescale/kds_2.0.0/toolchain/bin/../lib/gcc/arm-none-eabi/4.8.0/../../../../arm-none-eabi/bin/ld.exe: region `m_data’ overflowed by 352 bytes
collect2.exe: error: ld returned 1 exit status
make: *** [Bootloader.elf] Error 1
How to rectify it ?
Thanks
Ganesh R
LikeLike
Hi Ganesh,
You are allocating more RAM than you have available on your system. You need to reduce the amount of RAM allocated in the linker file for stack and heap by 352 bytes.
Erich
LikeLike
Hi Erich,
This is exactly where I got my doubt. You have written in this article, ” I recommend at least 0x400 for stack and 0xc00 for the heap “.. In my project, when I opened the Build options tab, the stack size and heap size were 0x100 by default. After reading through this article I increased my stack and heap size to 0x400 and 0xc00 respectively. When I built the code, I got the errors which I already quoted in my first comment. Now from your reply to comment, If I have to reduce the stack and heap size by 352 bytes (0x160 in hex), do you mean,
New Stack Size => 0x0400 – 0x160 = 2A0
New Heap Size => 0x0c00 – 0x160 = AA0
I changed the stack and heap sizes to these values and the code built fine. But I don’t know whether this is correct ?
Have I rectified the error correctly ?
LikeLike
Hi Ganesh,
you only need to reduce the RAM size for 0x160 once. You did it twice (both for stack and heap).
LikeLike
Oh .. So is it enough if I reduce the heap size by 0x160. So my new size should be
New Stack Size : 0x400
New Heap Size: 0xc00 – 0x160 = 0xAA0
have I understood it correctly now ?
LikeLike
yes, that looks good.
LikeLiked by 1 person
Hello,
I am using CodeWarrior for MCU Version: 10.6.4 and I cannot find any checkbox to enable semihosting. In my case the setting windows are not the same as in the discription above (e.g. I cannot find a startup tab).
I have an example code in which semihosting is used and it works fine. I also found the “-D__SEMIHOSTING” flag in the build options of the C compiler (under “all options:” this field is not editable). So I tried to enable semihosting in another example project by adding the phrase “-D__SEMIHOSTING” in the “others flag” field. However, then there is this error when I want to build the project: “undefined reference to ‘sys_exit'” in “__arm_end.c”
So, how can i enable semihosting? Where are the settings hidden?
I would be most grateful for any help.
LikeLike
Hi Andreas,
I believe I have never used Semihosting with the CodeWarrior tools. And I do not recommend it as it is very, very slow because of the way it is done in the CodeWarrior libraries (I remember something with only few hundred bytes per second). And the panels are different because Kinetis Design Studio is using GDB, while CodeWarrior is using a proprietary debugger.
Erich
LikeLike
Hi Erich,
I’m attempting to use semihosting under P&E Multilink. I have followed the steps P&E outline for enabling their part of it, and have followed your instructions(which they link to). When I try to debug my target program I get the branch showing “Semihosting Console”, but when I click on it, although the Console switches to “P&E Semihosting Console”, the debug Resume/Suspend etc. are greyed out. If I then reclick on Thread #1, the Resume etc. come back to life, but the Semihosting Console disappears.
This is a totally bare metal project, if that makes any difference…
LikeLike
Hi John,
double clicking on the ‘semihosting’ entry in the call stack opens the console with that view. And yes, if you don’t have the current (code) tread selected, then you cannot step/etc. This is how it is implemented with the GNU ARM Eclipse plugins and to me this is in alingment with how Eclipse thread debugging works. The Semihosting ‘thread’ is just shown there to have an easy way to switch to the console view with the semihosting output.
As for the semihosting console disapearing: you can ‘pin’ the console view to whatever you want.
LikeLike
Thanks for the very prompt reply. I have now “pinned” the Semihosting Console, but nothing appears in it, so I guess I’m doing something else wrong, or missing some other part of the puzzle.
LikeLike
OK, I have it working now. I changed the -specs=nosys.specs to -specs=rdimon.specs
It maybe that I’m using a later set of tools?
Good tip also, on one of your pages, about finding the SemiHosting Console by using the Display selected console” icon.
Many thanks, I’m not sure that I’d be able to make any progress with Kinetis if is wasn’t for your blogs and advice. Whatever NXP are paying you it’s not enough.
John
LikeLike
Hi John,
does the application run and does not crash? Otherwise, it depends what kind of library or SDK your are using. For example there are special steps for the Kinetis SDK v2.0 necessary, see https://mcuoneclipse.com/2016/08/06/semihosting-again-with-nxp-kinetis-sdk-v2-0/
I hope this helps,
Erich
LikeLike
Hi,
No crashing. Only problem I have now is that I can’t get the Semihosting Console to persist – have to re-select it every debug session. I fear these questions and answers are getting out of sync now!
LikeLike
Although despite “pinning”, I can’t get the Semihosting Console to persist between debugging sessions. I always have to select it anew. Is this normal?
LikeLike
Hi John,
yes, I noticed this too. The ‘pinning’ state is not stored between debugging sessions.
LikeLike
I’m not using any SDK, by the way. When I say bare metal I mean bare metal. Stupid as it may sound, I’m writing everything from scratch, using some of the SDK files for a bit of guidance now and again. I’m wondering if SDK_DEBUGCONSOLE=0 as you mention on another page could be the trick…
LikeLike
Hi John,
ah, ok. Some (mostly myself too) are using ‘bare metal’ for ‘without RTOS’. But to the essence, real bare metal is not using the SDK, I agree with you.
The SD_DEBUGCONSOLE=0 is used with the SDK to disable the debug console code, as it overwrites some of the low level rxchar/txchar methods used by printf. If these overwrites are in place, semihosting does not work.
LikeLike
Thanks again for all the replies.
Semihosting working fine now, apart from having to open the Semihosting Console view every time. I can live with that – need to get on with writing code. While I agree, in principle, with the maxim “Give me six hours to chop down a tree and I’ll spend the first four sharpening the axe”, there comes a time when you have to get some results!
LikeLike
Hi John,
good to hear that it is working now. And I agree to the tree thing 100% :-).
LikeLike
Hello,
I’m doing a project with some simple image acquisition and processing in an STM32 microcontroller. I’ve been using ARM semihosting technology for debugging with standard C library fopen/fwrite functions for logging the data of the pictures on the host computer for purposes of debugging but I find it quite slow since I have sometimes to log data for RGB565 320×240 pictures (153 600 bytes), and it takes quite some time to write the data to the file on PC. As so I’m asking if you have another recomendation or alternative for debugging this kind of data (maybe using ITM SWO output?). Thank you for your attention.
Best regards,
LikeLike
Yes, semihosting is very slow. Because it stops the target with a breakpoint, the debugger needs to catch this, then the debugger reads one or more byte of data and restarts the device, and so on.
If you have a SEGGER J-Link, then a fast ways is to use the Segger RTT to tranfer the file (see https://mcuoneclipse.com/2015/07/07/using-segger-real-time-terminal-rtt-with-eclipse/). Another way is to attach an SD card over SPI and store the data on it (see https://mcuoneclipse.com/2016/07/09/fatfs-with-adafruit-microsd-breakout-board-and-nxp-frdm-kl25z/).
Or simply send the data over USB CDC (or UART), but this will need a special program on the host to receive the data.
LikeLike
I love the whole blog and found it super helpful for learning how to use JTAG debugging. I typically use M0 processors (like the SAMD21G or SAMD11D that don’t have SWO. Does semi-hosting work on these types of devices?
LikeLike
Hi Jeremy,
semihosting works on any device, as long as the debugger/debug connection is able catch the semihosting traps.
LikeLike
Thanks for the blog post and lots of great information on JTAG debugging. I typically use SAMD21 and SAMD11 processors which are cortex-M0. Does semi-hosting work without SWO?
LikeLike
Semihosting depends on the debug connection and capability of the debug probe, and does not depend on SWO. Using a terminal connection with SWO is using a different technology, but does not need a direct involvement of the debug probe
LikeLike