Skip to content

Commit 4018753

Browse files
committed
Merge branch 'master-minimal-printf' into minimal-printf
2 parents 9cdfe37 + 1624de2 commit 4018753

File tree

14 files changed

+2841
-0
lines changed

14 files changed

+2841
-0
lines changed

features/minimal-printf/Jenkinsfile

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
// Jenkins configuration.
2+
properties ([
3+
buildDiscarder(
4+
logRotator(artifactDaysToKeepStr: '',
5+
artifactNumToKeepStr: '',
6+
daysToKeepStr: '30',
7+
numToKeepStr: '100'
8+
)
9+
)
10+
])
11+
12+
// RaaS credentials and settings.
13+
raas_username = "ci"
14+
raas_password = "ci"
15+
raas_timeout = 1200
16+
17+
// Test combinations, for each listed target, each toolchain is build and tested on RaaS instance.
18+
targets = [
19+
"K64F": ["toolchains": [ "ARM", "IAR", "GCC_ARM"], "raas": "https://eeva.mbedcloudtesting.com"],
20+
"NUCLEO_F429ZI": ["toolchains": [ "ARM", "IAR", "GCC_ARM"], "raas": "https://ruka.mbedcloudtesting.com"],
21+
]
22+
23+
// Map toolchains to compiler labels to find suitable node on Jenkins.
24+
def nodes = [
25+
ARM: "armcc",
26+
IAR: "iar_arm",
27+
GCC_ARM: "arm-none-eabi-gcc",
28+
SXOS: "linux"
29+
]
30+
31+
// Initial maps for parallel build steps
32+
def buildStepsForParallel = [:]
33+
def testStepsForParallel = [:]
34+
35+
for (target in targets.keySet()) {
36+
for (toolchain_key in targets[target]["toolchains"]) {
37+
echo "Include for build: ${target} ${toolchain_key}"
38+
39+
def stepName = "${target} ${toolchain_key}"
40+
buildStepsForParallel[stepName] = buildStep(target, nodes[toolchain_key], toolchain_key)
41+
}
42+
}
43+
44+
for (target in targets.keySet()) {
45+
for (toolchain_key in targets[target]["toolchains"]) {
46+
echo "Include for test: ${target} ${toolchain_key}"
47+
48+
def stepName = "${target} ${toolchain_key}"
49+
testStepsForParallel[stepName] = testStep(target, nodes[toolchain_key], toolchain_key)
50+
}
51+
}
52+
53+
// Actually run the steps in parallel - parallel takes a map as an argument, hence the above.
54+
timestamps {
55+
parallel buildStepsForParallel
56+
parallel testStepsForParallel
57+
}
58+
59+
// Create build steps for parallel execution.
60+
def buildStep(target, compilerLabel, toolchain) {
61+
return {
62+
stage("Build_${target}_${toolchain}") {
63+
node("${compilerLabel}") {
64+
deleteDir()
65+
66+
echo "buildStep: ${target} ${compilerLabel} ${toolchain}"
67+
dir("test") {
68+
69+
// checkout PR.
70+
checkout scm
71+
72+
// remove wrapper file so we don't compare minimal-printf with itself.
73+
sh "rm ./mbed_printf_wrapper.c"
74+
75+
// checkout newest Mbed OS release.
76+
sh "mbed new ."
77+
78+
// use default release profile for ARM and IAR.
79+
sh "mbed test -vv --compile -m ${target} -t ${toolchain} -n '*minimal-printf*' --build ci --stats-depth 10 --app-config ./TESTS/minimal-printf/compliance/test_app.json"
80+
81+
// stash build directory for testins step.
82+
stash name: "minimal-printf-greentea-${target}-${toolchain}", includes: "ci/**"
83+
}
84+
85+
step([$class: 'WsCleanup'])
86+
}
87+
}
88+
}
89+
}
90+
91+
def testStep(target, compilerLabel, toolchain) {
92+
return {
93+
stage("Light suite ${target}_${toolchain}") {
94+
node("${compilerLabel}") {
95+
deleteDir()
96+
97+
echo "testStep: ${target} ${toolchain}"
98+
99+
// unstash build directory containing greentea tests.
100+
unstash "minimal-printf-greentea-${target}-${toolchain}"
101+
102+
// setup RaaS environment.
103+
env.RAAS_USERNAME = raas_username
104+
env.RAAS_PASSWORD = raas_password
105+
env.RAAS_PYCLIENT_FORCE_REMOTE_ALLOCATION = 1
106+
env.RAAS_PYCLIENT_ALLOCATION_QUEUE_TIMEOUT = raas_timeout
107+
108+
raas = targets[target]["raas"]
109+
110+
// execute greentea on RaaS.
111+
execute("mbedgt -g ${target}:raas_client:${raas}:443 -vV --test-spec ./ci/test_spec.json --polling-timeout 240")
112+
113+
// Clean up workarea.
114+
step([$class: 'WsCleanup'])
115+
}
116+
}
117+
}
118+
}

