1 /*
2 * This is a modified version of the file printf.c, which was distributed
3 * by Motorola as part of the M5407C3BOOT.zip package used to initialize
4 * the M5407C3 evaluation board.
5 *
6 * Copyright:
7 * 1999-2000 MOTOROLA, INC. All Rights Reserved.
8 * You are hereby granted a copyright license to use, modify, and
9 * distribute the SOFTWARE so long as this entire notice is
10 * retained without alteration in any modified and/or redistributed
11 * versions, and that such modified versions are clearly identified
12 * as such. No licenses are granted by implication, estoppel or
13 * otherwise under any patents or trademarks of Motorola, Inc. This
14 * software is provided on an "AS IS" basis and without warranty.
15 *
16 * To the maximum extent permitted by applicable law, MOTOROLA
17 * DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING
18 * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
19 * PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE
20 * SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY
21 * ACCOMPANYING WRITTEN MATERIALS.
22 *
23 * To the maximum extent permitted by applicable law, IN NO EVENT
24 * SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING
25 * WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
26 * INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
27 * LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
28 *
29 * Motorola assumes no responsibility for the maintenance and support
30 * of this software
31
32 * Copyright (c) 2015, Freescale Semiconductor, Inc.
33 * Copyright 2016-2017 NXP
34 *
35 * SPDX-License-Identifier: BSD-3-Clause
36 */
37
38 #include <stdarg.h>
39 #include <stdlib.h>
40 #if defined(__CC_ARM)
41 #include <stdio.h>
42 #endif
43
44 #include "fsl_debug_console.h"
45 #include "fsl_debug_console_conf.h"
46 #include "fsl_log.h"
47 #include "fsl_str.h"
48
49 #if defined(__riscv)
50 #include <sys/stat.h>
51 #include <sys/types.h>
52 #endif
53
54 /*******************************************************************************
55 * Definitions
56 ******************************************************************************/
57
58 /*******************************************************************************
59 * Variables
60 ******************************************************************************/
61
62 /*******************************************************************************
63 * Prototypes
64 ******************************************************************************/
65 /*!
66 * @brief This is a printf call back function which is used to relocate the log to buffer
67 * or print the log immediately when the local buffer is full.
68 *
69 * @param[in] buf Buffer to store log.
70 * @param[in] indicator Buffer index.
71 * @param[in] val Target character to store.
72 * @param[in] len length of the character
73 *
74 */
75 #if SDK_DEBUGCONSOLE
76 static void DbgConsole_RelocateLog(char *buf, int32_t *indicator, char val, int len);
77 #endif
78 /*******************************************************************************
79 * Code
80 ******************************************************************************/
81
82 /*************Code for DbgConsole Init, Deinit, Printf, Scanf *******************************/
83
84 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Init(uint32_t baseAddr,uint32_t baudRate,uint8_t device,uint32_t clkSrcFreq)85 status_t DbgConsole_Init(uint32_t baseAddr, uint32_t baudRate, uint8_t device, uint32_t clkSrcFreq)
86 {
87 assert(device != DEBUG_CONSOLE_DEVICE_TYPE_NONE);
88
89 return LOG_Init(baseAddr, device, baudRate, clkSrcFreq);
90 }
91
92 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Deinit(void)93 status_t DbgConsole_Deinit(void)
94 {
95 /* LOG deinit */
96 LOG_Deinit();
97
98 return kStatus_Success;
99 }
100
DbgConsole_Flush(void)101 status_t DbgConsole_Flush(void)
102 {
103 /* wait log and io idle */
104 return LOG_WaitIdle();
105 }
106
107 #if SDK_DEBUGCONSOLE
108 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Printf(const char * fmt_s,...)109 int DbgConsole_Printf(const char *fmt_s, ...)
110 {
111 va_list ap;
112 int logLength = 0U, result = 0U;
113 char printBuf[DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN] = {0U};
114
115 va_start(ap, fmt_s);
116 /* format print log first */
117 logLength = StrFormatPrintf(fmt_s, ap, printBuf, DbgConsole_RelocateLog);
118 /* print log */
119 result = LOG_Push((uint8_t *)printBuf, logLength);
120
121 va_end(ap);
122
123 return result;
124 }
125
126 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Putchar(int ch)127 int DbgConsole_Putchar(int ch)
128 {
129 /* print char */
130 return LOG_Push((uint8_t *)&ch, 1U);
131 }
132
133 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Scanf(char * fmt_ptr,...)134 int DbgConsole_Scanf(char *fmt_ptr, ...)
135 {
136 va_list ap;
137 int result;
138 char scanfBuf[DEBUG_CONSOLE_SCANF_MAX_LOG_LEN + 1U] = {0U};
139
140 /* scanf log */
141 LOG_ReadLine((uint8_t *)scanfBuf, DEBUG_CONSOLE_SCANF_MAX_LOG_LEN);
142 /* get va_list */
143 va_start(ap, fmt_ptr);
144 /* format scanf log */
145 result = StrFormatScanf(scanfBuf, fmt_ptr, ap);
146
147 va_end(ap);
148
149 return result;
150 }
151
152 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Getchar(void)153 int DbgConsole_Getchar(void)
154 {
155 uint8_t ch;
156
157 /* Get char */
158 LOG_ReadCharacter(&ch);
159
160 return ch;
161 }
162
DbgConsole_RelocateLog(char * buf,int32_t * indicator,char val,int len)163 static void DbgConsole_RelocateLog(char *buf, int32_t *indicator, char val, int len)
164 {
165 int i = 0;
166
167 for (i = 0; i < len; i++)
168 {
169 if ((*indicator + 1) >= DEBUG_CONSOLE_PRINTF_MAX_LOG_LEN)
170 {
171 LOG_Push((uint8_t *)buf, *indicator);
172 *indicator = 0U;
173 }
174
175 buf[*indicator] = val;
176 (*indicator)++;
177 }
178 }
179
180 #endif /* SDK_DEBUGCONSOLE */
181 /*************Code to support toolchain's printf, scanf *******************************/
182 /* These function __write and __read is used to support IAR toolchain to printf and scanf*/
183 #if (defined(__ICCARM__))
184 #pragma weak __write
__write(int handle,const unsigned char * buffer,size_t size)185 size_t __write(int handle, const unsigned char *buffer, size_t size)
186 {
187 if (buffer == 0)
188 {
189 /*
190 * This means that we should flush internal buffers. Since we don't we just return.
191 * (Remember, "handle" == -1 means that all handles should be flushed.)
192 */
193 return 0;
194 }
195
196 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
197 if ((handle != 1) && (handle != 2))
198 {
199 return ((size_t)-1);
200 }
201
202 /* Send data. */
203 LOG_Push((uint8_t *)buffer, 1U);
204
205 return size;
206 }
207
208 #pragma weak __read
__read(int handle,unsigned char * buffer,size_t size)209 size_t __read(int handle, unsigned char *buffer, size_t size)
210 {
211 /* This function only reads from "standard in", for all other file handles it returns failure. */
212 if (handle != 0)
213 {
214 return ((size_t)-1);
215 }
216
217 /* Receive data.*/
218 LOG_ReadLine(buffer, size);
219
220 return size;
221 }
222
223 /* support LPC Xpresso with RedLib */
224 #elif(defined(__REDLIB__))
225
226 #if (!SDK_DEBUGCONSOLE) && (defined(SDK_DEBUGCONSOLE_UART))
__sys_write(int handle,char * buffer,int size)227 int __attribute__((weak)) __sys_write(int handle, char *buffer, int size)
228 {
229 if (buffer == 0)
230 {
231 /* return -1 if error. */
232 return -1;
233 }
234
235 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
236 if ((handle != 1) && (handle != 2))
237 {
238 return -1;
239 }
240
241 /* Send data. */
242 LOG_Push((uint8_t *)buffer, size);
243
244 return 0;
245 }
246
__sys_readc(void)247 int __attribute__((weak)) __sys_readc(void)
248 {
249 char tmp;
250
251 /* Receive data. */
252 LOG_ReadCharacter((uint8_t *)&tmp);
253
254 return tmp;
255 }
256 #endif
257
258 /* These function __write and __read is used to support ARM_GCC, KDS, Atollic toolchains to printf and scanf*/
259 #elif(defined(__GNUC__))
260
261 #if ((defined(__GNUC__) && (!defined(__MCUXPRESSO))) || \
262 (defined(__MCUXPRESSO) && (!SDK_DEBUGCONSOLE) && (defined(SDK_DEBUGCONSOLE_UART))))
263
_write(int handle,char * buffer,int size)264 int __attribute__((weak)) _write(int handle, char *buffer, int size)
265 {
266 if (buffer == 0)
267 {
268 /* return -1 if error. */
269 return -1;
270 }
271
272 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
273 if ((handle != 1) && (handle != 2))
274 {
275 return -1;
276 }
277
278 /* Send data. */
279 LOG_Push((uint8_t *)buffer, size);
280
281 return size;
282 }
283
_read(int handle,char * buffer,int size)284 int __attribute__((weak)) _read(int handle, char *buffer, int size)
285 {
286 /* This function only reads from "standard in", for all other file handles it returns failure. */
287 if (handle != 0)
288 {
289 return -1;
290 }
291
292 /* Receive data. */
293 return LOG_ReadLine((uint8_t *)buffer, size);
294 }
295 #endif
296
297 /* These function fputc and fgetc is used to support KEIL toolchain to printf and scanf*/
298 #elif defined(__CC_ARM)
299 struct __FILE
300 {
301 int handle;
302 /*
303 * Whatever you require here. If the only file you are using is standard output using printf() for debugging,
304 * no file handling is required.
305 */
306 };
307
308 /* FILE is typedef in stdio.h. */
309 #pragma weak __stdout
310 #pragma weak __stdin
311 FILE __stdout;
312 FILE __stdin;
313
314 #pragma weak fputc
fputc(int ch,FILE * f)315 int fputc(int ch, FILE *f)
316 {
317 /* Send data. */
318 return LOG_Push((uint8_t *)(&ch), 1);
319 }
320
321 #pragma weak fgetc
fgetc(FILE * f)322 int fgetc(FILE *f)
323 {
324 char ch;
325
326 /* Receive data. */
327 LOG_ReadCharacter((uint8_t *)&ch);
328
329 return ch;
330 }
331 #endif /* __ICCARM__ */
332
333 #if defined(__riscv)
isatty(int fd)334 int isatty(int fd)
335 {
336 return 1;
337 }
338
fstat(int fd,struct stat * st)339 int fstat(int fd, struct stat *st)
340 {
341 st->st_mode = S_IFCHR;
342 return 0;
343 }
344
lseek(int fd,off_t ptr,int dir)345 int lseek(int fd, off_t ptr, int dir)
346 {
347 return 0;
348 }
349
close(int fd)350 int close(int fd)
351 {
352 return -1;
353 }
354
read(int fd,void * ptr,size_t len)355 int read(int fd, void* ptr, size_t len)
356 {
357 /* This function only reads from "standard in", for all other file handles it returns failure. */
358 if (fd != 0)
359 {
360 return -1;
361 }
362
363 /* Receive data. */
364 return LOG_ReadLine((uint8_t *)ptr, len);
365 }
366
write(int fd,const void * ptr,size_t len)367 int write(int fd, const void* ptr, size_t len)
368 {
369 if (ptr == 0)
370 {
371 /* return -1 if error. */
372 return -1;
373 }
374
375 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
376 if ((fd != 1) && (fd != 2))
377 {
378 return -1;
379 }
380
381 /* Send data. */
382 LOG_Push((uint8_t *)ptr, len);
383
384 return len;
385 }
386 #endif
387