Formatted Output
Applications as well as Zephyr itself requires infrastructure to format
values for user consumption. The standard C99 library *printf()
functionality fulfills this need for streaming output devices or memory
buffers, but in an embedded system devices may not accept streamed data
and memory may not be available to store the formatted output.
Internal Zephyr API traditionally provided this both for
printk()
and for Zephyr’s internal minimal libc, but with
separate internal interfaces. Logging, tracing, shell, and other
applications made use of either these APIs or standard libc routines
based on build options.
The cbprintf()
public APIs convert C99 format strings and
arguments, providing output produced one character at a time through a
callback mechanism, replacing the original internal functions and
providing support for almost all C99 format specifications. Existing
use of s*printf()
C libraries in Zephyr can be converted to
snprintfcb()
to avoid pulling in libc implementations.
Several Kconfig options control the set of features that are enabled, allowing some control over features and memory usage:
CONFIG_CBPRINTF_LIBC_SUBSTS
can be used to provide functions
that behave like standard libc functions but use the selected cbprintf
formatter rather than pulling in another formatter from libc.
In addition CONFIG_CBPRINTF_NANO
can be used to revert back to
the very space-optimized but limited formatter used for printk()
before this capability was added.
Cbprintf Packaging
Typically, strings are formatted synchronously when a function from printf
family is called. However, there are cases when it is beneficial that formatting
is deferred. In that case, a state (format string and arguments) must be captured.
Such state forms a self-contained package which contains format string and
arguments. Additionally, package contains copies of all strings which are
part of a format string (format string or any %s
argument) and are identifed
as the one located in the read write memory. Package primary content resembles
va_list stack frame thus standard formatting functions are used to process a
package. Since package contains data which is processed as va_list frame,
strict alignment must be maintained. Due to required padding, size of the
package depends on alignment. When package is copied, it should be copied to a
memory block with the same alignment as origin.
Package can be created using two methods:
runtime - using
cbprintf_package()
orcbvprintf_package()
. This method scans format string and based on detected format specifiers builds the package.static - types of arguments are detected at compile time by the preprocessor and package is created as simple assignments to a provided memory. This method is significantly faster than runtime (more than 15 times) but has following limitations: requires
_Generic
keyword (C11 feature) to be supported by the compiler and can only create a package that is known to have no string arguments (%s
).CBPRINTF_MUST_RUNTIME_PACKAGE
can be used to determine at compile time if static packaging can be applied. Macro determines need for runtime packaging based on presence of char pointers in the argument list so there are cases when it will be false positive, e.g.%p
with char pointer.
Several Kconfig options control behavior of the packaging:
Cbprintf package format
Format of the package contains paddings which are platform specific. Package consists of header which contains size of package (excluding appended strings) and number of appended strings. It is followed by the arguments which contains alignment paddings and resembles va_list stack frame. Finally, package optionally contains appended strings. Each string contains 1 byte header which contains index of the location where address argument is stored. During packaging address is set to null and before string formatting it is updated to point to the current string location within the package. Updating address argument must happen just before string formatting since address changes whenever package is copied.
Header sizeof(void *)
|
1 byte: Argument list size including header and fmt (in 32 bit words) |
1 byte: Number of appended strings |
|
platform specific padding to sizeof(void *) |
|
Arguments |
Pointer to fmt (or null if fmt is appended to the package) |
(optional padding for platform specific alignment) |
|
argument 0 |
|
(optional padding for platform specific alignment) |
|
argument 1 |
|
… |
|
Appended strings |
1 byte: Index within the package to the location of associated argument |
Null terminated string |
|
… |
Warning
If CONFIG_MINIMAL_LIBC
is selected in combination with
CONFIG_CBPRINTF_NANO
formatting with C standard library
functions like printf
or snprintf
is limited. Among other
things the %n
specifier, most format flags, precision control, and
floating point are not supported.
API Reference
- group cbprintf_apis
Defines
-
CBPRINTF_PACKAGE_ALIGNMENT
Required alignment of the buffer used for packaging.
-
CBPRINTF_MUST_RUNTIME_PACKAGE(skip, flags, ...)
Determine if string must be packaged in run time.
Static packaging can be applied if size of the package can be determined at compile time. In general, package size can be determined at compile time if there are no string arguments which might be copied into package body if they are considered transient.
Note
By default any char pointers are considered to be pointing at transient strings. This can be narrowed down to non const pointers by using CBPRINTF_MUST_RUNTIME_PACKAGE_CONST_CHAR.
- Parameters
skip – number of read only string arguments in the parameter list. It shall be non-zero if there are known read only string arguments present in the string (e.g. function name prefix in the log message).
... – String with arguments.
flags – option flags. See Package flags..
- Return values
1 – if string must be packaged in run time.
0 – string can be statically packaged.
-
CBPRINTF_STATIC_PACKAGE(packaged, inlen, outlen, align_offset, flags, ...)
Statically package string.
Build string package from formatted string. It assumes that formatted string is in the read only memory.
If _Generic is not supported then runtime packaging is performed.
- Parameters
packaged – pointer to where the packaged data can be stored. Pass a null pointer to skip packaging but still calculate the total space required. The data stored here is relocatable, that is it can be moved to another contiguous block of memory. It must be aligned to the size of the longest argument. It is recommended to use CBPRINTF_PACKAGE_ALIGNMENT for alignment.
inlen – set to the number of bytes available at
packaged
. Ifpackaged
is NULL the value is ignored.outlen – variable updated to the number of bytes required to completely store the packed information. If input buffer was too small it is set to -ENOSPC.
align_offset – input buffer alignment offset in bytes. Where offset 0 means that buffer is aligned to CBPRINTF_PACKAGE_ALIGNMENT. Xtensa requires that
packaged
is aligned to CBPRINTF_PACKAGE_ALIGNMENT so it must be multiply of CBPRINTF_PACKAGE_ALIGNMENT or 0.flags – option flags. See Package flags..
... – formatted string with arguments. Format string must be constant.
Typedefs
-
typedef int (*cbprintf_cb)()
Signature for a cbprintf callback function.
This function expects two parameters:
c
a character to output. The output behavior should be as if this was cast to an unsigned char.ctx
a pointer to an object that provides context for the output operation.
The declaration does not specify the parameter types. This allows a function like
fputc
to be used without requiring all context pointers to be to aFILE
object.- Return
the value of
c
cast to an unsigned char then back to int, or a negative error code that will be returned from cbprintf().
Functions
-
int cbprintf_package(void *packaged, size_t len, uint32_t flags, const char *format, ...)
Capture state required to output formatted data later.
Like cbprintf() but instead of processing the arguments and emitting the formatted results immediately all arguments are captured so this can be done in a different context, e.g. when the output function can block.
In addition to the values extracted from arguments this will ensure that copies are made of the necessary portions of any string parameters that are not confirmed to be stored in read-only memory (hence assumed to be safe to refer to directly later).
- Parameters
packaged – pointer to where the packaged data can be stored. Pass a null pointer to store nothing but still calculate the total space required. The data stored here is relocatable, that is it can be moved to another contiguous block of memory. However, under condition that alignment is maintained. It must be aligned to at least the size of a pointer.
len – this must be set to the number of bytes available at
packaged
if it is not null. Ifpackaged
is null then it indicates hypothetical buffer alignment offset in bytes compared to CBPRINTF_PACKAGE_ALIGNMENT alignment. Buffer alignment offset impacts returned size of the package. Xtensa requires that buffer is always aligned to CBPRINTF_PACKAGE_ALIGNMENT so it must be multiply of CBPRINTF_PACKAGE_ALIGNMENT or 0 whenpackaged
is null.flags – option flags. See Package flags..
format – a standard ISO C format string with characters and conversion specifications.
... – arguments corresponding to the conversion specifications found within
format
.
- Return values
nonegative – the number of bytes successfully stored at
packaged
. This will not exceedlen
.-EINVAL – if
format
is not acceptable-EFAULT – if
packaged
alignment is not acceptable-ENOSPC – if
packaged
was not null and the space required to store exceedlen
.
-
int cbvprintf_package(void *packaged, size_t len, uint32_t flags, const char *format, va_list ap)
Capture state required to output formatted data later.
Like cbprintf() but instead of processing the arguments and emitting the formatted results immediately all arguments are captured so this can be done in a different context, e.g. when the output function can block.
In addition to the values extracted from arguments this will ensure that copies are made of the necessary portions of any string parameters that are not confirmed to be stored in read-only memory (hence assumed to be safe to refer to directly later).
- Parameters
packaged – pointer to where the packaged data can be stored. Pass a null pointer to store nothing but still calculate the total space required. The data stored here is relocatable, that is it can be moved to another contiguous block of memory. The pointer must be aligned to a multiple of the largest element in the argument list.
len – this must be set to the number of bytes available at
packaged
. Ignored ifpackaged
is NULL.flags – option flags. See Package flags..
format – a standard ISO C format string with characters and conversion specifications.
ap – captured stack arguments corresponding to the conversion specifications found within
format
.
- Return values
nonegative – the number of bytes successfully stored at
packaged
. This will not exceedlen
.-EINVAL – if
format
is not acceptable-ENOSPC – if
packaged
was not null and the space required to store exceedlen
.
-
int cbprintf_fsc_package(void *in_packaged, size_t in_len, void *packaged, size_t len)
Convert package to fully self-contained (fsc) package.
By default, package does not contain read only strings. However, if needed it may be converted to a fully self-contained package which contains all strings. In order to allow such conversion, original package must be created with CBPRINTF_PACKAGE_ADD_STRING_IDXS flag. Such package will contain necessary data to find read only strings in the package and copy them into package body.
- Parameters
in_packaged – pointer to original package created with CBPRINTF_PACKAGE_ADD_STRING_IDXS.
in_len –
in_packaged
length.packaged – pointer to location where fully self-contained version of the input package will be written. Pass a null pointer to calculate space required.
len – must be set to the number of bytes available at
packaged
. Not used ifpackaged
is null.
- Return values
nonegative – the number of bytes successfully stored at
packaged
. This will not exceedlen
. Ifpackaged
is null, calculated length.-ENOSPC – if
packaged
was not null and the space required to store exceedlen
.-EINVAL – if
in_packaged
is null.
-
int cbpprintf(cbprintf_cb out, void *ctx, void *packaged)
Generate the output for a previously captured format operation.
Note
Memory indicated by
packaged
will be modified in a non-destructive way, meaning that it could still be reused with this function again.- Parameters
out – the function used to emit each generated character.
ctx – context provided when invoking out
packaged – the data required to generate the formatted output, as captured by cbprintf_package() or cbvprintf_package(). The alignment requirement on this data is the same as when it was initially created.
- Returns
the number of characters printed, or a negative error value returned from invoking
out
.
-
int cbprintf(cbprintf_cb out, void *ctx, const char *format, ...)
*printf-like output through a callback.
This is essentially printf() except the output is generated character-by-character using the provided
out
function. This allows formatting text of unbounded length without incurring the cost of a temporary buffer.All formatting specifiers of C99 are recognized, and most are supported if the functionality is enabled.
Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
out – the function used to emit each generated character.
ctx – context provided when invoking out
format – a standard ISO C format string with characters and conversion specifications.
... – arguments corresponding to the conversion specifications found within
format
.
- Returns
the number of characters printed, or a negative error value returned from invoking
out
.
-
int cbvprintf(cbprintf_cb out, void *ctx, const char *format, va_list ap)
varargs-aware *printf-like output through a callback.
This is essentially vsprintf() except the output is generated character-by-character using the provided
out
function. This allows formatting text of unbounded length without incurring the cost of a temporary buffer.Note
This function is available only when
CONFIG_CBPRINTF_LIBC_SUBSTS
is selected.Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
out – the function used to emit each generated character.
ctx – context provided when invoking out
format – a standard ISO C format string with characters and conversion specifications.
ap – a reference to the values to be converted.
- Returns
the number of characters generated, or a negative error value returned from invoking
out
.
-
int fprintfcb(FILE *stream, const char *format, ...)
fprintf using Zephyrs cbprintf infrastructure.
return The number of characters printed.
Note
This function is available only when
CONFIG_CBPRINTF_LIBC_SUBSTS
is selected.Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
stream – the stream to which the output should be written.
format – a standard ISO C format string with characters and conversion specifications.
... – arguments corresponding to the conversion specifications found within
format
.
-
int vfprintfcb(FILE *stream, const char *format, va_list ap)
vfprintf using Zephyrs cbprintf infrastructure.
Note
This function is available only when
CONFIG_CBPRINTF_LIBC_SUBSTS
is selected.Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
stream – the stream to which the output should be written.
format – a standard ISO C format string with characters and conversion specifications.
ap – a reference to the values to be converted.
- Returns
The number of characters printed.
-
int printfcb(const char *format, ...)
printf using Zephyrs cbprintf infrastructure.
Note
This function is available only when
CONFIG_CBPRINTF_LIBC_SUBSTS
is selected.Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
format – a standard ISO C format string with characters and conversion specifications.
... – arguments corresponding to the conversion specifications found within
format
.
- Returns
The number of characters printed.
-
int vprintfcb(const char *format, va_list ap)
vprintf using Zephyrs cbprintf infrastructure.
Note
This function is available only when
CONFIG_CBPRINTF_LIBC_SUBSTS
is selected.Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
format – a standard ISO C format string with characters and conversion specifications.
ap – a reference to the values to be converted.
- Returns
The number of characters printed.
-
int snprintfcb(char *str, size_t size, const char *format, ...)
snprintf using Zephyrs cbprintf infrastructure.
Note
This function is available only when
CONFIG_CBPRINTF_LIBC_SUBSTS
is selected.Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
str – where the formatted content should be written
size – maximum number of chaacters for the formatted output, including the terminating null byte.
format – a standard ISO C format string with characters and conversion specifications.
... – arguments corresponding to the conversion specifications found within
format
.
- Returns
The number of characters that would have been written to
str
, excluding the terminating null byte. This is greater than the number actually written ifsize
is too small.
-
int vsnprintfcb(char *str, size_t size, const char *format, va_list ap)
vsnprintf using Zephyrs cbprintf infrastructure.
Note
This function is available only when
CONFIG_CBPRINTF_LIBC_SUBSTS
is selected.Note
The functionality of this function is significantly reduced when
CONFIG_CBPRINTF_NANO
is selected.- Parameters
str – where the formatted content should be written
size – maximum number of chaacters for the formatted output, including the terminating null byte.
format – a standard ISO C format string with characters and conversion specifications.
ap – a reference to the values to be converted.
- Returns
The number of characters that would have been written to
str
, excluding the terminating null byte. This is greater than the number actually written ifsize
is too small.
-
CBPRINTF_PACKAGE_ALIGNMENT