diff --git a/doc/reference/misc/formatted_output.rst b/doc/reference/misc/formatted_output.rst index ccca29200e9..7bb0ce2a2f3 100644 --- a/doc/reference/misc/formatted_output.rst +++ b/doc/reference/misc/formatted_output.rst @@ -40,6 +40,84 @@ In addition :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 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 :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 can only create a package that is known to have no string + arguments (``%s``). :c:macro:`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: + +* :option:`CONFIG_CBPRINTF_PACKAGE_LONGDOUBLE` +* :option:`CONFIG_CBPRINTF_STATIC_PACKAGE_CHECK_ALIGNMENT` + +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 | 1 byte: Argument list size including header and *fmt* (in 32 bit words) | +| +-------------------------------------------------------------------------+ +| | sizeof(void \*)| 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 | 1 byte: Index within the package to the location of associated argument | +| +-------------------------------------------------------------------------+ +| strings | Null terminated string | +| +-------------------------------------------------------------------------+ +| | ... | ++------------------+-------------------------------------------------------------------------+ + .. warning:: If :option:`CONFIG_MINIMAL_LIBC` is selected in combination with