features/minimal-printf/README.md

Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
# Minimal printf and snprintf
2+
3+
Library supports both printf and snprintf in 1252 bytes of flash.
4+
5+
Prints directly to stdio/UART without using malloc. All flags and precision modifiers are ignored.
6+
Floating point is disabled by default.
7+
Printing to a FILE stream is enabled by default.
8+
9+
Supports:
10+
* %d: signed integer [h, hh, (none), l, ll, z, j, t].
11+
* %i: signed integer [h, hh, (none), l, ll, z, j, t].
12+
* %u: unsigned integer [h, hh, (none), l, ll, z, j, t].
13+
* %x: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., ff).
14+
* %X: unsigned integer [h, hh, (none), l, ll, z, j, t], printed as hexadecimal number (e.g., FF).
15+
* %f: floating point (disabled by default).
16+
* %F: floating point (disabled by default, treated as %f).
17+
* %g: floating point (disabled by default, treated as %f).
18+
* %G: floating point (disabled by default, treated as %f).
19+
* %c: character.
20+
* %s: string.
21+
* %p: pointer (e.g. 0x00123456).
22+
23+
Unrecognized format specifiers are treated as ordinary characters.
24+
25+
Floating point support:
26+
* Floating point is disabled by default.
27+
* All floating points are treated as %f.
28+
* No support for inf, infinity or nan
29+
30+
To replace the standard implementations of the printf functions with the ones in this library:
31+
32+
* Add the library to your project.
33+
* Compile with mbed-cli using one of the custom profiles in the `profiles/` subdirectory. For
34+
example, to compile in release mode:
35+
36+
```
37+
$ mbed compile -t <toolchain> -m <target> --profile mbed-printf/profiles/release.json
38+
```
39+
40+
## Enabling floating point, FILE stream, 64 bit integers, new line conversion, and setting baud rate
41+
42+
In mbed_app.json:
43+
44+
```
45+
"target_overrides": {
46+
"*": {
47+
"platform.stdio-baud-rate": 115200,
48+
"platform.stdio-convert-newlines": false,
49+
"minimal-printf.enable-file-stream": true,
50+
"minimal-printf.enable-floating-point": true,
51+
"minimal-printf.set-floating-point-max-decimals": 6,
52+
"minimal-printf.enable-64-bit": true
53+
}
54+
}
55+
```
56+
57+
58+
## Size comparison
59+
60+
Example application compiled with minimal mbed OS (no RTOS) using this .mbedignore:
61+
62+
```
63+
mbed-os/rtos/*
64+
mbed-os/features/FEATURE_LWIP/*
65+
mbed-os/features/FEATURE_CLIENT/*
66+
mbed-os/features/FEATURE_COMMON_PAL/*
67+
mbed-os/features/FEATURE_UVISOR/*
68+
mbed-os/features/frameworks/*
69+
mbed-os/features/net/*
70+
mbed-os/features/netsocket/*
71+
mbed-os/features/storage/*
72+
mbed-os/events/*
73+
```
74+
75+
### Example application
76+
```
77+
#include "mbed.h"
78+
#include "mbed_printf.h"
79+
#include <limits.h>
80+
81+
int main()
82+
{
83+
char buffer[1000];
84+
int result;
85+
86+
double pi = 3.14159265359;
87+
88+
#if 0
89+
result = printf("hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh", pi);
90+
printf("results: %d\r\n", result);
91+
92+
result = snprintf(buffer, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi);
93+
printf("%s\r\n", buffer);
94+
95+
printf("results: %d\r\n", result);
96+
97+
#else
98+
result = mbed_printf("hello world %ld %llu %02X %p %s %2.5f %% %\r\n", LONG_MAX, ULONG_MAX, UCHAR_MAX, buffer, "muh", pi);
99+
mbed_printf("results: %d\r\n", result);
100+
101+
result = mbed_snprintf(buffer, 1000, "hello world %d %u %X %p %s %2.5f %% %\r\n", LONG_MIN, 0, 0, buffer, "muh", -1*pi);
102+
mbed_printf("%s\r\n", buffer);
103+
104+
mbed_printf("results: %d\r\n", result);
105+
#endif
106+
}
107+
```
108+
109+
### Full application size on K64F/GCC
110+
111+
| | Floating point | 64 bit integers | Flash | RAM |
112+
| - | - | - | - | - |
113+
| mbed-printf | | | 7772 | 2752 |
114+
| mbed-printf | | X | 8708 | 2752 |
115+
| mbed-printf | X | | 10368 | 2752 |
116+
| mbed-printf | X | X | 11360 | 2752 |
117+
| std printf | X | X | 37354 | 5364 |

0 commit comments

Comments
 (0)