Skip to content

Commit 6d8233f

Browse files
committed
pkg/mpaland-printf: Add alternative stdio as package
This packs the stdio implementation from [1] as alternative to what the used standard C lib provides with the intent to provide a thread-safe, smaller, and more feature-complete alternative on newlib targets. Compared to `newlib_nano` this reduces `.text` by a bit more than 200 B while adding support for standard format specifiers such as `RPIu8`, `PRIu16`, `PRIu64`, `%z`, and `%t`. Note that `newlib_nano`'s stdio can be thread-safe in reentrant mode at the cost of RAM (per thread) and latency. Especially the increase in latency can be prohibitive when real time requirements need to be met. [1]: https://github.com/mpaland/printf
1 parent d9938cc commit 6d8233f

9 files changed

+235
-0
lines changed

pkg/mpaland-printf/Makefile

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
PKG_NAME=mpaland-printf
2+
PKG_URL=https://github.com/mpaland/printf
3+
# 4.0.0
4+
PKG_VERSION=0dd4b64bc778bf55229428cefccba4c0a81f384b
5+
PKG_LICENSE=MIT
6+
7+
include $(RIOTBASE)/pkg/pkg.mk
8+
9+
all:
10+
$(QQ)"$(MAKE)" -C $(PKG_SOURCE_DIR) -f $(RIOTPKG)/$(PKG_NAME)/$(PKG_NAME).mk

pkg/mpaland-printf/Makefile.dep

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
# mpaland's printf does not implement non-standard format specifiers. For
2+
# AVR MCUs we do need the ability to print from PROGMEM, though. Hence, this
3+
# is not compatible with AVR MCUs.
4+
FEATURES_BLACKLIST += arch_avr8
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
# wrap stdio functions to use mpaland's printf instead of the one from the
2+
# standard C lib
3+
LINKFLAGS += -Wl,-wrap=printf
4+
LINKFLAGS += -Wl,-wrap=sprintf
5+
LINKFLAGS += -Wl,-wrap=snprintf
6+
LINKFLAGS += -Wl,-wrap=vprintf
7+
LINKFLAGS += -Wl,-wrap=vsnprintf
8+
LINKFLAGS += -Wl,-wrap=putchar
9+
LINKFLAGS += -Wl,-wrap=puts
10+
11+
# Workaround for bug in the newlib headers shipped with e.g. Ubuntu 24.04 LTS
12+
# not defining PRId64 / PRIu64 / PRIx64 / PRIo64 in <inttypes.h> due to an issue
13+
# in <machine/_default_types.h>. Tested to cause no regression on fixed newlib
14+
# headers.
15+
ifneq (,$(filter newlib,$(FEATURES_USED)))
16+
CFLAGS += -D__int64_t_defined=1
17+
endif

