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