1 /*
2 * Copyright 2017-2018, 2020, 2022NXP
3 * All rights reserved.
4 *
5 *
6 * SPDX-License-Identifier: BSD-3-Clause
7 *
8 */
9
10 #include <stdarg.h>
11 #include <stdlib.h>
12 #if defined(__CC_ARM) || defined(__ARMCC_VERSION)
13 #include <stdio.h>
14 #endif
15 #include <math.h>
16 #include "fsl_debug_console.h"
17 #include "fsl_adapter_uart.h"
18 #include "fsl_str.h"
19
20 /*! @brief Keil: suppress ellipsis warning in va_arg usage below. */
21 #if defined(__CC_ARM)
22 #pragma diag_suppress 1256
23 #endif /* __CC_ARM */
24
25 /*******************************************************************************
26 * Definitions
27 ******************************************************************************/
28
29 /*! @brief This definition is maximum line that debugconsole can scanf each time.*/
30 #define IO_MAXLINE 20U
31
32 /*! @brief The overflow value.*/
33 #ifndef HUGE_VAL
34 #define HUGE_VAL (99.e99)
35 #endif /* HUGE_VAL */
36
37 /*! @brief State structure storing debug console. */
38 typedef struct DebugConsoleState
39 {
40 uint8_t uartHandleBuffer[HAL_UART_HANDLE_SIZE];
41 hal_uart_status_t (*putChar)(hal_uart_handle_t handle,
42 const uint8_t *data,
43 size_t length); /*!< put char function pointer */
44 hal_uart_status_t (*getChar)(hal_uart_handle_t handle,
45 uint8_t *data,
46 size_t length); /*!< get char function pointer */
47 serial_port_type_t serial_port_type; /*!< The initialized port of the debug console. */
48 } debug_console_state_t;
49
50 /*! @brief Type of KSDK printf function pointer. */
51 typedef int (*PUTCHAR_FUNC)(int a);
52
53 /*******************************************************************************
54 * Variables
55 ******************************************************************************/
56 #if ((SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK) || defined(SDK_DEBUGCONSOLE_UART))
57 /*! @brief Debug UART state information. */
58 static debug_console_state_t s_debugConsole;
59 #endif
60
61 /*******************************************************************************
62 * Prototypes
63 ******************************************************************************/
64 #if (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK))
65 static int DbgConsole_PrintfFormattedData(PUTCHAR_FUNC func_ptr, const char *fmt, va_list ap);
66 #endif /* SDK_DEBUGCONSOLE */
67
68 /*******************************************************************************
69 * Code
70 ******************************************************************************/
71
72 /*************Code for DbgConsole Init, Deinit, Printf, Scanf *******************************/
73
74 #if ((SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK) || defined(SDK_DEBUGCONSOLE_UART))
75 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Init(uint8_t instance,uint32_t baudRate,serial_port_type_t device,uint32_t clkSrcFreq)76 status_t DbgConsole_Init(uint8_t instance, uint32_t baudRate, serial_port_type_t device, uint32_t clkSrcFreq)
77 {
78 hal_uart_config_t usrtConfig;
79
80 if (kSerialPort_Uart != device)
81 {
82 return kStatus_Fail;
83 }
84
85 /* Set debug console to initialized to avoid duplicated initialized operation. */
86 s_debugConsole.serial_port_type = device;
87
88 usrtConfig.srcClock_Hz = clkSrcFreq;
89 usrtConfig.baudRate_Bps = baudRate;
90 usrtConfig.parityMode = kHAL_UartParityDisabled;
91 usrtConfig.stopBitCount = kHAL_UartOneStopBit;
92 usrtConfig.enableRx = 1U;
93 usrtConfig.enableTx = 1U;
94 usrtConfig.enableRxRTS = 0U;
95 usrtConfig.enableTxCTS = 0U;
96 usrtConfig.instance = instance;
97 #if (defined(HAL_UART_ADAPTER_FIFO) && (HAL_UART_ADAPTER_FIFO > 0u))
98 usrtConfig.txFifoWatermark = 0U;
99 usrtConfig.rxFifoWatermark = 0U;
100 #endif
101 /* Enable clock and initial UART module follow user configure structure. */
102 (void)HAL_UartInit((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], &usrtConfig);
103 /* Set the function pointer for send and receive for this kind of device. */
104 s_debugConsole.putChar = HAL_UartSendBlocking;
105 s_debugConsole.getChar = HAL_UartReceiveBlocking;
106
107 return kStatus_Success;
108 }
109
110 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Deinit(void)111 status_t DbgConsole_Deinit(void)
112 {
113 if (kSerialPort_None == s_debugConsole.serial_port_type)
114 {
115 return kStatus_Success;
116 }
117
118 (void)HAL_UartDeinit((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0]);
119
120 s_debugConsole.serial_port_type = kSerialPort_None;
121 return kStatus_Success;
122 }
123
124 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_EnterLowpower(void)125 status_t DbgConsole_EnterLowpower(void)
126 {
127 hal_uart_status_t DbgConsoleUartStatus = kStatus_HAL_UartError;
128 if (kSerialPort_Uart == s_debugConsole.serial_port_type)
129 {
130 DbgConsoleUartStatus = HAL_UartEnterLowpower((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0]);
131 }
132 return (status_t)DbgConsoleUartStatus;
133 }
134
135 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_ExitLowpower(void)136 status_t DbgConsole_ExitLowpower(void)
137 {
138 hal_uart_status_t DbgConsoleUartStatus = kStatus_HAL_UartError;
139 if (kSerialPort_Uart == s_debugConsole.serial_port_type)
140 {
141 DbgConsoleUartStatus = HAL_UartExitLowpower((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0]);
142 }
143 return (status_t)DbgConsoleUartStatus;
144 }
145
146 #endif /* DEBUGCONSOLE_REDIRECT_TO_SDK */
147
148 #if (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK))
149 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Printf(const char * fmt_s,...)150 int DbgConsole_Printf(const char *fmt_s, ...)
151 {
152 va_list ap;
153 int result = 0;
154
155 va_start(ap, fmt_s);
156 result = DbgConsole_Vprintf(fmt_s, ap);
157 va_end(ap);
158
159 return result;
160 }
161
162 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Vprintf(const char * fmt_s,va_list formatStringArg)163 int DbgConsole_Vprintf(const char *fmt_s, va_list formatStringArg)
164 {
165 int result = 0;
166
167 /* Do nothing if the debug UART is not initialized. */
168 if (kSerialPort_None == s_debugConsole.serial_port_type)
169 {
170 return -1;
171 }
172
173 result = DbgConsole_PrintfFormattedData(DbgConsole_Putchar, fmt_s, formatStringArg);
174
175 return result;
176 }
177
178 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Putchar(int dbgConsoleCh)179 int DbgConsole_Putchar(int dbgConsoleCh)
180 {
181 /* Do nothing if the debug UART is not initialized. */
182 if (kSerialPort_None == s_debugConsole.serial_port_type)
183 {
184 return -1;
185 }
186 (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&dbgConsoleCh), 1);
187
188 return 1;
189 }
190
191 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Scanf(char * fmt_s,...)192 int DbgConsole_Scanf(char *fmt_s, ...)
193 {
194 /* Plus one to store end of string char */
195 char temp_buf[IO_MAXLINE + 1];
196 va_list ap;
197 int32_t i;
198 char result;
199
200 /* Do nothing if the debug UART is not initialized. */
201 if (kSerialPort_None == s_debugConsole.serial_port_type)
202 {
203 return -1;
204 }
205 va_start(ap, fmt_s);
206 temp_buf[0] = '\0';
207
208 i = 0;
209 while (true)
210 {
211 if (i >= (int32_t)IO_MAXLINE)
212 {
213 break;
214 }
215
216 result = (char)DbgConsole_Getchar();
217 temp_buf[i] = result;
218
219 if ((result == '\r') || (result == '\n'))
220 {
221 /* End of Line. */
222 if (i == 0)
223 {
224 temp_buf[i] = '\0';
225 i = -1;
226 }
227 else
228 {
229 break;
230 }
231 }
232
233 i++;
234 }
235
236 if (i == (int32_t)IO_MAXLINE)
237 {
238 temp_buf[i] = '\0';
239 }
240 else
241 {
242 temp_buf[i + 1] = '\0';
243 }
244 result = (char)StrFormatScanf(temp_buf, fmt_s, ap);
245 va_end(ap);
246
247 return (int)result;
248 }
249
250 /* See fsl_debug_console.h for documentation of this function. */
DbgConsole_Getchar(void)251 int DbgConsole_Getchar(void)
252 {
253 char dbgConsoleCh;
254 /* Do nothing if the debug UART is not initialized. */
255 if (kSerialPort_None == s_debugConsole.serial_port_type)
256 {
257 return -1;
258 }
259 while (kStatus_HAL_UartSuccess !=
260 s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&dbgConsoleCh), 1))
261 {
262 return -1;
263 }
264
265 return (int)dbgConsoleCh;
266 }
267
268 /*************Code for process formatted data*******************************/
269 /*!
270 * @brief This function puts padding character.
271 *
272 * @param[in] c Padding character.
273 * @param[in] curlen Length of current formatted string .
274 * @param[in] width Width of expected formatted string.
275 * @param[in] count Number of characters.
276 * @param[in] func_ptr Function to put character out.
277 */
DbgConsole_PrintfPaddingCharacter(char c,int32_t curlen,int32_t width,int32_t * count,PUTCHAR_FUNC func_ptr)278 static void DbgConsole_PrintfPaddingCharacter(
279 char c, int32_t curlen, int32_t width, int32_t *count, PUTCHAR_FUNC func_ptr)
280 {
281 int32_t i;
282
283 for (i = curlen; i < width; i++)
284 {
285 (void)func_ptr(c);
286 (*count)++;
287 }
288 }
289
290 /*!
291 * @brief Converts a radix number to a string and return its length.
292 *
293 * @param[in] numstr Converted string of the number.
294 * @param[in] nump Pointer to the number.
295 * @param[in] neg Polarity of the number.
296 * @param[in] radix The radix to be converted to.
297 * @param[in] use_caps Used to identify %x/X output format.
298
299 * @return Length of the converted string.
300 */
DbgConsole_ConvertRadixNumToString(char * numstr,void * nump,int32_t neg,int32_t radix,bool use_caps)301 static int32_t DbgConsole_ConvertRadixNumToString(char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps)
302 {
303 #if PRINTF_ADVANCED_ENABLE
304 long long int a;
305 long long int b;
306 long long int c;
307
308 unsigned long long int ua;
309 unsigned long long int ub;
310 unsigned long long int uc;
311 unsigned long long int uc_param;
312 #else
313 int a;
314 int b;
315 int c;
316
317 unsigned int ua;
318 unsigned int ub;
319 unsigned int uc;
320 unsigned int uc_param;
321 #endif /* PRINTF_ADVANCED_ENABLE */
322
323 int32_t nlen;
324 char *nstrp;
325
326 nlen = 0;
327 nstrp = numstr;
328 *nstrp++ = '\0';
329
330 #if !(PRINTF_ADVANCED_ENABLE > 0)
331 neg = 0;
332 #endif
333
334 #if PRINTF_ADVANCED_ENABLE
335 a = 0;
336 b = 0;
337 c = 0;
338 ua = 0ULL;
339 ub = 0ULL;
340 uc = 0ULL;
341 uc_param = 0ULL;
342 #else
343 a = 0;
344 b = 0;
345 c = 0;
346 ua = 0U;
347 ub = 0U;
348 uc = 0U;
349 uc_param = 0U;
350 #endif /* PRINTF_ADVANCED_ENABLE */
351
352 (void)a;
353 (void)b;
354 (void)c;
355 (void)ua;
356 (void)ub;
357 (void)uc;
358 (void)uc_param;
359 (void)neg;
360 /*
361 * Fix MISRA issue: CID 15985711 (#15 of 15): MISRA C-2012 Control Flow Expressions (MISRA C-2012 Rule 14.3)
362 * misra_c_2012_rule_14_3_violation: Execution cannot reach this statement: a = *((int *)nump);
363 */
364 #if PRINTF_ADVANCED_ENABLE
365 if (0 != neg)
366 {
367 #if PRINTF_ADVANCED_ENABLE
368 a = *(long long int *)nump;
369 #else
370 a = *(int *)nump;
371 #endif /* PRINTF_ADVANCED_ENABLE */
372 if (a == 0)
373 {
374 *nstrp = '0';
375 ++nlen;
376 return nlen;
377 }
378 while (a != 0)
379 {
380 #if PRINTF_ADVANCED_ENABLE
381 b = (long long int)a / (long long int)radix;
382 c = (long long int)a - ((long long int)b * (long long int)radix);
383 if (c < 0)
384 {
385 uc = (unsigned long long int)c;
386 uc_param = ~uc;
387 c = (long long int)uc_param + 1 + (long long int)'0';
388 }
389 #else
390 b = (int)a / (int)radix;
391 c = (int)a - ((int)b * (int)radix);
392 if (c < 0)
393 {
394 uc = (unsigned int)c;
395 uc_param = ~uc;
396 c = (int)uc_param + 1 + (int)'0';
397 }
398 #endif /* PRINTF_ADVANCED_ENABLE */
399 else
400 {
401 c = c + (int)'0';
402 }
403 a = b;
404 *nstrp++ = (char)c;
405 ++nlen;
406 }
407 }
408 else
409 #endif /* PRINTF_ADVANCED_ENABLE */
410 {
411 #if PRINTF_ADVANCED_ENABLE
412 ua = *(unsigned long long int *)nump;
413 #else
414 ua = *(unsigned int *)nump;
415 #endif /* PRINTF_ADVANCED_ENABLE */
416 if (ua == 0U)
417 {
418 *nstrp = '0';
419 ++nlen;
420 return nlen;
421 }
422 while (ua != 0U)
423 {
424 #if PRINTF_ADVANCED_ENABLE
425 ub = (unsigned long long int)ua / (unsigned long long int)radix;
426 uc = (unsigned long long int)ua - ((unsigned long long int)ub * (unsigned long long int)radix);
427 #else
428 ub = ua / (unsigned int)radix;
429 uc = ua - (ub * (unsigned int)radix);
430 #endif /* PRINTF_ADVANCED_ENABLE */
431
432 if (uc < 10U)
433 {
434 uc = uc + (unsigned int)'0';
435 }
436 else
437 {
438 uc = uc - 10U + (unsigned int)(use_caps ? 'A' : 'a');
439 }
440 ua = ub;
441 *nstrp++ = (char)uc;
442 ++nlen;
443 }
444 }
445 return nlen;
446 }
447
448 #if PRINTF_FLOAT_ENABLE
449 /*!
450 * @brief Converts a floating radix number to a string and return its length.
451 *
452 * @param[in] numstr Converted string of the number.
453 * @param[in] nump Pointer to the number.
454 * @param[in] radix The radix to be converted to.
455 * @param[in] precision_width Specify the precision width.
456
457 * @return Length of the converted string.
458 */
DbgConsole_ConvertFloatRadixNumToString(char * numstr,void * nump,int32_t radix,uint32_t precision_width)459 static int32_t DbgConsole_ConvertFloatRadixNumToString(char *numstr,
460 void *nump,
461 int32_t radix,
462 uint32_t precision_width)
463 {
464 int32_t a;
465 int32_t b;
466 int32_t c;
467 uint32_t i;
468 double fa;
469 double dc;
470 double fb;
471 double r;
472 double fractpart;
473 double intpart;
474
475 int32_t nlen;
476 char *nstrp;
477 nlen = 0;
478 nstrp = numstr;
479 *nstrp++ = '\0';
480 r = *(double *)nump;
481 if (0.0 == r)
482 {
483 *nstrp = '0';
484 ++nlen;
485 return nlen;
486 }
487 fractpart = modf((double)r, (double *)&intpart);
488 /* Process fractional part. */
489 for (i = 0; i < precision_width; i++)
490 {
491 fractpart *= (double)radix;
492 }
493 if (r >= 0.0)
494 {
495 fa = fractpart + (double)0.5;
496 if (fa >= pow((double)10, (double)precision_width))
497 {
498 intpart++;
499 }
500 }
501 else
502 {
503 fa = fractpart - (double)0.5;
504 if (fa <= -pow((double)10, (double)precision_width))
505 {
506 intpart--;
507 }
508 }
509 for (i = 0; i < precision_width; i++)
510 {
511 fb = fa / (double)radix;
512 dc = (fa - (double)(long long int)fb * (double)radix);
513 c = (int32_t)dc;
514 if (c < 0)
515 {
516 c = (int32_t)'0' - c;
517 }
518 else
519 {
520 c = c + '0';
521 }
522 fa = fb;
523 *nstrp++ = (char)c;
524 ++nlen;
525 }
526 *nstrp++ = (char)'.';
527 ++nlen;
528 a = (int32_t)intpart;
529 if (a == 0)
530 {
531 *nstrp++ = '0';
532 ++nlen;
533 }
534 else
535 {
536 while (a != 0)
537 {
538 b = (int32_t)a / (int32_t)radix;
539 c = (int32_t)a - ((int32_t)b * (int32_t)radix);
540 if (c < 0)
541 {
542 c = (int32_t)'0' - c;
543 }
544 else
545 {
546 c = c + '0';
547 }
548 a = b;
549 *nstrp++ = (char)c;
550 ++nlen;
551 }
552 }
553 return nlen;
554 }
555 #endif /* PRINTF_FLOAT_ENABLE */
556
557 /*!
558 * @brief This function outputs its parameters according to a formatted string.
559 *
560 * @note I/O is performed by calling given function pointer using following
561 * (*func_ptr)(c);
562 *
563 * @param[in] func_ptr Function to put character out.
564 * @param[in] fmt Format string for printf.
565 * @param[in] ap Arguments to printf.
566 *
567 * @return Number of characters
568 */
DbgConsole_PrintfFormattedData(PUTCHAR_FUNC func_ptr,const char * fmt,va_list ap)569 static int DbgConsole_PrintfFormattedData(PUTCHAR_FUNC func_ptr, const char *fmt, va_list ap)
570 {
571 /* va_list ap; */
572 const char *p;
573 char c;
574
575 char vstr[33];
576 char *vstrp = NULL;
577 int32_t vlen = 0;
578
579 bool done;
580 int32_t count = 0;
581
582 uint32_t field_width;
583 uint32_t precision_width;
584 char *sval;
585 int32_t cval;
586 bool use_caps;
587 uint8_t radix = 0;
588
589 #if PRINTF_ADVANCED_ENABLE
590 uint32_t flags_used;
591 char schar;
592 bool dschar;
593 long long int ival;
594 unsigned long long int uval = 0;
595 bool valid_precision_width;
596 #else
597 int ival;
598 unsigned int uval = 0;
599 #endif /* PRINTF_ADVANCED_ENABLE */
600
601 #if PRINTF_FLOAT_ENABLE
602 double fval;
603 #endif /* PRINTF_FLOAT_ENABLE */
604
605 /* Start parsing apart the format string and display appropriate formats and data. */
606 p = fmt;
607 while (true)
608 {
609 if ('\0' == *p)
610 {
611 break;
612 }
613 c = *p;
614 /*
615 * All formats begin with a '%' marker. Special chars like
616 * '\n' or '\t' are normally converted to the appropriate
617 * character by the __compiler__. Thus, no need for this
618 * routine to account for the '\' character.
619 */
620 if (c != '%')
621 {
622 (void)func_ptr(c);
623 count++;
624 p++;
625 /* By using 'continue', the next iteration of the loop is used, skipping the code that follows. */
626 continue;
627 }
628
629 use_caps = true;
630
631 #if PRINTF_ADVANCED_ENABLE
632 /* First check for specification modifier flags. */
633 flags_used = 0;
634 done = false;
635 while (!done)
636 {
637 switch (*++p)
638 {
639 case '-':
640 flags_used |= (uint32_t)kPRINTF_Minus;
641 break;
642 case '+':
643 flags_used |= (uint32_t)kPRINTF_Plus;
644 break;
645 case ' ':
646 flags_used |= (uint32_t)kPRINTF_Space;
647 break;
648 case '0':
649 flags_used |= (uint32_t)kPRINTF_Zero;
650 break;
651 case '#':
652 flags_used |= (uint32_t)kPRINTF_Pound;
653 break;
654 default:
655 /* We've gone one char too far. */
656 --p;
657 done = true;
658 break;
659 }
660 }
661 #endif /* PRINTF_ADVANCED_ENABLE */
662
663 /* Next check for minimum field width. */
664 field_width = 0;
665 done = false;
666 while (!done)
667 {
668 c = *++p;
669 if ((c >= '0') && (c <= '9'))
670 {
671 field_width = (field_width * 10U) + ((uint32_t)c - (uint32_t)'0');
672 }
673 #if PRINTF_ADVANCED_ENABLE
674 else if (c == '*')
675 {
676 field_width = (uint32_t)va_arg(ap, unsigned int);
677 }
678 #endif /* PRINTF_ADVANCED_ENABLE */
679 else
680 {
681 /* We've gone one char too far. */
682 --p;
683 done = true;
684 }
685 }
686 /* Next check for the width and precision field separator. */
687 #if (PRINTF_ADVANCED_ENABLE || PRINTF_FLOAT_ENABLE)
688 precision_width = 6U; /* MISRA C-2012 Rule 2.2 */
689 #endif
690 #if PRINTF_ADVANCED_ENABLE
691 valid_precision_width = false;
692 #endif /* PRINTF_ADVANCED_ENABLE */
693 if (*++p == '.')
694 {
695 /* Must get precision field width, if present. */
696 precision_width = 0U;
697 done = false;
698 while (!done)
699 {
700 c = *++p;
701 if ((c >= '0') && (c <= '9'))
702 {
703 precision_width = (precision_width * 10U) + ((uint32_t)c - (uint32_t)'0');
704 #if PRINTF_ADVANCED_ENABLE
705 valid_precision_width = true;
706 #endif /* PRINTF_ADVANCED_ENABLE */
707 }
708 #if PRINTF_ADVANCED_ENABLE
709 else if (c == '*')
710 {
711 precision_width = (uint32_t)va_arg(ap, unsigned int);
712 valid_precision_width = true;
713 }
714 #endif /* PRINTF_ADVANCED_ENABLE */
715 else
716 {
717 /* We've gone one char too far. */
718 --p;
719 done = true;
720 }
721 }
722 }
723 else
724 {
725 /* We've gone one char too far. */
726 --p;
727 }
728 #if PRINTF_ADVANCED_ENABLE
729 /*
730 * Check for the length modifier.
731 */
732 switch (/* c = */ *++p)
733 {
734 case 'h':
735 if (*++p != 'h')
736 {
737 flags_used |= (uint32_t)kPRINTF_LengthShortInt;
738 --p;
739 }
740 else
741 {
742 flags_used |= (uint32_t)kPRINTF_LengthChar;
743 }
744 break;
745 case 'l':
746 if (*++p != 'l')
747 {
748 flags_used |= (uint32_t)kPRINTF_LengthLongInt;
749 --p;
750 }
751 else
752 {
753 flags_used |= (uint32_t)kPRINTF_LengthLongLongInt;
754 }
755 break;
756 case 'z':
757 if (sizeof(size_t) == sizeof(uint32_t))
758 {
759 flags_used |= (uint32_t)kPRINTF_LengthLongInt;
760 }
761 else if (sizeof(size_t) == (2U * sizeof(uint32_t)))
762 {
763 flags_used |= (uint32_t)kPRINTF_LengthLongLongInt;
764 }
765 else if (sizeof(size_t) == sizeof(uint16_t))
766 {
767 flags_used |= (uint32_t)kPRINTF_LengthShortInt;
768 }
769 else
770 {
771 /* MISRA C-2012 Rule 15.7 */
772 }
773 break;
774 default:
775 /* we've gone one char too far */
776 --p;
777 break;
778 }
779 #endif /* PRINTF_ADVANCED_ENABLE */
780 /* Now we're ready to examine the format. */
781 c = *++p;
782 {
783 if ((c == 'd') || (c == 'i') || (c == 'f') || (c == 'F') || (c == 'x') || (c == 'X') || (c == 'o') ||
784 (c == 'b') || (c == 'p') || (c == 'u'))
785 {
786 if ((c == 'd') || (c == 'i'))
787 {
788 #if PRINTF_ADVANCED_ENABLE
789 if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt))
790 {
791 ival = (long long int)va_arg(ap, long long int);
792 }
793 else if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongInt))
794 {
795 ival = (long int)va_arg(ap, long int);
796 }
797 else
798 #endif /* PRINTF_ADVANCED_ENABLE */
799 {
800 ival = (int)va_arg(ap, int);
801 }
802 vlen = DbgConsole_ConvertRadixNumToString(vstr, &ival, 1, 10, use_caps);
803 vstrp = &vstr[vlen];
804 #if PRINTF_ADVANCED_ENABLE
805 if (ival < 0)
806 {
807 schar = '-';
808 ++vlen;
809 }
810 else
811 {
812 if (0U != (flags_used & (uint32_t)kPRINTF_Plus))
813 {
814 schar = '+';
815 ++vlen;
816 }
817 else
818 {
819 if (0U != (flags_used & (uint32_t)kPRINTF_Space))
820 {
821 schar = ' ';
822 ++vlen;
823 }
824 else
825 {
826 schar = '\0';
827 }
828 }
829 }
830 dschar = false;
831 /* Do the ZERO pad. */
832 if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
833 {
834 if ('\0' != schar)
835 {
836 (void)func_ptr(schar);
837 count++;
838 }
839 dschar = true;
840
841 DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr);
842 vlen = (int32_t)field_width;
843 }
844 else
845 {
846 if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
847 {
848 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
849 if ('\0' != schar)
850 {
851 (void)func_ptr(schar);
852 count++;
853 }
854 dschar = true;
855 }
856 }
857 /* The string was built in reverse order, now display in correct order. */
858 if ((!dschar) && ('\0' != schar))
859 {
860 (void)func_ptr(schar);
861 count++;
862 }
863 #endif /* PRINTF_ADVANCED_ENABLE */
864 }
865
866 #if PRINTF_FLOAT_ENABLE
867 if ((c == 'f') || (c == 'F'))
868 {
869 fval = (double)va_arg(ap, double);
870 vlen = DbgConsole_ConvertFloatRadixNumToString(vstr, &fval, 10, precision_width);
871 vstrp = &vstr[vlen];
872
873 #if PRINTF_ADVANCED_ENABLE
874 if (fval < 0.0)
875 {
876 schar = '-';
877 ++vlen;
878 }
879 else
880 {
881 if (0U != (flags_used & (uint32_t)kPRINTF_Plus))
882 {
883 schar = '+';
884 ++vlen;
885 }
886 else
887 {
888 if (0U != (flags_used & (uint32_t)kPRINTF_Space))
889 {
890 schar = ' ';
891 ++vlen;
892 }
893 else
894 {
895 schar = '\0';
896 }
897 }
898 }
899 dschar = false;
900 if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
901 {
902 if ('\0' != schar)
903 {
904 (void)func_ptr(schar);
905 count++;
906 }
907 dschar = true;
908 DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr);
909 vlen = (int32_t)field_width;
910 }
911 else
912 {
913 if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
914 {
915 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
916 if ('\0' != schar)
917 {
918 (void)func_ptr(schar);
919 count++;
920 }
921 dschar = true;
922 }
923 }
924 if ((!dschar) && ('\0' != schar))
925 {
926 (void)func_ptr(schar);
927 count++;
928 }
929 #endif /* PRINTF_ADVANCED_ENABLE */
930 }
931 #endif /* PRINTF_FLOAT_ENABLE */
932 if ((c == 'X') || (c == 'x'))
933 {
934 if (c == 'x')
935 {
936 use_caps = false;
937 }
938 #if PRINTF_ADVANCED_ENABLE
939 if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt))
940 {
941 uval = (unsigned long long int)va_arg(ap, unsigned long long int);
942 }
943 else if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongInt))
944 {
945 uval = (unsigned long int)va_arg(ap, unsigned long int);
946 }
947 else
948 #endif /* PRINTF_ADVANCED_ENABLE */
949 {
950 uval = (unsigned int)va_arg(ap, unsigned int);
951 }
952 vlen = DbgConsole_ConvertRadixNumToString(vstr, &uval, 0, 16, use_caps);
953 vstrp = &vstr[vlen];
954
955 #if PRINTF_ADVANCED_ENABLE
956 dschar = false;
957 if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
958 {
959 if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
960 {
961 (void)func_ptr('0');
962 (void)func_ptr((use_caps ? 'X' : 'x'));
963 count += 2;
964 /*vlen += 2;*/
965 dschar = true;
966 }
967 DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr);
968 vlen = (int32_t)field_width;
969 }
970 else
971 {
972 if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
973 {
974 if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
975 {
976 vlen += 2;
977 }
978 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
979 if (0U != (flags_used & (uint32_t)kPRINTF_Pound))
980 {
981 (void)func_ptr('0');
982 (void)func_ptr(use_caps ? 'X' : 'x');
983 count += 2;
984
985 dschar = true;
986 }
987 }
988 }
989
990 if ((0U != (flags_used & (uint32_t)kPRINTF_Pound)) && (!dschar))
991 {
992 (void)func_ptr('0');
993 (void)func_ptr(use_caps ? 'X' : 'x');
994 count += 2;
995 vlen += 2;
996 }
997 #endif /* PRINTF_ADVANCED_ENABLE */
998 }
999 if ((c == 'o') || (c == 'b') || (c == 'p') || (c == 'u'))
1000 {
1001 if ('p' == c)
1002 {
1003 /*
1004 * Fix MISRA issue: CID 16209727 (#15 of 15): MISRA C-2012 Pointer Type Conversions (MISRA
1005 * C-2012 Rule 11.6)
1006 * 1. misra_c_2012_rule_11_6_violation: The expression va_arg (ap, void *) of type void * is
1007 * cast to type unsigned int.
1008 *
1009 * Orignal code: uval = (unsigned int)va_arg(ap, void *);
1010 */
1011 void *pval;
1012 pval = (void *)va_arg(ap, void *);
1013 (void)memcpy((void *)&uval, (void *)&pval, sizeof(void *));
1014 }
1015 else
1016 {
1017 #if PRINTF_ADVANCED_ENABLE
1018 if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt))
1019 {
1020 uval = (unsigned long long int)va_arg(ap, unsigned long long int);
1021 }
1022 else if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongInt))
1023 {
1024 uval = (unsigned long int)va_arg(ap, unsigned long int);
1025 }
1026 else
1027 #endif /* PRINTF_ADVANCED_ENABLE */
1028 {
1029 uval = (unsigned int)va_arg(ap, unsigned int);
1030 }
1031 }
1032 switch (c)
1033 {
1034 case 'o':
1035 radix = 8;
1036 break;
1037 case 'b':
1038 radix = 2;
1039 break;
1040 case 'p':
1041 radix = 16;
1042 break;
1043 case 'u':
1044 radix = 10;
1045 break;
1046 default:
1047 /* MISRA C-2012 Rule 16.4 */
1048 break;
1049 }
1050 vlen = DbgConsole_ConvertRadixNumToString(vstr, &uval, 0, (int32_t)radix, use_caps);
1051 vstrp = &vstr[vlen];
1052 #if PRINTF_ADVANCED_ENABLE
1053 if (0U != (flags_used & (uint32_t)kPRINTF_Zero))
1054 {
1055 DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr);
1056 vlen = (int32_t)field_width;
1057 }
1058 else
1059 {
1060 if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
1061 {
1062 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
1063 }
1064 }
1065 #endif /* PRINTF_ADVANCED_ENABLE */
1066 }
1067 #if !PRINTF_ADVANCED_ENABLE
1068 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
1069 #endif /* !PRINTF_ADVANCED_ENABLE */
1070 if (vstrp != NULL)
1071 {
1072 while ('\0' != *vstrp)
1073 {
1074 (void)func_ptr(*vstrp--);
1075 count++;
1076 }
1077 }
1078 #if PRINTF_ADVANCED_ENABLE
1079 if (0U != (flags_used & (uint32_t)kPRINTF_Minus))
1080 {
1081 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
1082 }
1083 #endif /* PRINTF_ADVANCED_ENABLE */
1084 }
1085 else if (c == 'c')
1086 {
1087 cval = (int32_t)va_arg(ap, unsigned int);
1088 (void)func_ptr(cval);
1089 count++;
1090 }
1091 else if (c == 's')
1092 {
1093 sval = (char *)va_arg(ap, char *);
1094 if (NULL != sval)
1095 {
1096 #if PRINTF_ADVANCED_ENABLE
1097 if (valid_precision_width)
1098 {
1099 vlen = (int32_t)precision_width;
1100 }
1101 else
1102 {
1103 vlen = (int32_t)strlen(sval);
1104 }
1105 #else
1106 vlen = (int32_t)strlen(sval);
1107 #endif /* PRINTF_ADVANCED_ENABLE */
1108 #if PRINTF_ADVANCED_ENABLE
1109 if (0U == (flags_used & (uint32_t)kPRINTF_Minus))
1110 #endif /* PRINTF_ADVANCED_ENABLE */
1111 {
1112 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
1113 }
1114
1115 #if PRINTF_ADVANCED_ENABLE
1116 if (valid_precision_width)
1117 {
1118 while (('\0' != *sval) && (vlen > 0))
1119 {
1120 (void)func_ptr(*sval++);
1121 count++;
1122 vlen--;
1123 }
1124 /* In case that vlen sval is shorter than vlen */
1125 vlen = (int32_t)precision_width - vlen;
1126 }
1127 else
1128 {
1129 #endif /* PRINTF_ADVANCED_ENABLE */
1130 while ('\0' != *sval)
1131 {
1132 (void)func_ptr(*sval++);
1133 count++;
1134 }
1135 #if PRINTF_ADVANCED_ENABLE
1136 }
1137 #endif /* PRINTF_ADVANCED_ENABLE */
1138
1139 #if PRINTF_ADVANCED_ENABLE
1140 if (0U != (flags_used & (uint32_t)kPRINTF_Minus))
1141 {
1142 DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr);
1143 }
1144 #endif /* PRINTF_ADVANCED_ENABLE */
1145 }
1146 }
1147 else
1148 {
1149 (void)func_ptr(c);
1150 count++;
1151 }
1152 }
1153 p++;
1154 }
1155 return count;
1156 }
1157
1158 #endif /* SDK_DEBUGCONSOLE */
1159
1160 /*************Code to support toolchain's printf, scanf *******************************/
1161 /* These function __write and __read is used to support IAR toolchain to printf and scanf*/
1162 #if (defined(__ICCARM__))
1163 #if defined(SDK_DEBUGCONSOLE_UART)
1164 #pragma weak __write
1165 size_t __write(int handle, const unsigned char *buffer, size_t size);
__write(int handle,const unsigned char * buffer,size_t size)1166 size_t __write(int handle, const unsigned char *buffer, size_t size)
1167 {
1168 size_t ret;
1169 if (NULL == buffer)
1170 {
1171 /*
1172 * This means that we should flush internal buffers. Since we don't we just return.
1173 * (Remember, "handle" == -1 means that all handles should be flushed.)
1174 */
1175 ret = (size_t)0;
1176 }
1177 else if ((handle != 1) && (handle != 2))
1178 {
1179 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure.
1180 */
1181 ret = (size_t)-1;
1182 }
1183 else if (kSerialPort_None == s_debugConsole.serial_port_type)
1184 {
1185 /* Do nothing if the debug UART is not initialized. */
1186 ret = (size_t)-1;
1187 }
1188 else
1189 {
1190 /* Send data. */
1191 (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], buffer, size);
1192 ret = size;
1193 }
1194 return ret;
1195 }
1196
1197 #pragma weak __read
1198 size_t __read(int handle, unsigned char *buffer, size_t size);
__read(int handle,unsigned char * buffer,size_t size)1199 size_t __read(int handle, unsigned char *buffer, size_t size)
1200 {
1201 size_t ret;
1202 /* This function only reads from "standard in", for all other file handles it returns failure. */
1203 if (handle != 0)
1204 {
1205 ret = ((size_t)-1);
1206 }
1207 else if (kSerialPort_None == s_debugConsole.serial_port_type)
1208 {
1209 /* Do nothing if the debug UART is not initialized. */
1210 ret = ((size_t)-1);
1211 }
1212 else
1213 {
1214 /* Receive data. */
1215 (void)s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], buffer, size);
1216 ret = size;
1217 }
1218 return ret;
1219 }
1220 #endif /* SDK_DEBUGCONSOLE_UART */
1221
1222 /* support LPC Xpresso with RedLib */
1223 #elif (defined(__REDLIB__))
1224
1225 #if (defined(SDK_DEBUGCONSOLE_UART))
__sys_write(int handle,char * buffer,int size)1226 int __attribute__((weak)) __sys_write(int handle, char *buffer, int size)
1227 {
1228 if (NULL == buffer)
1229 {
1230 /* return -1 if error. */
1231 return -1;
1232 }
1233
1234 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
1235 if ((handle != 1) && (handle != 2))
1236 {
1237 return -1;
1238 }
1239
1240 /* Do nothing if the debug UART is not initialized. */
1241 if (kSerialPort_None == s_debugConsole.serial_port_type)
1242 {
1243 return -1;
1244 }
1245
1246 /* Send data. */
1247 (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size);
1248
1249 return 0;
1250 }
1251
__sys_readc(void)1252 int __attribute__((weak)) __sys_readc(void)
1253 {
1254 char tmp;
1255 /* Do nothing if the debug UART is not initialized. */
1256 if (kSerialPort_None == s_debugConsole.serial_port_type)
1257 {
1258 return -1;
1259 }
1260
1261 /* Receive data. */
1262 s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)&tmp, sizeof(tmp));
1263
1264 return tmp;
1265 }
1266 #endif /* SDK_DEBUGCONSOLE_UART */
1267
1268 /* These function fputc and fgetc is used to support KEIL toolchain to printf and scanf*/
1269 #elif defined(__CC_ARM) || defined(__ARMCC_VERSION)
1270 #if defined(SDK_DEBUGCONSOLE_UART)
1271 #if defined(__CC_ARM)
1272 struct __FILE
1273 {
1274 int handle;
1275 /*
1276 * Whatever you require here. If the only file you are using is standard output using printf() for debugging,
1277 * no file handling is required.
1278 */
1279 };
1280 #endif
1281
1282 /* FILE is typedef in stdio.h. */
1283 #pragma weak __stdout
1284 #pragma weak __stdin
1285 FILE __stdout;
1286 FILE __stdin;
1287
1288 #pragma weak fputc
fputc(int ch,FILE * f)1289 int fputc(int ch, FILE *f)
1290 {
1291 /* Do nothing if the debug UART is not initialized. */
1292 if (kSerialPort_None == s_debugConsole.serial_port_type)
1293 {
1294 return -1;
1295 }
1296
1297 /* Send data. */
1298 (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&ch), 1);
1299 return 1;
1300 }
1301
1302 #pragma weak fgetc
fgetc(FILE * f)1303 int fgetc(FILE *f)
1304 {
1305 char ch;
1306 /* Do nothing if the debug UART is not initialized. */
1307 if (kSerialPort_None == s_debugConsole.serial_port_type)
1308 {
1309 return -1;
1310 }
1311
1312 /* Receive data. */
1313 s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&ch), 1);
1314 return ch;
1315 }
1316
1317 /*
1318 * Terminate the program, passing a return code back to the user.
1319 * This function may not return.
1320 */
_sys_exit(int returncode)1321 void _sys_exit(int returncode)
1322 {
1323 while (1)
1324 {
1325 }
1326 }
1327
1328 /*
1329 * Writes a character to the output channel. This function is used
1330 * for last-resort error message output.
1331 */
_ttywrch(int ch)1332 void _ttywrch(int ch)
1333 {
1334 char ench = ch;
1335 /* Send data. */
1336 s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&ench), 1);
1337 }
1338
_sys_command_string(char * cmd,int len)1339 char *_sys_command_string(char *cmd, int len)
1340 {
1341 return (cmd);
1342 }
1343 #endif /* SDK_DEBUGCONSOLE_UART */
1344
1345 /* These function __write_r and __read_r are used to support Xtensa Clang toolchain to printf and scanf */
1346 #elif defined(__XTENSA__) && defined(__XT_CLANG__)
1347 #if defined(SDK_DEBUGCONSOLE_UART)
1348
1349 int __attribute__((weak)) _write_r(void *ptr, int handle, char *buffer, int size);
_write_r(void * ptr,int handle,char * buffer,int size)1350 int __attribute__((weak)) _write_r(void *ptr, int handle, char *buffer, int size)
1351 {
1352 if (NULL == buffer)
1353 {
1354 /* return -1 if error. */
1355 return -1;
1356 }
1357
1358 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
1359 if ((handle != 1) && (handle != 2))
1360 {
1361 return -1;
1362 }
1363
1364 /* Do nothing if the debug UART is not initialized. */
1365 if (kSerialPort_None == s_debugConsole.serial_port_type)
1366 {
1367 return -1;
1368 }
1369
1370 /* Send data. */
1371 (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size);
1372
1373 return size;
1374 }
1375
1376 int __attribute__((weak)) _read_r(void *ptr, int handle, char *buffer, int size);
_read_r(void * ptr,int handle,char * buffer,int size)1377 int __attribute__((weak)) _read_r(void *ptr, int handle, char *buffer, int size)
1378 {
1379 /* This function only reads from "standard in", for all other file handles it returns failure. */
1380 if (handle != 0)
1381 {
1382 return -1;
1383 }
1384
1385 /* Do nothing if the debug UART is not initialized. */
1386 if (kSerialPort_None == s_debugConsole.serial_port_type)
1387 {
1388 return -1;
1389 }
1390
1391 /* Receive data. */
1392 (void)s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size);
1393 return size;
1394 }
1395 #endif /* SDK_DEBUGCONSOLE_UART */
1396
1397 /* These function __write and __read is used to support ARM_GCC, KDS, Atollic toolchains to printf and scanf*/
1398 #elif (defined(__GNUC__))
1399
1400 #if ((defined(__GNUC__) && (!defined(__MCUXPRESSO)) && (defined(SDK_DEBUGCONSOLE_UART))) || \
1401 (defined(__MCUXPRESSO) && (defined(SDK_DEBUGCONSOLE_UART))))
1402 int __attribute__((weak)) _write(int handle, char *buffer, int size);
_write(int handle,char * buffer,int size)1403 int __attribute__((weak)) _write(int handle, char *buffer, int size)
1404 {
1405 if (NULL == buffer)
1406 {
1407 /* return -1 if error. */
1408 return -1;
1409 }
1410
1411 /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
1412 if ((handle != 1) && (handle != 2))
1413 {
1414 return -1;
1415 }
1416
1417 /* Do nothing if the debug UART is not initialized. */
1418 if (kSerialPort_None == s_debugConsole.serial_port_type)
1419 {
1420 return -1;
1421 }
1422
1423 /* Send data. */
1424 (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size);
1425
1426 return size;
1427 }
1428
1429 int __attribute__((weak)) _read(int handle, char *buffer, int size);
_read(int handle,char * buffer,int size)1430 int __attribute__((weak)) _read(int handle, char *buffer, int size)
1431 {
1432 /* This function only reads from "standard in", for all other file handles it returns failure. */
1433 if (handle != 0)
1434 {
1435 return -1;
1436 }
1437
1438 /* Do nothing if the debug UART is not initialized. */
1439 if (kSerialPort_None == s_debugConsole.serial_port_type)
1440 {
1441 return -1;
1442 }
1443
1444 /* Receive data. */
1445 (void)s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size);
1446 return size;
1447 }
1448 #endif
1449
1450 #endif /* __ICCARM__ */
1451