mirror of https://github.com/ARMmbed/mbed-os.git
Merge pull request #12233 from bulislaw/minimal_printf_default
Enable minimal-printf by default for all buildspull/12613/head
commit
33f3049286
|
@ -116,14 +116,15 @@ Case cases[] = {
|
||||||
Case("C strings: %u %d integer formatting", test_case_c_string_u_d, greentea_failure_handler),
|
Case("C strings: %u %d integer formatting", test_case_c_string_u_d, greentea_failure_handler),
|
||||||
Case("C strings: %x %E integer formatting", test_case_c_string_x_X, greentea_failure_handler),
|
Case("C strings: %x %E integer formatting", test_case_c_string_x_X, greentea_failure_handler),
|
||||||
#if !defined(__NEWLIB_NANO)
|
#if !defined(__NEWLIB_NANO)
|
||||||
//In build tools, GCC with Newlib-nano linker option "-u _printf_float" is not configured
|
// Newlib-nano linker option "-u _printf_float" is not set to enable floating point support.
|
||||||
//to enable printf floating format. So disabling floating format test case.
|
#if (defined(MBED_MINIMAL_PRINTF) && MBED_CONF_PLATFORM_MINIMAL_PRINTF_ENABLE_FLOATING_POINT) || !defined(MBED_MINIMAL_PRINTF)
|
||||||
Case("C strings: %f %f float formatting", test_case_c_string_f_f, greentea_failure_handler),
|
Case("C strings: %f %f float formatting", test_case_c_string_f_f, greentea_failure_handler),
|
||||||
|
#endif
|
||||||
#ifndef MBED_MINIMAL_PRINTF
|
#ifndef MBED_MINIMAL_PRINTF
|
||||||
Case("C strings: %e %E float formatting", test_case_c_string_e_E, greentea_failure_handler),
|
Case("C strings: %e %E float formatting", test_case_c_string_e_E, greentea_failure_handler),
|
||||||
Case("C strings: %g %g float formatting", test_case_c_string_g_g, greentea_failure_handler),
|
Case("C strings: %g %g float formatting", test_case_c_string_g_g, greentea_failure_handler),
|
||||||
#endif
|
#endif // MBED_MINIMAL_PRINTF
|
||||||
#endif
|
#endif // !defined(__NEWLIB_NANO)
|
||||||
};
|
};
|
||||||
|
|
||||||
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
utest::v1::status_t greentea_test_setup(const size_t number_of_cases)
|
||||||
|
|
|
@ -75,7 +75,7 @@ static cmd_status_t handle_command(const char *key, const char *value)
|
||||||
int raw_reason_hex_str_len = snprintf(raw_reason_hex_str,
|
int raw_reason_hex_str_len = snprintf(raw_reason_hex_str,
|
||||||
sizeof raw_reason_hex_str, "%08lx", raw_reason);
|
sizeof raw_reason_hex_str, "%08lx", raw_reason);
|
||||||
|
|
||||||
if (raw_reason_hex_str_len != (sizeof raw_reason_hex_str) - 1) {
|
if (raw_reason_hex_str_len < 0) {
|
||||||
TEST_ASSERT_MESSAGE(0, "Failed to compose raw reset reason hex string.");
|
TEST_ASSERT_MESSAGE(0, "Failed to compose raw reset reason hex string.");
|
||||||
return CMD_STATUS_ERROR;
|
return CMD_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -134,7 +134,7 @@ void test_reset_reason()
|
||||||
hal_reset_reason_get_capabilities(&rrcap);
|
hal_reset_reason_get_capabilities(&rrcap);
|
||||||
char msg_value[11];
|
char msg_value[11];
|
||||||
int str_len = snprintf(msg_value, sizeof msg_value, "%08lx,%01x", rrcap.reasons, MSG_VALUE_WATCHDOG_STATUS);
|
int str_len = snprintf(msg_value, sizeof msg_value, "%08lx,%01x", rrcap.reasons, MSG_VALUE_WATCHDOG_STATUS);
|
||||||
if (str_len != (sizeof msg_value) - 1) {
|
if (str_len < 0) {
|
||||||
printf("Failed to compose a value string to be sent to host.");
|
printf("Failed to compose a value string to be sent to host.");
|
||||||
GREENTEA_TESTSUITE_RESULT(0);
|
GREENTEA_TESTSUITE_RESULT(0);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -92,7 +92,7 @@ bool send_reset_notification(testcase_data *tcdata, uint32_t delay_ms)
|
||||||
{
|
{
|
||||||
char msg_value[12];
|
char msg_value[12];
|
||||||
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
||||||
if (str_len != (sizeof msg_value) - 1) {
|
if (str_len < 0) {
|
||||||
utest_printf("Failed to compose a value string to be sent to host.");
|
utest_printf("Failed to compose a value string to be sent to host.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -75,7 +75,7 @@ static cmd_status_t handle_command(const char *key, const char *value)
|
||||||
int raw_reason_hex_str_len = snprintf(raw_reason_hex_str,
|
int raw_reason_hex_str_len = snprintf(raw_reason_hex_str,
|
||||||
sizeof raw_reason_hex_str, "%08lx", raw_reason);
|
sizeof raw_reason_hex_str, "%08lx", raw_reason);
|
||||||
|
|
||||||
if (raw_reason_hex_str_len != (sizeof raw_reason_hex_str) - 1) {
|
if (raw_reason_hex_str_len < 0) {
|
||||||
TEST_ASSERT_MESSAGE(0, "Failed to compose raw reset reason hex string.");
|
TEST_ASSERT_MESSAGE(0, "Failed to compose raw reset reason hex string.");
|
||||||
return CMD_STATUS_ERROR;
|
return CMD_STATUS_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -129,7 +129,7 @@ void test_reset_reason()
|
||||||
hal_reset_reason_get_capabilities(&rrcap);
|
hal_reset_reason_get_capabilities(&rrcap);
|
||||||
char msg_value[11];
|
char msg_value[11];
|
||||||
int str_len = snprintf(msg_value, sizeof msg_value, "%08lx,%01x", rrcap.reasons, MSG_VALUE_WATCHDOG_STATUS);
|
int str_len = snprintf(msg_value, sizeof msg_value, "%08lx,%01x", rrcap.reasons, MSG_VALUE_WATCHDOG_STATUS);
|
||||||
if (str_len != (sizeof msg_value) - 1) {
|
if (str_len < 0) {
|
||||||
printf("Failed to compose a value string to be sent to host.");
|
printf("Failed to compose a value string to be sent to host.");
|
||||||
GREENTEA_TESTSUITE_RESULT(0);
|
GREENTEA_TESTSUITE_RESULT(0);
|
||||||
return;
|
return;
|
||||||
|
|
|
@ -90,7 +90,7 @@ bool send_reset_notification(testcase_data *tcdata, uint32_t delay_ms)
|
||||||
{
|
{
|
||||||
char msg_value[12];
|
char msg_value[12];
|
||||||
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
||||||
if (str_len != (sizeof msg_value) - 1) {
|
if (str_len < 0) {
|
||||||
utest_printf("Failed to compose a value string to be sent to host.");
|
utest_printf("Failed to compose a value string to be sent to host.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -59,7 +59,7 @@ bool send_reset_notification(testcase_data *tcdata, uint32_t delay_ms)
|
||||||
{
|
{
|
||||||
char msg_value[12];
|
char msg_value[12];
|
||||||
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
||||||
if (str_len != (sizeof msg_value) - 1) {
|
if (str_len < 0) {
|
||||||
utest_printf("Failed to compose a value string to be sent to host.");
|
utest_printf("Failed to compose a value string to be sent to host.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -110,7 +110,7 @@ void test_timing()
|
||||||
|
|
||||||
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", current_case.start_index + current_case.index,
|
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", current_case.start_index + current_case.index,
|
||||||
(uint32_t) current_ts);
|
(uint32_t) current_ts);
|
||||||
if (str_len != (sizeof msg_value) - 1) {
|
if (str_len < 0) {
|
||||||
utest_printf("Failed to compose a value string to be sent to host.");
|
utest_printf("Failed to compose a value string to be sent to host.");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
|
@ -119,7 +119,7 @@ bool send_reset_notification(testcase_data *tcdata, uint32_t delay_ms)
|
||||||
{
|
{
|
||||||
char msg_value[12];
|
char msg_value[12];
|
||||||
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
int str_len = snprintf(msg_value, sizeof msg_value, "%02x,%08lx", tcdata->start_index + tcdata->index, delay_ms);
|
||||||
if (str_len != (sizeof msg_value) - 1) {
|
if (str_len < 0) {
|
||||||
utest_printf("Failed to compose a value string to be sent to host.");
|
utest_printf("Failed to compose a value string to be sent to host.");
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
|
@ -140,15 +140,15 @@
|
||||||
"value": true
|
"value": true
|
||||||
},
|
},
|
||||||
"minimal-printf-enable-64-bit": {
|
"minimal-printf-enable-64-bit": {
|
||||||
"help": "Enable printing 64 bit integers when using mprintf profile",
|
"help": "Enable printing 64 bit integers when using minimal printf library",
|
||||||
"value": true
|
"value": true
|
||||||
},
|
},
|
||||||
"minimal-printf-enable-floating-point": {
|
"minimal-printf-enable-floating-point": {
|
||||||
"help": "Enable floating point printing when using mprintf profile",
|
"help": "Enable floating point printing when using minimal printf library",
|
||||||
"value": false
|
"value": false
|
||||||
},
|
},
|
||||||
"minimal-printf-set-floating-point-max-decimals": {
|
"minimal-printf-set-floating-point-max-decimals": {
|
||||||
"help": "Maximum number of decimals to be printed",
|
"help": "Maximum number of decimals to be printed when using minimal printf library",
|
||||||
"value": 6
|
"value": 6
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
# Minimal printf and snprintf
|
# Minimal printf and snprintf
|
||||||
|
|
||||||
|
|
||||||
Library supports both printf and snprintf in 1252 bytes of flash.
|
Library supports both printf and snprintf in around 1300 bytes of flash.
|
||||||
|
|
||||||
Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored.
|
Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored.
|
||||||
There is no error handling if a writing error occurs.
|
There is no error handling if a writing error occurs.
|
||||||
|
@ -20,6 +20,10 @@ Supports:
|
||||||
* %s: string.
|
* %s: string.
|
||||||
* %p: pointer (e.g. 0x00123456).
|
* %p: pointer (e.g. 0x00123456).
|
||||||
|
|
||||||
|
Note that support for:
|
||||||
|
* 64b modifiers is only present when `minimal-printf-enable-64-bit` config is set to `true` (default).
|
||||||
|
* Floating point parameters is only present when `minimal-printf-enable-floating-point` config is set to `true` (disabled by default).
|
||||||
|
|
||||||
Unrecognized format specifiers are treated as ordinary characters.
|
Unrecognized format specifiers are treated as ordinary characters.
|
||||||
|
|
||||||
Floating point limitations:
|
Floating point limitations:
|
||||||
|
@ -28,8 +32,7 @@ Floating point limitations:
|
||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
|
As of Mbed OS 6.0 this is enabled by default. To replace the standard implementation of the printf functions with the ones in this library for older versions of Mbed:
|
||||||
To replace the standard implementation of the printf functions with the ones in this library:
|
|
||||||
|
|
||||||
Modify your application configuration file to override the parameter `target.printf_lib` with the value `minimal-printf` as shown below:
|
Modify your application configuration file to override the parameter `target.printf_lib` with the value `minimal-printf` as shown below:
|
||||||
|
|
||||||
|
@ -43,6 +46,17 @@ Modify your application configuration file to override the parameter `target.pri
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
If your application requires more advanced functionality, you'll need to revert to using standard version of printf/snprintf. Please note that it will result in significant ROM usage increase. In case you are using minimal version of standard C library advanced functionality may not be present.
|
||||||
|
|
||||||
|
Modify your application configuration in `mbed_app.json` file to override the parameter `target.printf_lib` with the value `std` as shown below:
|
||||||
|
|
||||||
|
```json
|
||||||
|
"target_overrides": {
|
||||||
|
"*": {
|
||||||
|
"target.printf_lib": "std"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## Configuration
|
## Configuration
|
||||||
|
|
||||||
|
@ -54,27 +68,24 @@ Minimal printf is configured by the following parameters defined in `platform/mb
|
||||||
"name": "platform",
|
"name": "platform",
|
||||||
"config": {
|
"config": {
|
||||||
"minimal-printf-enable-64-bit": {
|
"minimal-printf-enable-64-bit": {
|
||||||
"help": "Enable printing 64 bit integers when using minimal-printf profile",
|
"help": "Enable printing 64 bit integers when using minimal printf library",
|
||||||
"value": true
|
"value": true
|
||||||
},
|
},
|
||||||
"minimal-printf-enable-floating-point": {
|
"minimal-printf-enable-floating-point": {
|
||||||
"help": "Enable floating point printing when using minimal-printf profile",
|
"help": "Enable floating point printing when using minimal printf library",
|
||||||
"value": false
|
"value": false
|
||||||
},
|
},
|
||||||
"minimal-printf-set-floating-point-max-decimals": {
|
"minimal-printf-set-floating-point-max-decimals": {
|
||||||
"help": "Maximum number of decimals to be printed",
|
"help": "Maximum number of decimals to be printed when using minimal printf library",
|
||||||
"value": 6
|
"value": 6
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
By default, 64 bit integers support is enabled.
|
By default, 64 bit integers support is enabled, but floating point support is disabled to increase memory savings.
|
||||||
|
|
||||||
If your target does not require some options then you can override the default configuration in your application `mbed_app.json` and achieve further memory optimisation (see next section for size comparison numbers).
|
|
||||||
|
|
||||||
In mbed_app.json:
|
|
||||||
|
|
||||||
|
If your application needs to override the default configuration add following section to your `mbed_app.json`:
|
||||||
```json
|
```json
|
||||||
"target_overrides": {
|
"target_overrides": {
|
||||||
"*": {
|
"*": {
|
||||||
|
|
|
@ -1,5 +1,5 @@
|
||||||
/* mbed Microcontroller Library
|
/* mbed Microcontroller Library
|
||||||
* Copyright (c) 2017 ARM Limited
|
* Copyright (c) 2017-2020 ARM Limited
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*
|
*
|
||||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||||
|
@ -122,17 +122,22 @@ static void mbed_minimal_putchar(char *buffer, size_t length, int *result, char
|
||||||
{
|
{
|
||||||
/* only continue if 'result' doesn't overflow */
|
/* only continue if 'result' doesn't overflow */
|
||||||
if ((*result >= 0) && (*result <= INT_MAX - 1)) {
|
if ((*result >= 0) && (*result <= INT_MAX - 1)) {
|
||||||
/* write data only if there's enough space */
|
if (buffer) {
|
||||||
if ((size_t)*result < length) {
|
/* write data only if there's enough space */
|
||||||
if (buffer) {
|
if ((size_t)*result < length) {
|
||||||
buffer[*result] = data;
|
buffer[*result] = data;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* increment 'result' even if data was not written. This ensures that
|
||||||
|
'mbed_minimal_formatted_string' returns the correct value. */
|
||||||
|
*result += 1;
|
||||||
|
} else {
|
||||||
|
if (fputc(data, stream) == EOF) {
|
||||||
|
*result = EOF;
|
||||||
} else {
|
} else {
|
||||||
fputc(data, stream);
|
*result += 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* increment 'result' even if data was not written. This ensures that
|
|
||||||
'mbed_minimal_formatted_string' returns the correct value. */
|
|
||||||
*result += 1;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -503,6 +508,16 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
|
||||||
/* use 64 bit storage type for readout */
|
/* use 64 bit storage type for readout */
|
||||||
value = va_arg(arguments, MBED_SIGNED_STORAGE);
|
value = va_arg(arguments, MBED_SIGNED_STORAGE);
|
||||||
} else
|
} else
|
||||||
|
#else
|
||||||
|
/* If 64 bit is not enabled, print %ll[di] rather than truncated value */
|
||||||
|
if (length_modifier == LENGTH_LL) {
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, '%', stream);
|
||||||
|
if (next == '%') {
|
||||||
|
// Continue printing loop after `%`
|
||||||
|
index = next_index;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* use native storage type (which can be 32 or 64 bit) */
|
/* use native storage type (which can be 32 or 64 bit) */
|
||||||
|
@ -552,6 +567,16 @@ int mbed_minimal_formatted_string(char *buffer, size_t length, const char *forma
|
||||||
/* use 64 bit storage type for readout */
|
/* use 64 bit storage type for readout */
|
||||||
value = va_arg(arguments, MBED_UNSIGNED_STORAGE);
|
value = va_arg(arguments, MBED_UNSIGNED_STORAGE);
|
||||||
} else
|
} else
|
||||||
|
#else
|
||||||
|
/* If 64 bit is not enabled, print %ll[uxX] rather than truncated value */
|
||||||
|
if (length_modifier == LENGTH_LL) {
|
||||||
|
mbed_minimal_formatted_string_character(buffer, length, &result, '%', stream);
|
||||||
|
if (next == '%') {
|
||||||
|
// Continue printing loop after `%`
|
||||||
|
index = next_index;
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
/* use native storage type (which can be 32 or 64 bit) */
|
/* use native storage type (which can be 32 or 64 bit) */
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
"c_lib": "std",
|
"c_lib": "std",
|
||||||
"bootloader_supported": false,
|
"bootloader_supported": false,
|
||||||
"static_memory_defines": true,
|
"static_memory_defines": true,
|
||||||
"printf_lib": "std",
|
"printf_lib": "minimal-printf",
|
||||||
"supported_c_libs": {
|
"supported_c_libs": {
|
||||||
"arm": [
|
"arm": [
|
||||||
"std"
|
"std"
|
||||||
|
|
Loading…
Reference in New Issue