This KB article presents a series of questions and answers related to the functionality and limitations of the am_util_stdio_printf() function used in the AmbiqSuite SDK, and highlights several differences compared to the standard printf() function.
The am_util_stdio_printf() function provided in the Ambiq Micro SDK seems to have limitations. Can these limitations be fixed?
The am_util_stdio_printf() performs as originally designed. It was designed to be a slimmed-down version of the standard C printf() that can be used for general debugging while maintaining a small footprint in non-volatile memory and RAM. By design it is purposely not a full, complete version of the standard function.
What does am_util_stdio_printf() support?
Please reference the following format syntax as used in the standard printf() function:
type field: The following common type specifiers are supported (shown with the ‘%’ prefix).
- %c Character
- %s Null-terminated string
- %x Lower case hex
- %X Upper case hex
- %u Unsigned integer
- %d or %i Signed integer
- %f, %F Float
- %ll Long long (double long)
Any other specifier will simply print the character following the ‘%’. e.g. ‘%%’ will print the character ‘%’, ‘%9’ the character ‘9’.
Zero (0): Zero extend the output.
Minus sign (-): Only supported with the %s specifier. If a minus sign is given with a width for any other specifier, the minus sign is simply ignored. If given with %s (e.g. %[-width]s), the string is left-aligned and padded on the right. If omitted (e.g. %[width]s), the string is right-aligned.
Supported for the %d, %i, %u, %x, %X specifiers.
An integer specifying the minimum number of characters to be output. Truncation does not occur, thus more characters can be output if the specified width is not large enough.
Only supported with %f, %F specifiers. e.g. %[.precision]f
When supplied, the precision field will generally limit the number of characters output. So for %f, specifies the number of digits to the right of the decimal point.
Specific to this implementation: By default if no precision value is given, the precision for %f is set to 6.
Summary of supported specifiers and fields:
How much output will am_util_stdio_printf() support?
As shipped in the SDK, an internal buffer limits the output to 256 characters total. This buffer size can be modified via the AM_PRINTF_BUFSIZE define found in am_util_stdio.h. Note that no overflow protection is provided. Therefore if the total number of characters output exceeds this value, the buffer will overflow.
One way to overflow the printf buffer is by using the %s specifier to print large strings.
How does am_util_stdio_printf() handle line endings?
By default, the functions do nothing special with ‘\n’ line endings. This behavior works as expected with most standard terminals (or at a minimum, most terminals can be configured to convert ‘\n’ to ‘\r\n’).
The default behavior of line ending conversion can be changed via the am_util_stdio_textmode_set() function. Calling this function with a true argument will change the behavior such that the function converts ‘\n’ characters to ‘\r\n’. This conversion has the side effect of counting as 2 characters in the output buffer. Thus a string with 10 lines will consume 10 additional characters in the buffer than it otherwise would.
What other functions are supported?
Other functions supported by am_util_stdio include:
as well as the implementation-specific functions:
What is the return value for am_util_stdio_printf() or am_util_stdio_sprintf()?
As with the standard printf(), the function returns the total number of characters printed or placed in the user's buffer.
What does the implementation-specific am_util_printf_init() function do?
This function must be called before am_util_stdio_printf(), otherwise nothing will actually print. It specifies a print function to be called for a given print interface, which is typically handled in the BSP. Two common print interfaces are SWO and UART. For an example of how these two print interfaces are used in am_util_printf_init(), see the hello_world and/or hello_world_uart examples included in the SDK.
Why is it that when I attempt to print a floating point number, the rounding and/or accuracy is incorrect?
This is a known limitation of am_util_stdio_printf(), which is designed and intended to be a small footprint implementation of the full function. Integrating full floating point support would greatly increase the footprint.
In this implementation, floating round up errors are especially prevalent when rounding up to a number with more digits than exist to the left of the decimal. For example, 1.99 will round up to 2.00, but 9.99 may not round up to 10.00, or 99.99 may not round up to 100.00.
The floating point implementation is accurate to only about 6 decimal places, hence the default precision of 6 places previously as mentioned.
For additional information about the AmbiqSuite SDK implementation of floating point, please see the static function ftoa() in am_util_stdio.c, particularly the error return values of AM_FTOA_ERR_xxx.
What if I absolutely need other printf() formatting capabilities or full floating point support?
Most toolchains come with their own library implementations of printf() which supports the full implementation. Ambiq suggests you look into the stdio library for your particular toolchain.
Article is closed for comments.