2 * Copyright (c) 2004,2012 Kustaa Nyholm / SpareTimeLabs
6 * Redistribution and use in source and binary forms, with or without modification,
7 * are permitted provided that the following conditions are met:
9 * Redistributions of source code must retain the above copyright notice, this list
10 * of conditions and the following disclaimer.
12 * Redistributions in binary form must reproduce the above copyright notice, this
13 * list of conditions and the following disclaimer in the documentation and/or other
14 * materials provided with the distribution.
16 * Neither the name of the Kustaa Nyholm or SpareTimeLabs nor the names of its
17 * contributors may be used to endorse or promote products derived from this software
18 * without specific prior written permission.
20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
22 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
23 * IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
24 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
25 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
26 * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
27 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
39 #include "build/build_config.h"
41 #include "common/utils.h"
43 #include "drivers/serial.h"
46 #include "io/serial.h"
49 #ifdef REQUIRE_PRINTF_LONG_SUPPORT
50 #include "typeconversion.h"
51 #define MAX UINT64_MAX
53 #define MAX UINT32_MAX
56 static serialPort_t
*printfSerialPort
;
58 #ifdef REQUIRE_CC_ARM_PRINTF_SUPPORT
60 typedef void (*putcf
) (void *, char);
61 static putcf stdout_putf
;
62 static void *stdout_putp
;
64 // print bf, padded from left to at least n characters.
65 // padding is zero ('0') if z!=0, space (' ') otherwise
66 static int putchw(void *putp
, const void *end
, putcf putf
, int n
, char z
, char *bf
)
69 char fc
= z
? '0' : ' ';
87 while ((ch
= *bf
++)) {
104 int tfp_format(void *putp
, putcf putf
, const char *fmt
, va_list va
)
106 return tfp_nformat(putp
, -1, putf
, fmt
, va
);
109 // return number of bytes written
110 int tfp_nformat(void *putp
, int size
, void (*putf
) (void *, char), const char *fmt
, va_list va
)
116 const void *end
= size
< 0 ? (void*)MAX
: ((char *)putp
+ size
- 1);
118 while ((ch
= *(fmt
++))) {
126 char pr
= 0; // padding at the right?
127 #ifdef REQUIRE_PRINTF_LONG_SUPPORT
140 if (ch
>= '0' && ch
<= '9') {
141 ch
= a2i(ch
, &fmt
, 10, &w
);
146 #ifdef REQUIRE_PRINTF_LONG_SUPPORT
156 #ifdef REQUIRE_PRINTF_LONG_SUPPORT
158 uli2a(va_arg(va
, unsigned long int), 10, 0, bf
);
161 ui2a(va_arg(va
, unsigned int), 10, 0, bf
);
162 written
+= putchw(putp
, end
, putf
, w
, lz
, bf
);
167 #ifdef REQUIRE_PRINTF_LONG_SUPPORT
169 li2a(va_arg(va
, unsigned long int), bf
);
172 i2a(va_arg(va
, int), bf
);
173 written
+= putchw(putp
, end
, putf
, w
, lz
, bf
);
178 #ifdef REQUIRE_PRINTF_LONG_SUPPORT
180 uli2a(va_arg(va
, unsigned long int), 16, (ch
== 'X'), bf
);
183 ui2a(va_arg(va
, unsigned int), 16, (ch
== 'X'), bf
);
184 written
+= putchw(putp
, end
, putf
, w
, lz
, bf
);
188 putf(putp
, (char) (va_arg(va
, int)));
193 written
+= putchw(putp
, end
, putf
, w
, 0, va_arg(va
, char *));
202 *va_arg(va
, int*) = written
;
205 ftoa(va_arg(va
, double), bf
);
206 written
+= putchw(putp
, end
, putf
, w
, lz
, bf
);
217 void init_printf(void *putp
, void (*putf
) (void *, char))
223 int tfp_printf(const char *fmt
, ...)
227 int written
= tfp_format(stdout_putp
, stdout_putf
, fmt
, va
);
229 while (!isSerialTransmitBufferEmpty(printfSerialPort
));
233 static void putcp(void *p
, char c
)
235 *(*((char **) p
))++ = c
;
238 int tfp_sprintf(char *s
, const char *fmt
, ...)
243 int written
= tfp_vsprintf(s
, fmt
, va
);
248 int tfp_snprintf(char *s
, int size
, const char *fmt
, ...)
253 int written
= tfp_vsnprintf(s
, size
, fmt
, va
);
258 int tfp_vsprintf(char *s
, const char *fmt
, va_list va
)
260 return tfp_vsnprintf(s
, -1, fmt
, va
);
263 int tfp_vsnprintf(char *s
, int size
, const char *fmt
, va_list va
)
265 int written
= tfp_nformat(&s
, size
, putcp
, fmt
, va
);
271 static void _putc(void *p
, char c
)
274 serialWrite(printfSerialPort
, c
);
277 void printfSupportInit(void)
279 init_printf(NULL
, _putc
);
284 // keil/armcc version
285 int fputc(int c
, FILE *f
)
287 // let DMA catch up a bit when using set or dump, we're too fast.
288 while (!isSerialTransmitBufferEmpty(printfSerialPort
));
289 serialWrite(printfSerialPort
, c
);
293 void printfSupportInit(void)
299 void setPrintfSerialPort(serialPort_t
*serialPort
)
301 printfSerialPort
= serialPort
;