/* * Copyright 2017-2018, 2020, 2022NXP * All rights reserved. * * * SPDX-License-Identifier: BSD-3-Clause * */ #include #include #if defined(__CC_ARM) || defined(__ARMCC_VERSION) #include #endif #include #include "fsl_debug_console.h" #include "fsl_adapter_uart.h" #include "fsl_str.h" /*! @brief Keil: suppress ellipsis warning in va_arg usage below. */ #if defined(__CC_ARM) #pragma diag_suppress 1256 #endif /* __CC_ARM */ /******************************************************************************* * Definitions ******************************************************************************/ /*! @brief This definition is maximum line that debugconsole can scanf each time.*/ #define IO_MAXLINE 20U /*! @brief The overflow value.*/ #ifndef HUGE_VAL #define HUGE_VAL (99.e99) #endif /* HUGE_VAL */ /*! @brief State structure storing debug console. */ typedef struct DebugConsoleState { uint8_t uartHandleBuffer[HAL_UART_HANDLE_SIZE]; hal_uart_status_t (*putChar)(hal_uart_handle_t handle, const uint8_t *data, size_t length); /*!< put char function pointer */ hal_uart_status_t (*getChar)(hal_uart_handle_t handle, uint8_t *data, size_t length); /*!< get char function pointer */ serial_port_type_t serial_port_type; /*!< The initialized port of the debug console. */ } debug_console_state_t; /*! @brief Type of KSDK printf function pointer. */ typedef int (*PUTCHAR_FUNC)(int a); /******************************************************************************* * Variables ******************************************************************************/ #if ((SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK) || defined(SDK_DEBUGCONSOLE_UART)) /*! @brief Debug UART state information. */ static debug_console_state_t s_debugConsole; #endif /******************************************************************************* * Prototypes ******************************************************************************/ #if (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK)) static int DbgConsole_PrintfFormattedData(PUTCHAR_FUNC func_ptr, const char *fmt, va_list ap); #endif /* SDK_DEBUGCONSOLE */ /******************************************************************************* * Code ******************************************************************************/ /*************Code for DbgConsole Init, Deinit, Printf, Scanf *******************************/ #if ((SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK) || defined(SDK_DEBUGCONSOLE_UART)) /* See fsl_debug_console.h for documentation of this function. */ status_t DbgConsole_Init(uint8_t instance, uint32_t baudRate, serial_port_type_t device, uint32_t clkSrcFreq) { hal_uart_config_t usrtConfig; if (kSerialPort_Uart != device) { return kStatus_Fail; } /* Set debug console to initialized to avoid duplicated initialized operation. */ s_debugConsole.serial_port_type = device; usrtConfig.srcClock_Hz = clkSrcFreq; usrtConfig.baudRate_Bps = baudRate; usrtConfig.parityMode = kHAL_UartParityDisabled; usrtConfig.stopBitCount = kHAL_UartOneStopBit; usrtConfig.enableRx = 1U; usrtConfig.enableTx = 1U; usrtConfig.enableRxRTS = 0U; usrtConfig.enableTxCTS = 0U; usrtConfig.instance = instance; #if (defined(HAL_UART_ADAPTER_FIFO) && (HAL_UART_ADAPTER_FIFO > 0u)) usrtConfig.txFifoWatermark = 0U; usrtConfig.rxFifoWatermark = 0U; #endif /* Enable clock and initial UART module follow user configure structure. */ (void)HAL_UartInit((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], &usrtConfig); /* Set the function pointer for send and receive for this kind of device. */ s_debugConsole.putChar = HAL_UartSendBlocking; s_debugConsole.getChar = HAL_UartReceiveBlocking; return kStatus_Success; } /* See fsl_debug_console.h for documentation of this function. */ status_t DbgConsole_Deinit(void) { if (kSerialPort_None == s_debugConsole.serial_port_type) { return kStatus_Success; } (void)HAL_UartDeinit((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0]); s_debugConsole.serial_port_type = kSerialPort_None; return kStatus_Success; } /* See fsl_debug_console.h for documentation of this function. */ status_t DbgConsole_EnterLowpower(void) { hal_uart_status_t DbgConsoleUartStatus = kStatus_HAL_UartError; if (kSerialPort_Uart == s_debugConsole.serial_port_type) { DbgConsoleUartStatus = HAL_UartEnterLowpower((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0]); } return (status_t)DbgConsoleUartStatus; } /* See fsl_debug_console.h for documentation of this function. */ status_t DbgConsole_ExitLowpower(void) { hal_uart_status_t DbgConsoleUartStatus = kStatus_HAL_UartError; if (kSerialPort_Uart == s_debugConsole.serial_port_type) { DbgConsoleUartStatus = HAL_UartExitLowpower((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0]); } return (status_t)DbgConsoleUartStatus; } #endif /* DEBUGCONSOLE_REDIRECT_TO_SDK */ #if (defined(SDK_DEBUGCONSOLE) && (SDK_DEBUGCONSOLE == DEBUGCONSOLE_REDIRECT_TO_SDK)) /* See fsl_debug_console.h for documentation of this function. */ int DbgConsole_Printf(const char *fmt_s, ...) { va_list ap; int result = 0; va_start(ap, fmt_s); result = DbgConsole_Vprintf(fmt_s, ap); va_end(ap); return result; } /* See fsl_debug_console.h for documentation of this function. */ int DbgConsole_Vprintf(const char *fmt_s, va_list formatStringArg) { int result = 0; /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } result = DbgConsole_PrintfFormattedData(DbgConsole_Putchar, fmt_s, formatStringArg); return result; } /* See fsl_debug_console.h for documentation of this function. */ int DbgConsole_Putchar(int dbgConsoleCh) { /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&dbgConsoleCh), 1); return 1; } /* See fsl_debug_console.h for documentation of this function. */ int DbgConsole_Scanf(char *fmt_s, ...) { /* Plus one to store end of string char */ char temp_buf[IO_MAXLINE + 1]; va_list ap; int32_t i; char result; /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } va_start(ap, fmt_s); temp_buf[0] = '\0'; i = 0; while (true) { if (i >= (int32_t)IO_MAXLINE) { break; } result = (char)DbgConsole_Getchar(); temp_buf[i] = result; if ((result == '\r') || (result == '\n')) { /* End of Line. */ if (i == 0) { temp_buf[i] = '\0'; i = -1; } else { break; } } i++; } if (i == (int32_t)IO_MAXLINE) { temp_buf[i] = '\0'; } else { temp_buf[i + 1] = '\0'; } result = (char)StrFormatScanf(temp_buf, fmt_s, ap); va_end(ap); return (int)result; } /* See fsl_debug_console.h for documentation of this function. */ int DbgConsole_Getchar(void) { char dbgConsoleCh; /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } while (kStatus_HAL_UartSuccess != s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&dbgConsoleCh), 1)) { return -1; } return (int)dbgConsoleCh; } /*************Code for process formatted data*******************************/ /*! * @brief This function puts padding character. * * @param[in] c Padding character. * @param[in] curlen Length of current formatted string . * @param[in] width Width of expected formatted string. * @param[in] count Number of characters. * @param[in] func_ptr Function to put character out. */ static void DbgConsole_PrintfPaddingCharacter( char c, int32_t curlen, int32_t width, int32_t *count, PUTCHAR_FUNC func_ptr) { int32_t i; for (i = curlen; i < width; i++) { (void)func_ptr(c); (*count)++; } } /*! * @brief Converts a radix number to a string and return its length. * * @param[in] numstr Converted string of the number. * @param[in] nump Pointer to the number. * @param[in] neg Polarity of the number. * @param[in] radix The radix to be converted to. * @param[in] use_caps Used to identify %x/X output format. * @return Length of the converted string. */ static int32_t DbgConsole_ConvertRadixNumToString(char *numstr, void *nump, int32_t neg, int32_t radix, bool use_caps) { #if PRINTF_ADVANCED_ENABLE long long int a; long long int b; long long int c; unsigned long long int ua; unsigned long long int ub; unsigned long long int uc; unsigned long long int uc_param; #else int a; int b; int c; unsigned int ua; unsigned int ub; unsigned int uc; unsigned int uc_param; #endif /* PRINTF_ADVANCED_ENABLE */ int32_t nlen; char *nstrp; nlen = 0; nstrp = numstr; *nstrp++ = '\0'; #if !(PRINTF_ADVANCED_ENABLE > 0) neg = 0; #endif #if PRINTF_ADVANCED_ENABLE a = 0; b = 0; c = 0; ua = 0ULL; ub = 0ULL; uc = 0ULL; uc_param = 0ULL; #else a = 0; b = 0; c = 0; ua = 0U; ub = 0U; uc = 0U; uc_param = 0U; #endif /* PRINTF_ADVANCED_ENABLE */ (void)a; (void)b; (void)c; (void)ua; (void)ub; (void)uc; (void)uc_param; (void)neg; /* * Fix MISRA issue: CID 15985711 (#15 of 15): MISRA C-2012 Control Flow Expressions (MISRA C-2012 Rule 14.3) * misra_c_2012_rule_14_3_violation: Execution cannot reach this statement: a = *((int *)nump); */ #if PRINTF_ADVANCED_ENABLE if (0 != neg) { #if PRINTF_ADVANCED_ENABLE a = *(long long int *)nump; #else a = *(int *)nump; #endif /* PRINTF_ADVANCED_ENABLE */ if (a == 0) { *nstrp = '0'; ++nlen; return nlen; } while (a != 0) { #if PRINTF_ADVANCED_ENABLE b = (long long int)a / (long long int)radix; c = (long long int)a - ((long long int)b * (long long int)radix); if (c < 0) { uc = (unsigned long long int)c; uc_param = ~uc; c = (long long int)uc_param + 1 + (long long int)'0'; } #else b = (int)a / (int)radix; c = (int)a - ((int)b * (int)radix); if (c < 0) { uc = (unsigned int)c; uc_param = ~uc; c = (int)uc_param + 1 + (int)'0'; } #endif /* PRINTF_ADVANCED_ENABLE */ else { c = c + (int)'0'; } a = b; *nstrp++ = (char)c; ++nlen; } } else #endif /* PRINTF_ADVANCED_ENABLE */ { #if PRINTF_ADVANCED_ENABLE ua = *(unsigned long long int *)nump; #else ua = *(unsigned int *)nump; #endif /* PRINTF_ADVANCED_ENABLE */ if (ua == 0U) { *nstrp = '0'; ++nlen; return nlen; } while (ua != 0U) { #if PRINTF_ADVANCED_ENABLE ub = (unsigned long long int)ua / (unsigned long long int)radix; uc = (unsigned long long int)ua - ((unsigned long long int)ub * (unsigned long long int)radix); #else ub = ua / (unsigned int)radix; uc = ua - (ub * (unsigned int)radix); #endif /* PRINTF_ADVANCED_ENABLE */ if (uc < 10U) { uc = uc + (unsigned int)'0'; } else { uc = uc - 10U + (unsigned int)(use_caps ? 'A' : 'a'); } ua = ub; *nstrp++ = (char)uc; ++nlen; } } return nlen; } #if PRINTF_FLOAT_ENABLE /*! * @brief Converts a floating radix number to a string and return its length. * * @param[in] numstr Converted string of the number. * @param[in] nump Pointer to the number. * @param[in] radix The radix to be converted to. * @param[in] precision_width Specify the precision width. * @return Length of the converted string. */ static int32_t DbgConsole_ConvertFloatRadixNumToString(char *numstr, void *nump, int32_t radix, uint32_t precision_width) { int32_t a; int32_t b; int32_t c; uint32_t i; double fa; double dc; double fb; double r; double fractpart; double intpart; int32_t nlen; char *nstrp; nlen = 0; nstrp = numstr; *nstrp++ = '\0'; r = *(double *)nump; if (0.0 == r) { *nstrp = '0'; ++nlen; return nlen; } fractpart = modf((double)r, (double *)&intpart); /* Process fractional part. */ for (i = 0; i < precision_width; i++) { fractpart *= (double)radix; } if (r >= 0.0) { fa = fractpart + (double)0.5; if (fa >= pow((double)10, (double)precision_width)) { intpart++; } } else { fa = fractpart - (double)0.5; if (fa <= -pow((double)10, (double)precision_width)) { intpart--; } } for (i = 0; i < precision_width; i++) { fb = fa / (double)radix; dc = (fa - (double)(long long int)fb * (double)radix); c = (int32_t)dc; if (c < 0) { c = (int32_t)'0' - c; } else { c = c + '0'; } fa = fb; *nstrp++ = (char)c; ++nlen; } *nstrp++ = (char)'.'; ++nlen; a = (int32_t)intpart; if (a == 0) { *nstrp++ = '0'; ++nlen; } else { while (a != 0) { b = (int32_t)a / (int32_t)radix; c = (int32_t)a - ((int32_t)b * (int32_t)radix); if (c < 0) { c = (int32_t)'0' - c; } else { c = c + '0'; } a = b; *nstrp++ = (char)c; ++nlen; } } return nlen; } #endif /* PRINTF_FLOAT_ENABLE */ /*! * @brief This function outputs its parameters according to a formatted string. * * @note I/O is performed by calling given function pointer using following * (*func_ptr)(c); * * @param[in] func_ptr Function to put character out. * @param[in] fmt Format string for printf. * @param[in] ap Arguments to printf. * * @return Number of characters */ static int DbgConsole_PrintfFormattedData(PUTCHAR_FUNC func_ptr, const char *fmt, va_list ap) { /* va_list ap; */ const char *p; char c; char vstr[33]; char *vstrp = NULL; int32_t vlen = 0; bool done; int32_t count = 0; uint32_t field_width; uint32_t precision_width; char *sval; int32_t cval; bool use_caps; uint8_t radix = 0; #if PRINTF_ADVANCED_ENABLE uint32_t flags_used; char schar; bool dschar; long long int ival; unsigned long long int uval = 0; bool valid_precision_width; #else int ival; unsigned int uval = 0; #endif /* PRINTF_ADVANCED_ENABLE */ #if PRINTF_FLOAT_ENABLE double fval; #endif /* PRINTF_FLOAT_ENABLE */ /* Start parsing apart the format string and display appropriate formats and data. */ p = fmt; while (true) { if ('\0' == *p) { break; } c = *p; /* * All formats begin with a '%' marker. Special chars like * '\n' or '\t' are normally converted to the appropriate * character by the __compiler__. Thus, no need for this * routine to account for the '\' character. */ if (c != '%') { (void)func_ptr(c); count++; p++; /* By using 'continue', the next iteration of the loop is used, skipping the code that follows. */ continue; } use_caps = true; #if PRINTF_ADVANCED_ENABLE /* First check for specification modifier flags. */ flags_used = 0; done = false; while (!done) { switch (*++p) { case '-': flags_used |= (uint32_t)kPRINTF_Minus; break; case '+': flags_used |= (uint32_t)kPRINTF_Plus; break; case ' ': flags_used |= (uint32_t)kPRINTF_Space; break; case '0': flags_used |= (uint32_t)kPRINTF_Zero; break; case '#': flags_used |= (uint32_t)kPRINTF_Pound; break; default: /* We've gone one char too far. */ --p; done = true; break; } } #endif /* PRINTF_ADVANCED_ENABLE */ /* Next check for minimum field width. */ field_width = 0; done = false; while (!done) { c = *++p; if ((c >= '0') && (c <= '9')) { field_width = (field_width * 10U) + ((uint32_t)c - (uint32_t)'0'); } #if PRINTF_ADVANCED_ENABLE else if (c == '*') { field_width = (uint32_t)va_arg(ap, unsigned int); } #endif /* PRINTF_ADVANCED_ENABLE */ else { /* We've gone one char too far. */ --p; done = true; } } /* Next check for the width and precision field separator. */ #if (PRINTF_ADVANCED_ENABLE || PRINTF_FLOAT_ENABLE) precision_width = 6U; /* MISRA C-2012 Rule 2.2 */ #endif #if PRINTF_ADVANCED_ENABLE valid_precision_width = false; #endif /* PRINTF_ADVANCED_ENABLE */ if (*++p == '.') { /* Must get precision field width, if present. */ precision_width = 0U; done = false; while (!done) { c = *++p; if ((c >= '0') && (c <= '9')) { precision_width = (precision_width * 10U) + ((uint32_t)c - (uint32_t)'0'); #if PRINTF_ADVANCED_ENABLE valid_precision_width = true; #endif /* PRINTF_ADVANCED_ENABLE */ } #if PRINTF_ADVANCED_ENABLE else if (c == '*') { precision_width = (uint32_t)va_arg(ap, unsigned int); valid_precision_width = true; } #endif /* PRINTF_ADVANCED_ENABLE */ else { /* We've gone one char too far. */ --p; done = true; } } } else { /* We've gone one char too far. */ --p; } #if PRINTF_ADVANCED_ENABLE /* * Check for the length modifier. */ switch (/* c = */ *++p) { case 'h': if (*++p != 'h') { flags_used |= (uint32_t)kPRINTF_LengthShortInt; --p; } else { flags_used |= (uint32_t)kPRINTF_LengthChar; } break; case 'l': if (*++p != 'l') { flags_used |= (uint32_t)kPRINTF_LengthLongInt; --p; } else { flags_used |= (uint32_t)kPRINTF_LengthLongLongInt; } break; case 'z': if (sizeof(size_t) == sizeof(uint32_t)) { flags_used |= (uint32_t)kPRINTF_LengthLongInt; } else if (sizeof(size_t) == (2U * sizeof(uint32_t))) { flags_used |= (uint32_t)kPRINTF_LengthLongLongInt; } else if (sizeof(size_t) == sizeof(uint16_t)) { flags_used |= (uint32_t)kPRINTF_LengthShortInt; } else { /* MISRA C-2012 Rule 15.7 */ } break; default: /* we've gone one char too far */ --p; break; } #endif /* PRINTF_ADVANCED_ENABLE */ /* Now we're ready to examine the format. */ c = *++p; { if ((c == 'd') || (c == 'i') || (c == 'f') || (c == 'F') || (c == 'x') || (c == 'X') || (c == 'o') || (c == 'b') || (c == 'p') || (c == 'u')) { if ((c == 'd') || (c == 'i')) { #if PRINTF_ADVANCED_ENABLE if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt)) { ival = (long long int)va_arg(ap, long long int); } else if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongInt)) { ival = (long int)va_arg(ap, long int); } else #endif /* PRINTF_ADVANCED_ENABLE */ { ival = (int)va_arg(ap, int); } vlen = DbgConsole_ConvertRadixNumToString(vstr, &ival, 1, 10, use_caps); vstrp = &vstr[vlen]; #if PRINTF_ADVANCED_ENABLE if (ival < 0) { schar = '-'; ++vlen; } else { if (0U != (flags_used & (uint32_t)kPRINTF_Plus)) { schar = '+'; ++vlen; } else { if (0U != (flags_used & (uint32_t)kPRINTF_Space)) { schar = ' '; ++vlen; } else { schar = '\0'; } } } dschar = false; /* Do the ZERO pad. */ if (0U != (flags_used & (uint32_t)kPRINTF_Zero)) { if ('\0' != schar) { (void)func_ptr(schar); count++; } dschar = true; DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr); vlen = (int32_t)field_width; } else { if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) { DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); if ('\0' != schar) { (void)func_ptr(schar); count++; } dschar = true; } } /* The string was built in reverse order, now display in correct order. */ if ((!dschar) && ('\0' != schar)) { (void)func_ptr(schar); count++; } #endif /* PRINTF_ADVANCED_ENABLE */ } #if PRINTF_FLOAT_ENABLE if ((c == 'f') || (c == 'F')) { fval = (double)va_arg(ap, double); vlen = DbgConsole_ConvertFloatRadixNumToString(vstr, &fval, 10, precision_width); vstrp = &vstr[vlen]; #if PRINTF_ADVANCED_ENABLE if (fval < 0.0) { schar = '-'; ++vlen; } else { if (0U != (flags_used & (uint32_t)kPRINTF_Plus)) { schar = '+'; ++vlen; } else { if (0U != (flags_used & (uint32_t)kPRINTF_Space)) { schar = ' '; ++vlen; } else { schar = '\0'; } } } dschar = false; if (0U != (flags_used & (uint32_t)kPRINTF_Zero)) { if ('\0' != schar) { (void)func_ptr(schar); count++; } dschar = true; DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr); vlen = (int32_t)field_width; } else { if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) { DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); if ('\0' != schar) { (void)func_ptr(schar); count++; } dschar = true; } } if ((!dschar) && ('\0' != schar)) { (void)func_ptr(schar); count++; } #endif /* PRINTF_ADVANCED_ENABLE */ } #endif /* PRINTF_FLOAT_ENABLE */ if ((c == 'X') || (c == 'x')) { if (c == 'x') { use_caps = false; } #if PRINTF_ADVANCED_ENABLE if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt)) { uval = (unsigned long long int)va_arg(ap, unsigned long long int); } else if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongInt)) { uval = (unsigned long int)va_arg(ap, unsigned long int); } else #endif /* PRINTF_ADVANCED_ENABLE */ { uval = (unsigned int)va_arg(ap, unsigned int); } vlen = DbgConsole_ConvertRadixNumToString(vstr, &uval, 0, 16, use_caps); vstrp = &vstr[vlen]; #if PRINTF_ADVANCED_ENABLE dschar = false; if (0U != (flags_used & (uint32_t)kPRINTF_Zero)) { if (0U != (flags_used & (uint32_t)kPRINTF_Pound)) { (void)func_ptr('0'); (void)func_ptr((use_caps ? 'X' : 'x')); count += 2; /*vlen += 2;*/ dschar = true; } DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr); vlen = (int32_t)field_width; } else { if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) { if (0U != (flags_used & (uint32_t)kPRINTF_Pound)) { vlen += 2; } DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); if (0U != (flags_used & (uint32_t)kPRINTF_Pound)) { (void)func_ptr('0'); (void)func_ptr(use_caps ? 'X' : 'x'); count += 2; dschar = true; } } } if ((0U != (flags_used & (uint32_t)kPRINTF_Pound)) && (!dschar)) { (void)func_ptr('0'); (void)func_ptr(use_caps ? 'X' : 'x'); count += 2; vlen += 2; } #endif /* PRINTF_ADVANCED_ENABLE */ } if ((c == 'o') || (c == 'b') || (c == 'p') || (c == 'u')) { if ('p' == c) { /* * Fix MISRA issue: CID 16209727 (#15 of 15): MISRA C-2012 Pointer Type Conversions (MISRA * C-2012 Rule 11.6) * 1. misra_c_2012_rule_11_6_violation: The expression va_arg (ap, void *) of type void * is * cast to type unsigned int. * * Orignal code: uval = (unsigned int)va_arg(ap, void *); */ void *pval; pval = (void *)va_arg(ap, void *); (void)memcpy((void *)&uval, (void *)&pval, sizeof(void *)); } else { #if PRINTF_ADVANCED_ENABLE if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongLongInt)) { uval = (unsigned long long int)va_arg(ap, unsigned long long int); } else if (0U != (flags_used & (uint32_t)kPRINTF_LengthLongInt)) { uval = (unsigned long int)va_arg(ap, unsigned long int); } else #endif /* PRINTF_ADVANCED_ENABLE */ { uval = (unsigned int)va_arg(ap, unsigned int); } } switch (c) { case 'o': radix = 8; break; case 'b': radix = 2; break; case 'p': radix = 16; break; case 'u': radix = 10; break; default: /* MISRA C-2012 Rule 16.4 */ break; } vlen = DbgConsole_ConvertRadixNumToString(vstr, &uval, 0, (int32_t)radix, use_caps); vstrp = &vstr[vlen]; #if PRINTF_ADVANCED_ENABLE if (0U != (flags_used & (uint32_t)kPRINTF_Zero)) { DbgConsole_PrintfPaddingCharacter('0', vlen, (int32_t)field_width, &count, func_ptr); vlen = (int32_t)field_width; } else { if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) { DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); } } #endif /* PRINTF_ADVANCED_ENABLE */ } #if !PRINTF_ADVANCED_ENABLE DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); #endif /* !PRINTF_ADVANCED_ENABLE */ if (vstrp != NULL) { while ('\0' != *vstrp) { (void)func_ptr(*vstrp--); count++; } } #if PRINTF_ADVANCED_ENABLE if (0U != (flags_used & (uint32_t)kPRINTF_Minus)) { DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); } #endif /* PRINTF_ADVANCED_ENABLE */ } else if (c == 'c') { cval = (int32_t)va_arg(ap, unsigned int); (void)func_ptr(cval); count++; } else if (c == 's') { sval = (char *)va_arg(ap, char *); if (NULL != sval) { #if PRINTF_ADVANCED_ENABLE if (valid_precision_width) { vlen = (int32_t)precision_width; } else { vlen = (int32_t)strlen(sval); } #else vlen = (int32_t)strlen(sval); #endif /* PRINTF_ADVANCED_ENABLE */ #if PRINTF_ADVANCED_ENABLE if (0U == (flags_used & (uint32_t)kPRINTF_Minus)) #endif /* PRINTF_ADVANCED_ENABLE */ { DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); } #if PRINTF_ADVANCED_ENABLE if (valid_precision_width) { while (('\0' != *sval) && (vlen > 0)) { (void)func_ptr(*sval++); count++; vlen--; } /* In case that vlen sval is shorter than vlen */ vlen = (int32_t)precision_width - vlen; } else { #endif /* PRINTF_ADVANCED_ENABLE */ while ('\0' != *sval) { (void)func_ptr(*sval++); count++; } #if PRINTF_ADVANCED_ENABLE } #endif /* PRINTF_ADVANCED_ENABLE */ #if PRINTF_ADVANCED_ENABLE if (0U != (flags_used & (uint32_t)kPRINTF_Minus)) { DbgConsole_PrintfPaddingCharacter(' ', vlen, (int32_t)field_width, &count, func_ptr); } #endif /* PRINTF_ADVANCED_ENABLE */ } } else { (void)func_ptr(c); count++; } } p++; } return count; } #endif /* SDK_DEBUGCONSOLE */ /*************Code to support toolchain's printf, scanf *******************************/ /* These function __write and __read is used to support IAR toolchain to printf and scanf*/ #if (defined(__ICCARM__)) #if defined(SDK_DEBUGCONSOLE_UART) #pragma weak __write size_t __write(int handle, const unsigned char *buffer, size_t size); size_t __write(int handle, const unsigned char *buffer, size_t size) { size_t ret; if (NULL == buffer) { /* * This means that we should flush internal buffers. Since we don't we just return. * (Remember, "handle" == -1 means that all handles should be flushed.) */ ret = (size_t)0; } else if ((handle != 1) && (handle != 2)) { /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */ ret = (size_t)-1; } else if (kSerialPort_None == s_debugConsole.serial_port_type) { /* Do nothing if the debug UART is not initialized. */ ret = (size_t)-1; } else { /* Send data. */ (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], buffer, size); ret = size; } return ret; } #pragma weak __read size_t __read(int handle, unsigned char *buffer, size_t size); size_t __read(int handle, unsigned char *buffer, size_t size) { size_t ret; /* This function only reads from "standard in", for all other file handles it returns failure. */ if (handle != 0) { ret = ((size_t)-1); } else if (kSerialPort_None == s_debugConsole.serial_port_type) { /* Do nothing if the debug UART is not initialized. */ ret = ((size_t)-1); } else { /* Receive data. */ (void)s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], buffer, size); ret = size; } return ret; } #endif /* SDK_DEBUGCONSOLE_UART */ /* support LPC Xpresso with RedLib */ #elif (defined(__REDLIB__)) #if (defined(SDK_DEBUGCONSOLE_UART)) int __attribute__((weak)) __sys_write(int handle, char *buffer, int size) { if (NULL == buffer) { /* return -1 if error. */ return -1; } /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */ if ((handle != 1) && (handle != 2)) { return -1; } /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Send data. */ (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size); return 0; } int __attribute__((weak)) __sys_readc(void) { char tmp; /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Receive data. */ s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)&tmp, sizeof(tmp)); return tmp; } #endif /* SDK_DEBUGCONSOLE_UART */ /* These function fputc and fgetc is used to support KEIL toolchain to printf and scanf*/ #elif defined(__CC_ARM) || defined(__ARMCC_VERSION) #if defined(SDK_DEBUGCONSOLE_UART) #if defined(__CC_ARM) struct __FILE { int handle; /* * Whatever you require here. If the only file you are using is standard output using printf() for debugging, * no file handling is required. */ }; #endif /* FILE is typedef in stdio.h. */ #pragma weak __stdout #pragma weak __stdin FILE __stdout; FILE __stdin; #pragma weak fputc int fputc(int ch, FILE *f) { /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Send data. */ (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&ch), 1); return 1; } #pragma weak fgetc int fgetc(FILE *f) { char ch; /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Receive data. */ s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&ch), 1); return ch; } /* * Terminate the program, passing a return code back to the user. * This function may not return. */ void _sys_exit(int returncode) { while (1) { } } /* * Writes a character to the output channel. This function is used * for last-resort error message output. */ void _ttywrch(int ch) { char ench = ch; /* Send data. */ s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)(&ench), 1); } char *_sys_command_string(char *cmd, int len) { return (cmd); } #endif /* SDK_DEBUGCONSOLE_UART */ /* These function __write_r and __read_r are used to support Xtensa Clang toolchain to printf and scanf */ #elif defined(__XTENSA__) && defined(__XT_CLANG__) #if defined(SDK_DEBUGCONSOLE_UART) int __attribute__((weak)) _write_r(void *ptr, int handle, char *buffer, int size); int __attribute__((weak)) _write_r(void *ptr, int handle, char *buffer, int size) { if (NULL == buffer) { /* return -1 if error. */ return -1; } /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */ if ((handle != 1) && (handle != 2)) { return -1; } /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Send data. */ (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size); return size; } int __attribute__((weak)) _read_r(void *ptr, int handle, char *buffer, int size); int __attribute__((weak)) _read_r(void *ptr, int handle, char *buffer, int size) { /* This function only reads from "standard in", for all other file handles it returns failure. */ if (handle != 0) { return -1; } /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Receive data. */ (void)s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size); return size; } #endif /* SDK_DEBUGCONSOLE_UART */ /* These function __write and __read is used to support ARM_GCC, KDS, Atollic toolchains to printf and scanf*/ #elif (defined(__GNUC__)) #if ((defined(__GNUC__) && (!defined(__MCUXPRESSO)) && (defined(SDK_DEBUGCONSOLE_UART))) || \ (defined(__MCUXPRESSO) && (defined(SDK_DEBUGCONSOLE_UART)))) int __attribute__((weak)) _write(int handle, char *buffer, int size); int __attribute__((weak)) _write(int handle, char *buffer, int size) { if (NULL == buffer) { /* return -1 if error. */ return -1; } /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */ if ((handle != 1) && (handle != 2)) { return -1; } /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Send data. */ (void)s_debugConsole.putChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size); return size; } int __attribute__((weak)) _read(int handle, char *buffer, int size); int __attribute__((weak)) _read(int handle, char *buffer, int size) { /* This function only reads from "standard in", for all other file handles it returns failure. */ if (handle != 0) { return -1; } /* Do nothing if the debug UART is not initialized. */ if (kSerialPort_None == s_debugConsole.serial_port_type) { return -1; } /* Receive data. */ (void)s_debugConsole.getChar((hal_uart_handle_t)&s_debugConsole.uartHandleBuffer[0], (uint8_t *)buffer, size); return size; } #endif #endif /* __ICCARM__ */