Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
28 changes: 17 additions & 11 deletions platform/source/minimal-printf/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,22 @@ Floating point limitations:
* All floating points are treated as %f.
* No support for inf, infinity or nan

## Usage


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` with the value `minimal-printf` as shown below:

```json
"target_overrides": {
"*": {
"target.printf": "minimal-printf",
}
}
```


## Configuration


Expand Down Expand Up @@ -60,24 +76,14 @@ In mbed_app.json:
```json
"target_overrides": {
"*": {
"target.printf": "minimal-printf",
"platform.minimal-printf-enable-floating-point": false,
"platform.minimal-printf-set-floating-point-max-decimals": 6,
"platform.minimal-printf-enable-64-bit": false
}
}
```

## Usage


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

Compile with mbed-cli using the custom `minimal-printf` profile. For example, to compile in release mode:

```
$ mbed compile -t <toolchain> -m <target> --profile release --profile mbed-os/tools/profiles/extensions/minimal-printf.json
```

## Size comparison


Expand Down
1 change: 1 addition & 0 deletions targets/targets.json
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
"default_lib": "std",
"bootloader_supported": false,
"static_memory_defines": true,
"printf_lib": "std",
"config": {
"console-uart": {
"help": "Target has UART console on pins STDIO_UART_TX, STDIO_UART_RX. Value is only significant if target has SERIAL device.",
Expand Down
87 changes: 87 additions & 0 deletions tools/test/toolchains/test_toolchains.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
#!/usr/bin/env python
# Copyright (c) 2019 Arm Limited and Contributors. All rights reserved.
#
# SPDX-License-Identifier: Apache-2.0

"""Test the arm toolchain."""

import os
import sys
from unittest import TestCase

import mock


ROOT = os.path.abspath(
os.path.join(os.path.dirname(__file__), "..", "..", "..")
)
sys.path.insert(0, ROOT)

from tools.toolchains.arm import ARM_STD, ARM_MICRO, ARMC6
from tools.toolchains.gcc import GCC_ARM
from tools.toolchains.iar import IAR


class TestArmToolchain(TestCase):
"""Test Arm classes."""

def test_arm_minimal_printf(self):
"""Test that linker flags are correctly added to an instance of ARM."""
mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4"
mock_target.printf_lib = "minimal-printf"
mock_target.supported_toolchains = ["ARM", "uARM", "ARMC5"]

arm_std_obj = ARM_STD(mock_target)
arm_micro_obj = ARM_MICRO(mock_target)
arm_c6_obj = ARMC6(mock_target)

self.assertIn("-DMBED_MINIMAL_PRINTF", arm_std_obj.flags["common"])
self.assertIn("-DMBED_MINIMAL_PRINTF", arm_micro_obj.flags["common"])
self.assertIn("-DMBED_MINIMAL_PRINTF", arm_c6_obj.flags["common"])


class TestGccToolchain(TestCase):
"""Test the GCC class."""

def test_gcc_minimal_printf(self):
"""Test that linker flags are correctly added to an instance of GCC_ARM."""
mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4"
mock_target.printf_lib = "minimal-printf"
mock_target.supported_toolchains = ["GCC_ARM"]
mock_target.is_TrustZone_secure_target = False

gcc_obj = GCC_ARM(mock_target)

self.assertIn("-DMBED_MINIMAL_PRINTF", gcc_obj.flags["common"])

minimal_printf_wraps = [
"-Wl,--wrap,printf",
"-Wl,--wrap,sprintf",
"-Wl,--wrap,snprintf",
"-Wl,--wrap,vprintf",
"-Wl,--wrap,vsprintf",
"-Wl,--wrap,vsnprintf",
"-Wl,--wrap,fprintf",
"-Wl,--wrap,vfprintf",
]

for i in minimal_printf_wraps:
self.assertIn(i, gcc_obj.flags["ld"])


class TestIarToolchain(TestCase):
"""Test the IAR class."""

def test_iar_minimal_printf(self):
"""Test that linker flags are correctly added to an instance of GCC_ARM."""
mock_target = mock.MagicMock()
mock_target.core = "Cortex-M4"
mock_target.printf_lib = "minimal-printf"
mock_target.supported_toolchains = ["IAR"]
mock_target.is_TrustZone_secure_target = False

iar_obj = IAR(mock_target)
var = "-DMBED_MINIMAL_PRINTF"
self.assertIn("-DMBED_MINIMAL_PRINTF", iar_obj.flags["common"])
5 changes: 5 additions & 0 deletions tools/toolchains/arm.py
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,8 @@ def __init__(self, target, notify=None, macros=None,
if "--library_type=microlib" not in self.flags['common']:
self.flags['common'].append("--library_type=microlib")

self.check_and_add_minimal_printf(target)

cpu = {
"Cortex-M0+": "Cortex-M0plus",
"Cortex-M4F": "Cortex-M4.fp.sp",
Expand Down Expand Up @@ -568,6 +570,8 @@ def __init__(self, target, *args, **kwargs):
if "--library_type=microlib" not in self.flags['asm']:
self.flags['asm'].append("--library_type=microlib")

self.check_and_add_minimal_printf(target)

if target.is_TrustZone_secure_target:
if kwargs.get('build_dir', False):
# Output secure import library
Expand Down Expand Up @@ -767,3 +771,4 @@ def get_binary_commands(self, bin_arg, bin, elf):
cmd.insert(1, "--ide=mbed")

return cmd

20 changes: 20 additions & 0 deletions tools/toolchains/gcc.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,26 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
self.flags["common"].append("-DMBED_RTOS_SINGLE_THREAD")
self.flags["ld"].append("--specs=nano.specs")

self.check_and_add_minimal_printf(target)

if getattr(target, "printf_lib", "std") == "minimal-printf":
minimal_printf_wraps = [
"-Wl,--wrap,printf",
"-Wl,--wrap,sprintf",
"-Wl,--wrap,snprintf",
"-Wl,--wrap,vprintf",
"-Wl,--wrap,vsprintf",
"-Wl,--wrap,vsnprintf",
"-Wl,--wrap,fprintf",
"-Wl,--wrap,vfprintf",
]

# Add the linker option to wrap the f\v\s\printf functions if not
# already added.
for minimal_printf_wrap in minimal_printf_wraps:
if minimal_printf_wrap not in self.flags["ld"]:
self.flags["ld"].append(minimal_printf_wrap)

self.cpu = []
if target.is_TrustZone_secure_target:
# Enable compiler security extensions
Expand Down
2 changes: 2 additions & 0 deletions tools/toolchains/iar.py
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,8 @@ def __init__(self, target, notify=None, macros=None, build_profile=None,
define_string = self.make_ld_define("DOMAIN_NS", "0x1")
self.flags["ld"].append(define_string)

self.check_and_add_minimal_printf(target)

core = target.core_without_NS
cpu = {
"Cortex-M7F": "Cortex-M7.fp.sp",
Expand Down
8 changes: 8 additions & 0 deletions tools/toolchains/mbed_toolchain.py
Original file line number Diff line number Diff line change
Expand Up @@ -1086,6 +1086,14 @@ def dump_build_profile(self):
self._overwrite_when_not_equal(where, json.dumps(
to_dump, sort_keys=True, indent=4))

def check_and_add_minimal_printf(self, target):
"""Add toolchain flag if minimal-printf is selected."""
if (
getattr(target, "printf_lib", "std") == "minimal-printf"
and "-DMBED_MINIMAL_PRINTF" not in self.flags["common"]
):
self.flags["common"].append("-DMBED_MINIMAL_PRINTF")

@staticmethod
def _overwrite_when_not_equal(filename, content):
if not exists(filename) or content != open(filename).read():
Expand Down