44#if (ENABLE_BSP_PRINTF_FULL || ENABLE_SEMIHOSTING_PRINT == 1)
49#if (!ENABLE_BSP_PRINTF)
50 static void _putchar(
char character){
51 #if (ENABLE_SEMIHOSTING_PRINT == 1)
58 static void _putchar_s(
char *p)
60 #if (ENABLE_SEMIHOSTING_PRINT == 1)
68 static void bsp_printHex(uint32_t val)
73 for (
int i = (4*digits)-4; i >= 0; i -= 4) {
74 _putchar(
"0123456789ABCDEF"[(val >> i) % 16]);
78 static void bsp_printf_c(
int c)
83 static void bsp_printf_s(
char *p)
99#define bsp_printf_full printf_
110#define bsp_sprintf_full sprintf_
124#define bsp_snprintf_full snprintf_
125#define bsp_efx_vsnprintf_full vsnprintf_
136#define bsp_vprintf_full vprintf_
148#define bsp_fctprintf_full fctprintf
155#ifdef PRINTF_INCLUDE_CONFIG_H
156#include "printf_config.h"
163#ifndef PRINTF_NTOA_BUFFER_SIZE
164#define PRINTF_NTOA_BUFFER_SIZE 32U
170#ifndef PRINTF_FTOA_BUFFER_SIZE
171#define PRINTF_FTOA_BUFFER_SIZE 32U
176#ifndef PRINTF_DISABLE_SUPPORT_FLOAT
177#define PRINTF_SUPPORT_FLOAT
182#ifndef PRINTF_DISABLE_SUPPORT_EXPONENTIAL
183#define PRINTF_SUPPORT_EXPONENTIAL
188#ifndef PRINTF_DEFAULT_FLOAT_PRECISION
189#define PRINTF_DEFAULT_FLOAT_PRECISION 4U
194#ifndef PRINTF_MAX_FLOAT
195#define PRINTF_MAX_FLOAT 1e9
200#ifndef PRINTF_DISABLE_SUPPORT_LONG_LONG
201#define PRINTF_SUPPORT_LONG_LONG
207#ifndef PRINTF_DISABLE_SUPPORT_PTRDIFF_T
208#define PRINTF_SUPPORT_PTRDIFF_T
212#ifndef MAX_STRING_BUFFER_SIZE
213#define MAX_STRING_BUFFER_SIZE 100
219#define FLAGS_ZEROPAD (1U << 0U)
220#define FLAGS_LEFT (1U << 1U)
221#define FLAGS_PLUS (1U << 2U)
222#define FLAGS_SPACE (1U << 3U)
223#define FLAGS_HASH (1U << 4U)
224#define FLAGS_UPPERCASE (1U << 5U)
225#define FLAGS_CHAR (1U << 6U)
226#define FLAGS_SHORT (1U << 7U)
227#define FLAGS_LONG (1U << 8U)
228#define FLAGS_LONG_LONG (1U << 9U)
229#define FLAGS_PRECISION (1U << 10U)
230#define FLAGS_ADAPT_EXP (1U << 11U)
234#if defined(PRINTF_SUPPORT_FLOAT)
239typedef void (*
out_fct_type)(
char character,
void* buffer,
size_t idx,
size_t maxlen);
250static inline void _out_buffer(
char character,
void* buffer,
size_t idx,
size_t maxlen)
253 ((
char*)buffer)[idx] = character;
259static inline void _out_null(
char character,
void* buffer,
size_t idx,
size_t maxlen)
261 (void)character; (void)buffer; (void)idx; (void)maxlen;
266static inline void _out_char(
char character,
void* buffer,
size_t idx,
size_t maxlen)
268 (void)buffer; (void)idx; (void)maxlen;
277static inline void _out_fct(
char character,
void* buffer,
size_t idx,
size_t maxlen)
279 (void)idx; (void)maxlen;
288static inline unsigned int _strnlen_s(
const char* str,
size_t maxsize)
291 for (s = str; *s && maxsize--; ++s);
292 return (
unsigned int)(s - str);
298static inline bool _is_digit(
char ch)
300 return (ch >=
'0') && (ch <=
'9');
305static unsigned int _atoi(
const char** str)
308 while (_is_digit(**str)) {
309 i = i * 10U + (
unsigned int)(*((*str)++) -
'0');
315static size_t _out_rev(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
const char* buf,
size_t len,
unsigned int width,
unsigned int flags)
317 const size_t start_idx = idx;
321 for (
size_t i = len; i < width; i++) {
322 out(
' ', buffer, idx++, maxlen);
328 out(buf[--len], buffer, idx++, maxlen);
333 while (idx - start_idx < width) {
334 out(
' ', buffer, idx++, maxlen);
343static size_t _ntoa_format(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
char* buf,
size_t len,
bool negative,
unsigned int base,
unsigned int prec,
unsigned int width,
unsigned int flags)
350 while ((len < prec) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
353 while ((flags &
FLAGS_ZEROPAD) && (len < width) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
360 if (!(flags &
FLAGS_PRECISION) && len && ((len == prec) || (len == width))) {
362 if (len && (base == 16U)) {
366 if ((base == 16U) && !(flags &
FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
369 else if ((base == 16U) && (flags &
FLAGS_UPPERCASE) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
372 else if ((base == 2U) && (len < PRINTF_NTOA_BUFFER_SIZE)) {
375 if (len < PRINTF_NTOA_BUFFER_SIZE) {
380 if (len < PRINTF_NTOA_BUFFER_SIZE) {
392 return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
397static size_t _ntoa_long(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
unsigned long value,
bool negative,
unsigned long base,
unsigned int prec,
unsigned int width,
unsigned int flags)
399 char buf[PRINTF_NTOA_BUFFER_SIZE];
410 const char digit = (char)(value % base);
411 buf[len++] = digit < 10 ?
'0' + digit : (flags &
FLAGS_UPPERCASE ?
'A' :
'a') + digit - 10;
413 }
while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
416 return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (
unsigned int)base, prec, width, flags);
421#if defined(PRINTF_SUPPORT_LONG_LONG)
422static size_t _ntoa_long_long(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
unsigned long long value,
bool negative,
unsigned long long base,
unsigned int prec,
unsigned int width,
unsigned int flags)
424 char buf[PRINTF_NTOA_BUFFER_SIZE];
435 const char digit = (char)(value % base);
436 buf[len++] = digit < 10 ?
'0' + digit : (flags &
FLAGS_UPPERCASE ?
'A' :
'a') + digit - 10;
438 }
while (value && (len < PRINTF_NTOA_BUFFER_SIZE));
441 return _ntoa_format(out, buffer, idx, maxlen, buf, len, negative, (
unsigned int)base, prec, width, flags);
446#if defined(PRINTF_SUPPORT_FLOAT)
448#if defined(PRINTF_SUPPORT_EXPONENTIAL)
450static size_t _etoa(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
double value,
unsigned int prec,
unsigned int width,
unsigned int flags);
455static size_t _ftoa(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
double value,
unsigned int prec,
unsigned int width,
unsigned int flags)
457 char buf[PRINTF_FTOA_BUFFER_SIZE];
462 static const double pow10[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 };
466 return _out_rev(out, buffer, idx, maxlen,
"nan", 3, width, flags);
467 if (value < -DBL_MAX)
468 return _out_rev(out, buffer, idx, maxlen,
"fni-", 4, width, flags);
470 return _out_rev(out, buffer, idx, maxlen, (flags &
FLAGS_PLUS) ?
"fni+" :
"fni", (flags &
FLAGS_PLUS) ? 4U : 3U, width, flags);
474 if ((value > PRINTF_MAX_FLOAT) || (value < -PRINTF_MAX_FLOAT)) {
475#if defined(PRINTF_SUPPORT_EXPONENTIAL)
476 return _etoa(out, buffer, idx, maxlen, value, prec, width, flags);
483 bool negative =
false;
491 prec = PRINTF_DEFAULT_FLOAT_PRECISION;
494 while ((len < PRINTF_FTOA_BUFFER_SIZE) && (prec > 9U)) {
499 int whole = (int)value;
500 double tmp = (value - whole) * pow10[prec];
501 unsigned long frac = (
unsigned long)tmp;
507 if (frac >= pow10[prec]) {
512 else if (diff < 0.5) {
514 else if ((frac == 0U) || (frac & 1U)) {
520 diff = value - (double)whole;
521 if ((!(diff < 0.5) || (diff > 0.5)) && (whole & 1)) {
528 unsigned int count = prec;
530 while (len < PRINTF_FTOA_BUFFER_SIZE) {
532 buf[len++] = (char)(48U + (frac % 10U));
533 if (!(frac /= 10U)) {
538 while ((len < PRINTF_FTOA_BUFFER_SIZE) && (count-- > 0U)) {
541 if (len < PRINTF_FTOA_BUFFER_SIZE) {
548 while (len < PRINTF_FTOA_BUFFER_SIZE) {
549 buf[len++] = (char)(48 + (whole % 10));
550 if (!(whole /= 10)) {
560 while ((len < width) && (len < PRINTF_FTOA_BUFFER_SIZE)) {
565 if (len < PRINTF_FTOA_BUFFER_SIZE) {
577 return _out_rev(out, buffer, idx, maxlen, buf, len, width, flags);
581#if defined(PRINTF_SUPPORT_EXPONENTIAL)
583static size_t _etoa(
out_fct_type out,
char* buffer,
size_t idx,
size_t maxlen,
double value,
unsigned int prec,
unsigned int width,
unsigned int flags)
586 if ((value != value) || (value > DBL_MAX) || (value < -DBL_MAX)) {
587 return _ftoa(out, buffer, idx, maxlen, value, prec, width, flags);
591 const bool negative = value < 0;
598 prec = PRINTF_DEFAULT_FLOAT_PRECISION;
609 int exp2 = (int)((conv.U >> 52U) & 0x07FFU) - 1023;
610 conv.U = (conv.U & ((1ULL << 52U) - 1U)) | (1023ULL << 52U);
612 int expval = (int)(0.1760912590558 + exp2 * 0.301029995663981 + (conv.F - 1.5) * 0.289529654602168);
614 exp2 = (int)(expval * 3.321928094887362 + 0.5);
615 const double z = expval * 2.302585092994046 - exp2 * 0.6931471805599453;
616 const double z2 = z * z;
617 conv.U = (uint64_t)(exp2 + 1023) << 52U;
619 conv.F *= 1 + 2 * z / (2 - z + (z2 / (6 + (z2 / (10 + z2 / 14)))));
621 if (value < conv.F) {
627 unsigned int minwidth = ((expval < 100) && (expval > -100)) ? 4U : 5U;
632 if ((value >= 1e-4) && (value < 1e6)) {
633 if ((
int)prec > expval) {
634 prec = (unsigned)((
int)prec - expval - 1);
653 unsigned int fwidth = width;
654 if (width > minwidth) {
672 const size_t start_idx = idx;
673 idx = _ftoa(out, buffer, idx, maxlen, negative ? -value : value, prec, fwidth, flags & ~
FLAGS_ADAPT_EXP);
680 idx = _ntoa_long(out, buffer, idx, maxlen, (expval < 0) ? -expval : expval, expval < 0, 10, 0, minwidth-1,
FLAGS_ZEROPAD |
FLAGS_PLUS);
683 while (idx - start_idx < width) out(
' ', buffer, idx++, maxlen);
693static int _vsnprintf(
out_fct_type out,
char* buffer,
const size_t maxlen,
const char* format, va_list va)
695 unsigned int flags, width, precision, n;
706 if (*format !=
'%') {
708 out(*format, buffer, idx++, maxlen);
722 case '-': flags |=
FLAGS_LEFT; format++; n = 1U;
break;
723 case '+': flags |=
FLAGS_PLUS; format++; n = 1U;
break;
724 case ' ': flags |=
FLAGS_SPACE; format++; n = 1U;
break;
725 case '#': flags |=
FLAGS_HASH; format++; n = 1U;
break;
726 default : n = 0U;
break;
732 if (_is_digit(*format)) {
733 width = _atoi(&format);
735 else if (*format ==
'*') {
736 const int w = va_arg(va,
int);
739 width = (
unsigned int)-w;
742 width = (
unsigned int)w;
749 if (*format ==
'.') {
752 if (_is_digit(*format)) {
753 precision = _atoi(&format);
755 else if (*format ==
'*') {
756 const int prec = (int)va_arg(va,
int);
757 precision = prec > 0 ? (
unsigned int)prec : 0U;
767 if (*format ==
'l') {
775 if (*format ==
'h') {
780#if defined(PRINTF_SUPPORT_PTRDIFF_T)
809 if (*format ==
'x' || *format ==
'X') {
812 else if (*format ==
'o') {
815 else if (*format ==
'b') {
823 if (*format ==
'X') {
828 if ((*format !=
'i') && (*format !=
'd')) {
838 if ((*format ==
'i') || (*format ==
'd')) {
841#if defined(PRINTF_SUPPORT_LONG_LONG)
842 const long long value = va_arg(va,
long long);
843 idx = _ntoa_long_long(out, buffer, idx, maxlen, (
unsigned long long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
847 const long value = va_arg(va,
long);
848 idx = _ntoa_long(out, buffer, idx, maxlen, (
unsigned long)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
851 const int value = (flags &
FLAGS_CHAR) ? (
char)va_arg(va,
int) : (flags &
FLAGS_SHORT) ? (short int)va_arg(va, int) : va_arg(va, int);
852 idx = _ntoa_long(out, buffer, idx, maxlen, (
unsigned int)(value > 0 ? value : 0 - value), value < 0, base, precision, width, flags);
858#if defined(PRINTF_SUPPORT_LONG_LONG)
859 idx = _ntoa_long_long(out, buffer, idx, maxlen, va_arg(va,
unsigned long long),
false, base, precision, width, flags);
863 idx = _ntoa_long(out, buffer, idx, maxlen, va_arg(va,
unsigned long),
false, base, precision, width, flags);
866 const unsigned int value = (flags &
FLAGS_CHAR) ? (
unsigned char)va_arg(va,
unsigned int) : (flags &
FLAGS_SHORT) ? (unsigned short int)va_arg(va, unsigned int) : va_arg(va, unsigned int);
867 idx = _ntoa_long(out, buffer, idx, maxlen, value,
false, base, precision, width, flags);
873#if defined(PRINTF_SUPPORT_FLOAT)
877 idx = _ftoa(out, buffer, idx, maxlen, va_arg(va,
double), precision, width, flags);
880#if defined(PRINTF_SUPPORT_EXPONENTIAL)
887 idx = _etoa(out, buffer, idx, maxlen, va_arg(va,
double), precision, width, flags);
890#elif (ENABLE_PRINTF_WARNING)
895 const char* p =
"<Warning, unsupported specifier used, please enable floating point support in bsp.h %";
896 unsigned int l = _strnlen_s(p, precision ? precision : (
size_t)-1);
899 l = (l < precision ? l : precision);
902 while (l++ < width) {
903 out(
' ', buffer, idx++, maxlen);
908 out(*(p++), buffer, idx++, maxlen);
910 out(*format, buffer, idx++, maxlen);
911 out(
'>', buffer, idx++, maxlen);
916#elif (ENABLE_PRINTF_WARNING)
919 const char* p =
"<Warning, unsupported specifier used, please enable floating point support in bsp.h %";
920 unsigned int l = _strnlen_s(p, precision ? precision : (
size_t)-1);
923 l = (l < precision ? l : precision);
926 while (l++ < width) {
927 out(
' ', buffer, idx++, maxlen);
932 out(*(p++), buffer, idx++, maxlen);
934 out(*format, buffer, idx++, maxlen);
935 out(
'>', buffer, idx++, maxlen);
944 while (l++ < width) {
945 out(
' ', buffer, idx++, maxlen);
949 out((
char)va_arg(va,
int), buffer, idx++, maxlen);
952 while (l++ < width) {
953 out(
' ', buffer, idx++, maxlen);
961 const char* p = va_arg(va,
char*);
962 unsigned int l = _strnlen_s(p, precision ? precision : (
size_t)-1);
965 l = (l < precision ? l : precision);
968 while (l++ < width) {
969 out(
' ', buffer, idx++, maxlen);
974 out(*(p++), buffer, idx++, maxlen);
978 while (l++ < width) {
979 out(
' ', buffer, idx++, maxlen);
987 width =
sizeof(
void*) * 2U;
989#if defined(PRINTF_SUPPORT_LONG_LONG)
990 const bool is_ll =
sizeof(uintptr_t) ==
sizeof(
long long);
992 idx = _ntoa_long_long(out, buffer, idx, maxlen, (uintptr_t)va_arg(va,
void*),
false, 16U, precision, width, flags);
996 idx = _ntoa_long(out, buffer, idx, maxlen, (
unsigned long)((uintptr_t)va_arg(va,
void*)),
false, 16U, precision, width, flags);
997#if defined(PRINTF_SUPPORT_LONG_LONG)
1005 out(
'%', buffer, idx++, maxlen);
1010 out(*format, buffer, idx++, maxlen);
1017 out((
char)0, buffer, idx < maxlen ? idx : maxlen - 1U, maxlen);
1026static int printf_(
const char* format, ...)
1029 va_start(va, format);
1030#if (ENABLE_SEMIHOSTING_PRINT == 1)
1031 char buffer[MAX_STRING_BUFFER_SIZE];
1032 const int ret = _vsnprintf(_out_buffer, buffer, (
size_t)-1, format, va);
1036 const int ret = _vsnprintf(_out_char, buffer, (
size_t)-1, format, va);
1045static int sprintf_(
char* buffer,
const char* format, ...)
1048 va_start(va, format);
1049 const int ret = _vsnprintf(_out_buffer, buffer, (
size_t)-1, format, va);
1055static int snprintf_(
char* buffer,
size_t count,
const char* format, ...)
1058 va_start(va, format);
1059 const int ret = _vsnprintf(_out_buffer, buffer, count, format, va);
1065static int vprintf_(
const char* format, va_list va)
1068 return _vsnprintf(_out_char, buffer, (
size_t)-1, format, va);
1072static int vsnprintf_(
char* buffer,
size_t count,
const char* format, va_list va)
1074 return _vsnprintf(_out_buffer, buffer, count, format, va);
1078static int fctprintf(
void (*out)(
char character,
void* arg),
void* arg,
const char* format, ...)
1081 va_start(va, format);
1083 const int ret = _vsnprintf(_out_fct, (
char*)(uintptr_t)&out_fct_wrap, (
size_t)-1, format, va);
void(* out_fct_type)(char character, void *buffer, size_t idx, size_t maxlen)
void(* fct)(char character, void *arg)