pkg/mpaland-printf/doc.md

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
@defgroup pkg_mpaland-printf mpaland's printf
2+
@ingroup pkg
3+
@brief mpaland's printf implementation is a lean, thread-safe and
4+
feature-complete printf implementation
5+
6+
# License
7+
8+
Licensed under the MIT license.
9+
10+
# Usage
11+
12+
Add `USEPKG += mpaland-printf` to the application's `Makefile` or compile
13+
using `USEPKG=mpaland-printf make BOARD=<BOARD> -C <APP_DIR>`.
14+
15+
# Features
16+
17+
The package implements all standard format specifiers. However, support
18+
for floating point is disabled by default due to the immense ROM overhead
19+
on MCUs without FPU.
20+
21+
@note Support for floating point formatting can be enabled
22+
via the `printf_float` module, i.e., by adding
23+
`USEMODULE += printf_float` to the application's `Makefile`.
24+
@note Support for non-standard format specifiers such as needed for
25+
printing from flash on AVR MCUs are not implemented.
26+
27+
@see https://github.com/mpaland/printf
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
MODULE := mpaland-printf
2+
3+
SRC := \
4+
printf.c \
5+
#
6+
7+
include $(RIOTBASE)/Makefile.base
Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,50 @@
1+
From 04f0f9616f74bbb93a2994d627d4ab476bd81d31 Mon Sep 17 00:00:00 2001
2+
From: Marian Buschsieweke <[email protected]>
3+
Date: Sat, 11 May 2024 17:51:01 +0200
4+
Subject: [PATCH 1/4] RIOT integration
5+
6+
Use stdio_write() from stdio_base.h for output
7+
---
8+
printf.c | 8 ++++++++
9+
printf.h | 2 +-
10+
2 files changed, 9 insertions(+), 1 deletion(-)
11+
12+
diff --git a/printf.c b/printf.c
13+
index 8a700ad..4a17672 100644
14+
--- a/printf.c
15+
+++ b/printf.c
16+
@@ -34,6 +34,7 @@
17+
#include <stdint.h>
18+
19+
#include "printf.h"
20+
+#include "stdio_base.h"
21+
22+
23+
// define this globally (e.g. gcc -DPRINTF_INCLUDE_CONFIG_H ...) to include the
24+
@@ -912,3 +913,10 @@ int fctprintf(void (*out)(char character, void* arg), void* arg, const char* for
25+
va_end(va);
26+
return ret;
27+
}
28+
+
29+
+
30+
+/* RIOT integration: Use stdio_write for output */
31+
+static void _putchar(char character)
32+
+{
33+
+ stdio_write(&character, sizeof(character));
34+
+}
35+
diff --git a/printf.h b/printf.h
36+
index 6075bc2..154930a 100644
37+
--- a/printf.h
38+
+++ b/printf.h
39+
@@ -46,7 +46,7 @@ extern "C" {
40+
* This function is declared here only. You have to write your custom implementation somewhere
41+
* \param character Character to output
42+
*/
43+
-void _putchar(char character);
44+
+static void _putchar(char character);
45+
46+
47+
/**
48+
--
49+
2.43.0
50+
Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,66 @@
1+
From 2070026e3325ad7640c5cddc9cb1254aa63d61bb Mon Sep 17 00:00:00 2001
2+
From: Marian Buschsieweke <[email protected]>
3+
Date: Sat, 11 May 2024 17:51:38 +0200
4+
Subject: [PATCH 2/4] Wrapper targets: Add endpoints for -Wl,wrap=...
5+
6+
This adds aliases needed to wrap printf() and friends.
7+
---
8+
printf.c | 38 ++++++++++++++++++++++++++++++++++++++
9+
1 file changed, 38 insertions(+)
10+
11+
diff --git a/printf.c b/printf.c
12+
index 4a17672..e06c9aa 100644
13+
--- a/printf.c
14+
+++ b/printf.c
15+
@@ -32,6 +32,7 @@
16+
17+
#include <stdbool.h>
18+
#include <stdint.h>
19+
+#include <string.h>
20+
21+
#include "printf.h"
22+
#include "stdio_base.h"
23+
@@ -920,3 +921,40 @@ static void _putchar(char character)
24+
{
25+
stdio_write(&character, sizeof(character));
26+
}
27+
+
28+
+
29+
+/* provide entry points for linker to redirect stdio */
30+
+__attribute__((alias("printf_")))
31+
+int __wrap_printf(const char* format, ...);
32+
+
33+
+
34+
+__attribute__((alias("sprintf_")))
35+
+int __wrap_sprintf(char* buffer, const char* format, ...);
36+
+
37+
+
38+
+__attribute__((alias("snprintf_")))
39+
+int __wrap_snprintf(char* buffer, size_t count, const char* format, ...);
40+
+
41+
+
42+
+__attribute__((alias("vprintf_")))
43+
+int __wrap_vprintf(const char* format, va_list va);
44+
+
45+
+
46+
+__attribute__((alias("vsnprintf_")))
47+
+int __wrap_vsnprintf(char* buffer, size_t count, const char* format, va_list va);
48+
+
49+
+
50+
+int __wrap_putchar(int c)
51+
+{
52+
+ _putchar((char)c);
53+
+ return 1;
54+
+}
55+
+
56+
+
57+
+int __wrap_puts(const char *s)
58+
+{
59+
+ size_t len = strlen(s);
60+
+ stdio_write(s, len);
61+
+ stdio_write("\n", 1);
62+
+ return len + 1;
63+
+}
64+
--
65+
2.43.0
66+
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
From 33f690a4882dc567df328a900c5d12e113feb15c Mon Sep 17 00:00:00 2001
2+
From: Marian Buschsieweke <[email protected]>
3+
Date: Sat, 11 May 2024 18:38:51 +0200
4+
Subject: [PATCH 3/4] RIOT integration: Enable floating support based on module
5+
selection
6+
7+
---
8+
printf.c | 2 +-
9+
1 file changed, 1 insertion(+), 1 deletion(-)
10+
11+
diff --git a/printf.c b/printf.c
12+
index e06c9aa..5266cf7 100644
13+
--- a/printf.c
14+
+++ b/printf.c
15+
@@ -62,7 +62,7 @@
16+
17+
// support for the floating point type (%f)
18+
// default: activated
19+
-#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
20+
+#ifdef MODULE_PRINTF_FLOAT
21+
#define PRINTF_SUPPORT_FLOAT
22+
#endif
23+
24+
--
25+
2.43.0
26+
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
From 81ef21a29faafbdb95800ce40b2e20b533b88ebd Mon Sep 17 00:00:00 2001
2+
From: Marian Buschsieweke <[email protected]>
3+
Date: Sat, 11 May 2024 22:42:21 +0200
4+
Subject: [PATCH 4/4] Fix parsing of `int8_t`
5+
6+
The code assumes that `char` is signed, but the C standard allows
7+
`char` to be either signed or unsigned. Instead, `singed char` and
8+
`unsigned char` need to be used for portable code.
9+
---
10+
printf.c | 2 +-
11+
1 file changed, 1 insertion(+), 1 deletion(-)
12+
13+
diff --git a/printf.c b/printf.c
14+
index 5266cf7..3f5f66a 100644
15+
--- a/printf.c
16+
+++ b/printf.c
17+
@@ -734,7 +734,7 @@ static int _vsnprintf(out_fct_type out, char* buffer, const size_t maxlen, const
18+
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
19+
}
20+
else {
21+
- const int value = (flags & FLAGS_CHAR) ? (char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
22+
+ const int value = (flags & FLAGS_CHAR) ? (signed char)va_arg(va, int) : (flags & FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
23+
idx = _ntoa_long(out, buffer, idx, maxlen, (unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
24+
}
25+
}
26+
--
27+
2.43.0
28+

0 commit comments

Comments
 (0)