mbed-os/features/minimal-printf
Bogdan Marinescu c6cac23960 Implementation fixes
The printf(3) man page says "The functions snprintf() and vsnprintf() do
not write more than size bytes (including the terminating null byte
('\0')).  If the output was truncated due to this limit, then the return
value is the number of characters (excluding the terminating null byte)
which would have been written to the final string if enough space had been
available." The last part of this spec (returning the number of
characters which would have been written to the string if enough space
had been available) was not implemented in minimal-printf. This PR
changes that by redirecting all the processed characters through the
"minimal_printf_putchar" helper function. This function will not write
to the buffer if there's no space left, but it will always increment the
number of written characters, in order to match the above description.
minimal_printf_putchar also contains checks for overflows, so these
checks are no longer needed in the rest of the code.

Other changes:

- In some cases, mbed_minimal_formatted_string didn't put the string
  terminator in the output buffer. This PR ensures that this always
  happens.
- Fixed a bug in printed hexadecimal numbers introduced by a previous
  commit.
- Added buffer overflow tests for snprintf.
2018-04-26 13:37:33 +03:00
..
TESTS/minimal-printf/compliance Implementation fixes 2018-04-26 13:37:33 +03:00
profiles Add "-g" to 'release' and 'develop' profiles 2017-10-30 19:10:19 +02:00
README.md Add compile profiles 2017-10-27 14:44:31 +03:00
mbed_lib.json Fix file permissions 2017-10-26 13:41:32 -07:00
mbed_printf.c Add support for width specifiers 2017-10-26 07:28:15 -07:00
mbed_printf.h Fix file permissions 2017-10-26 13:41:32 -07:00
mbed_printf_implementation.c Implementation fixes 2018-04-26 13:37:33 +03:00
mbed_printf_implementation.h Add test case 2017-10-26 08:56:00 -07:00
mbed_printf_wrapper.c Add support for width specifiers 2017-10-26 07:28:15 -07:00

README.md

Minimal printf and snprintf

Library supports both printf and snprintf in 1252 bytes of flash.

Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored. Floating point is disabled by default.

Supports:

  • %d: signed integer [h, hh, (none), l, ll, z, j, t].
  • %i: signed integer [h, hh, (none), l, ll, z, j, t].
  • %u: unsigned integer [h, hh, (none), l, ll, z, j, t].
  • %x: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., FF).
  • %X: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., FF).
  • %f: floating point (disabled by default).
  • %F: floating point (disabled by default).
  • %g: floating point (disabled by default).
  • %G: floating point (disabled by default).
  • %c: character.
  • %s: string.
  • %p: pointer (e.g. 0x00123456).

To replace the standard implementations of the printf functions with the ones in this library:

  • Add the library to your project.
  • Compile with mbed-cli using one of the custom profiles in the profiles/ subdirectory. For example, to compile in release mode:
$ mbed compile -t <toolchain> -m <target> --profile mbed-printf/profiles/release.json

Enabling floating point, 64 bit integers, new line conversion, and setting baud rate

In mbed_app.json:

    "target_overrides": {
        "*": {
            "platform.stdio-baud-rate": 115200,
            "platform.stdio-convert-newlines": false,
            "minimal-printf.enable-floating-point": false,
            "minimal-printf.set-floating-point-max-decimals": 6,
            "minimal-printf.enable-64-bit": true
        }
    }

Size comparison

Example application compiled with minimal mbed OS (no RTOS) using this .mbedignore:

mbed-os/rtos/*
mbed-os/features/FEATURE_LWIP/*
mbed-os/features/FEATURE_CLIENT/*
mbed-os/features/FEATURE_COMMON_PAL/*
mbed-os/features/FEATURE_UVISOR/*
mbed-os/features/frameworks/*
mbed-os/features/net/*
mbed-os/features/netsocket/*
mbed-os/features/storage/*
mbed-os/events/*

Example application

#include "mbed.h"
#include "mbed_printf.h"
#include <limits.h>

int main()
{
    char buffer[1000];
    int result;

    double pi = 3.14159265359;

#if 0
    result = printf("hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh", pi);
    printf("results: %d\r\n", result);

    result = snprintf(buffer, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi);
    printf("%s\r\n", buffer);

    printf("results: %d\r\n", result);

#else
    result = mbed_printf("hello world %ld %llu %02X %p %s %2.5f %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh", pi);
    mbed_printf("results: %d\r\n", result);

    result = mbed_snprintf(buffer, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi);
    mbed_printf("%s\r\n", buffer);

    mbed_printf("results: %d\r\n", result);
#endif
}

Full application size on K64F/GCC

Floating point 64 bit integers Flash RAM
mbed-printf 7772 2752
mbed-printf X 8708 2752
mbed-printf X 10368 2752
mbed-printf X X 11360 2752
std printf X X 37354 5364