You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
187 lines
11 KiB
187 lines
11 KiB
.. _formatted_output: |
|
|
|
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 |
|
:c:func:`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 :c:func:`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 |
|
:c:func:`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: |
|
|
|
* :kconfig:option:`CONFIG_CBPRINTF_FULL_INTEGRAL` |
|
or :kconfig:option:`CONFIG_CBPRINTF_REDUCED_INTEGRAL` |
|
* :kconfig:option:`CONFIG_CBPRINTF_FP_SUPPORT` |
|
* :kconfig:option:`CONFIG_CBPRINTF_FP_A_SUPPORT` |
|
* :kconfig:option:`CONFIG_CBPRINTF_FP_ALWAYS_A` |
|
* :kconfig:option:`CONFIG_CBPRINTF_N_SPECIFIER` |
|
|
|
:kconfig:option:`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 :kconfig:option:`CONFIG_CBPRINTF_NANO` can be used to revert back to |
|
the very space-optimized but limited formatter used for :c:func:`printk` |
|
before this capability was added. |
|
|
|
.. _cbprintf_packaging: |
|
|
|
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 may contain copies of strings which are |
|
part of a format string (format string or any ``%s`` argument). 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 have following variants: |
|
|
|
* **Self-contained** - non read-only strings appended to the package. String can be |
|
formatted from such package as long as there is access to read-only string |
|
locations. Package may contain information where read-only strings are located |
|
within the package. That information can be used to convert packet to fully |
|
self-contained package. |
|
* **Fully self-contained** - all strings are appended to the package. String can be |
|
formatted from such package without any external data. |
|
* **Transient**- only arguments are stored. Package contain information |
|
where pointers to non read-only strings are located within the package. Optionally, |
|
it may contain read-only string location information. String can be formatted |
|
from such package as long as non read-only strings are still valid and read-only |
|
strings are accessible. Alternatively, package can be converted to **self-contained** |
|
package or **fully self-contained** if information about read-only string |
|
locations is present in the package. |
|
|
|
Package can be created using two methods: |
|
|
|
* runtime - using :c:func:`cbprintf_package` or :c:func:`cbvprintf_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 cannot distinguish between ``%p`` and ``%s`` if char pointer |
|
is used. It treats all (unsigned) char pointers as ``%s`` thus it will attempt |
|
to append string to a package. It can be handled correctly during conversion |
|
from **transient** package to **self-contained** package using |
|
:c:macro:`CBPRINTF_PACKAGE_CONVERT_PTR_CHECK` flag. However, it requires access |
|
to the format string and it is not always possible thus it is recommended to |
|
cast char pointers used for ``%p`` to ``void *``. There is a logging warning |
|
generated by :c:func:`cbprintf_package_convert` called with |
|
:c:macro:`CBPRINTF_PACKAGE_CONVERT_PTR_CHECK` flag when char pointer is used with |
|
``%p``. |
|
|
|
|
|
Several Kconfig options control behavior of the packaging: |
|
|
|
* :kconfig:option:`CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE` |
|
* :kconfig:option:`CONFIG_CBPRINTF_STATIC_PACKAGE_CHECK_ALIGNMENT` |
|
|
|
Cbprintf package conversion |
|
=========================== |
|
|
|
It is possible to convert package to a variant which contains more information, e.g |
|
**transient** package can be converted to **self-contained**. Conversion to |
|
**fully self-contained** package is possible if :c:macro:`CBPRINTF_PACKAGE_ADD_RO_STR_POS` |
|
flag was used when package was created. |
|
|
|
:c:func:`cbprintf_package_copy` is used to calculate space needed for the new |
|
package and to copy and convert a package. |
|
|
|
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. It is followed by data associated with character |
|
pointer arguments used by the string which are not appended to the string (but may |
|
be appended later by :c:func:`cbprinf_package_convert`). 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 | 1 byte: Argument list size including header and *fmt* (in 32 bit words) | |
|
| +-------------------------------------------------------------------------+ |
|
| sizeof(void \*) | 1 byte: Number of strings appended to the package | |
|
| +-------------------------------------------------------------------------+ |
|
| | 1 byte: Number of read-only string argument locations | |
|
| +-------------------------------------------------------------------------+ |
|
| | 1 byte: Number of transient string argument locations | |
|
| +-------------------------------------------------------------------------+ |
|
| | 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 | |
|
| +-------------------------------------------------------------------------+ |
|
| | ... | |
|
+------------------+-------------------------------------------------------------------------+ |
|
| String location | Indexes of words within the package where read-only strings are located | |
|
| information +-------------------------------------------------------------------------+ |
|
| (optional) | Pairs of argument index and argument location index where transient | |
|
| | strings are located | |
|
+------------------+-------------------------------------------------------------------------+ |
|
| Appended | 1 byte: Index within the package to the location of associated argument | |
|
| strings +-------------------------------------------------------------------------+ |
|
| (optional) | Null terminated string | |
|
| +-------------------------------------------------------------------------+ |
|
| | ... | |
|
+------------------+-------------------------------------------------------------------------+ |
|
|
|
.. warning:: |
|
|
|
If :kconfig:option:`CONFIG_MINIMAL_LIBC` is selected in combination with |
|
:kconfig:option:`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. |
|
|
|
.. _cbprintf_packaging_limitations: |
|
|
|
Limitations and recommendations |
|
=============================== |
|
|
|
* C11 ``_Generic`` support is required by the compiler to use static (fast) packaging. |
|
* It is recommended to cast any character pointer used with ``%p`` format specifier to |
|
other pointer type (e.g. ``void *``). If format string is not accessible then only |
|
static packaging is possible and it will append all detected strings. Character pointer |
|
used for ``%p`` will be considered as string pointer. Copying from unexpected location |
|
can have serious consequences (e.g., memory fault or security violation). |
|
|
|
API Reference |
|
************* |
|
|
|
.. doxygengroup:: cbprintf_apis
|
|
|