Difference between revisions of "Host-based formatting"
(→Worked example) |
|||
(12 intermediate revisions by 3 users not shown) | |||
Line 1: | Line 1: | ||
+ | [[Category:Knowledge Base]] |
||
Host-based formatting is a technology that reduces the on-target code and data size associated with typical semihosting. |
Host-based formatting is a technology that reduces the on-target code and data size associated with typical semihosting. |
||
Line 9: | Line 10: | ||
==Host-based formatting== |
==Host-based formatting== |
||
− | For MCUs with very small amounts of flash and RAM, debug messages delivered through semihosting can be an unacceptable burden, consuming most of the flash and RAM space of the target thereby leaving very little space for the application. For instance, MSP430 processors can have as little as 256 bytes of RAM and 1 |
+ | For MCUs with very small amounts of flash and RAM, debug messages delivered through semihosting can be an unacceptable burden, consuming most of the flash and RAM space of the target thereby leaving very little space for the application. For instance, MSP430 processors can have as little as 256 bytes of RAM and 1 KiB of flash. Usually a PCB would be populated with a larger device for product development to enable larger debug builds to be programmed into the flash. However, some device families do not offer larger memory versions that could be used for development and, therefore, reducing the footprint of debug code is essential for the application to fit. |
===Advantages=== |
===Advantages=== |
||
− | Host-based formatting shifts the burden of formatting from the target system, where resources are limited, to the host system. The host system supports all formatting |
+ | Host-based formatting shifts the burden of formatting from the target system, where resources are limited, to the host system, where resources are plentiful. The host system supports all formatting specifications (such as width, precision, text alignment, floating point, and so on) simply because it has ample resources to do so. In this scenario the target footprint for <code>printf</code>, for instance, is no more than a few instructions to issue a semihosting call and have the debug agent perform the semihosting operation. |
===Implementation details=== |
===Implementation details=== |
||
Line 29: | Line 30: | ||
===Worked example=== |
===Worked example=== |
||
− | + | With host-based formatting, the call... |
|
<syntaxhighlight lang="c"> |
<syntaxhighlight lang="c"> |
||
− | printf("There are %u bottles of |
+ | printf("There are %u bottles of %s on the wall", 99, "beer"); |
</syntaxhighlight> |
</syntaxhighlight> |
||
Line 43: | Line 44: | ||
* Host reads e.g. register <code>R1</code> to find the address of the format string. |
* Host reads e.g. register <code>R1</code> to find the address of the format string. |
||
* Host reads the format string from target memory into host memory, up to and including the terminating null character. |
* Host reads the format string from target memory into host memory, up to and including the terminating null character. |
||
− | * Host starts formatting the string, sending |
+ | * Host starts formatting the string, sending <code>There are</code> to the console. |
− | * Host recognizes <code>%u</code> format specifier and reads |
+ | * Host recognizes <code>%u</code> format specifier and reads a word (corresponding to the argument) from the processor stack under debug control, in this case 99. |
− | * Host formats the argument, 99, and writes |
+ | * Host formats the argument, 99, and writes <code>99</code> to the console. |
− | * Host continues and copies |
+ | * Host continues and copies <code> bottles of </code> to the console. |
* Host recognizes <code>%s</code> format specifier and reads an pointer value from the processor stack under debug control. |
* Host recognizes <code>%s</code> format specifier and reads an pointer value from the processor stack under debug control. |
||
− | * Host reads string using that pointer as |
+ | * Host reads zero-terminated string using that pointer as the base address and copies <code>beer</code> to the console. |
− | * Host |
+ | * Host continues and copies <code> on the wall</code> to the console. |
+ | * Host finds end of control string and writes an "success" result to e.g. register <code>R0</code>. |
||
* Host restarts program execution on the target. |
* Host restarts program execution on the target. |
||
* Target continues execution. |
* Target continues execution. |
Latest revision as of 09:07, 27 May 2021
Host-based formatting is a technology that reduces the on-target code and data size associated with typical semihosting.
Contents
Classic semihosting
Many embedded system development tools offer support for Semihosting where a host computer system provides I/O and other services to an embedded target. Semihosting is typically used during product development and is not included as part of the embedded system's code when the product is released.
Typical semihosting provides very simple I/O functions such as reading and writing characters to the terminal and to files. Such an implementation requires target code on the embedded system that implements the C-based format specifications used in calls to printf
and scanf
. This code is typically bulky even after eliminating floating-point I/O: 2k to 4k of code can be brought into the application just to support printf
which will not be present in the production code.
Host-based formatting
For MCUs with very small amounts of flash and RAM, debug messages delivered through semihosting can be an unacceptable burden, consuming most of the flash and RAM space of the target thereby leaving very little space for the application. For instance, MSP430 processors can have as little as 256 bytes of RAM and 1 KiB of flash. Usually a PCB would be populated with a larger device for product development to enable larger debug builds to be programmed into the flash. However, some device families do not offer larger memory versions that could be used for development and, therefore, reducing the footprint of debug code is essential for the application to fit.
Advantages
Host-based formatting shifts the burden of formatting from the target system, where resources are limited, to the host system, where resources are plentiful. The host system supports all formatting specifications (such as width, precision, text alignment, floating point, and so on) simply because it has ample resources to do so. In this scenario the target footprint for printf
, for instance, is no more than a few instructions to issue a semihosting call and have the debug agent perform the semihosting operation.
Implementation details
The following is the implementation of printf
using the SEGGER Runtime Library using host-based formatting for semihosting:
int printf(const char *fmt, ...) {
return __do_debug_operation(DEBOP_PRINTF, &fmt);
}
The debugger or host agent identifies the semihosting request from the target (see the Semihosting page for details) and proceeds to service the request. It will first identify the parameters of the semihosting call: the debug operation and the incoming C arguments. With access to all of memory through the debug probe it can find the address of the format string, read the format string from memory under debug control, and format the output "virtually" on the host, taking arguments from the target's memory or registers, as needed, under debug control.
Worked example
With host-based formatting, the call...
printf("There are %u bottles of %s on the wall", 99, "beer");
...would be processed, in detail, as follows:
- Target calls
printf
with format string address in a register and additional arguments typically passed on processor stack. - Target execution enters
printf
and immediately requests a semihosting call (e.g. using breakpoint). - Host recognizes semihosting requests and proceeds to service it with the target halted.
- Host decodes the semihosting operation e.g. register
R0
and identifies it as aprintf
request. - Host reads e.g. register
R1
to find the address of the format string. - Host reads the format string from target memory into host memory, up to and including the terminating null character.
- Host starts formatting the string, sending
There are
to the console. - Host recognizes
%u
format specifier and reads a word (corresponding to the argument) from the processor stack under debug control, in this case 99. - Host formats the argument, 99, and writes
99
to the console. - Host continues and copies
bottles of
to the console. - Host recognizes
%s
format specifier and reads an pointer value from the processor stack under debug control. - Host reads zero-terminated string using that pointer as the base address and copies
beer
to the console. - Host continues and copies
on the wall
to the console. - Host finds end of control string and writes an "success" result to e.g. register
R0
. - Host restarts program execution on the target.
- Target continues execution.
The semihosting call is now complete.