summaryrefslogtreecommitdiff
path: root/utilities
diff options
context:
space:
mode:
Diffstat (limited to 'utilities')
-rw-r--r--utilities/fsl_debug_console.c1806
-rw-r--r--utilities/fsl_debug_console.h193
-rw-r--r--utilities/fsl_notifier.c182
-rw-r--r--utilities/fsl_notifier.h259
-rw-r--r--utilities/fsl_sbrk.c66
-rw-r--r--utilities/fsl_shell.c621
-rw-r--r--utilities/fsl_shell.h204
7 files changed, 3331 insertions, 0 deletions
diff --git a/utilities/fsl_debug_console.c b/utilities/fsl_debug_console.c
new file mode 100644
index 0000000..10c64a4
--- /dev/null
+++ b/utilities/fsl_debug_console.c
@@ -0,0 +1,1806 @@
+/*
+ * This is a modified version of the file printf.c, which was distributed
+ * by Motorola as part of the M5407C3BOOT.zip package used to initialize
+ * the M5407C3 evaluation board.
+ *
+ * Copyright:
+ * 1999-2000 MOTOROLA, INC. All Rights Reserved.
+ * You are hereby granted a copyright license to use, modify, and
+ * distribute the SOFTWARE so long as this entire notice is
+ * retained without alteration in any modified and/or redistributed
+ * versions, and that such modified versions are clearly identified
+ * as such. No licenses are granted by implication, estoppel or
+ * otherwise under any patents or trademarks of Motorola, Inc. This
+ * software is provided on an "AS IS" basis and without warranty.
+ *
+ * To the maximum extent permitted by applicable law, MOTOROLA
+ * DISCLAIMS ALL WARRANTIES WHETHER EXPRESS OR IMPLIED, INCLUDING
+ * IMPLIED WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR
+ * PURPOSE AND ANY WARRANTY AGAINST INFRINGEMENT WITH REGARD TO THE
+ * SOFTWARE (INCLUDING ANY MODIFIED VERSIONS THEREOF) AND ANY
+ * ACCOMPANYING WRITTEN MATERIALS.
+ *
+ * To the maximum extent permitted by applicable law, IN NO EVENT
+ * SHALL MOTOROLA BE LIABLE FOR ANY DAMAGES WHATSOEVER (INCLUDING
+ * WITHOUT LIMITATION, DAMAGES FOR LOSS OF BUSINESS PROFITS, BUSINESS
+ * INTERRUPTION, LOSS OF BUSINESS INFORMATION, OR OTHER PECUNIARY
+ * LOSS) ARISING OF THE USE OR INABILITY TO USE THE SOFTWARE.
+ *
+ * Motorola assumes no responsibility for the maintenance and support
+ * of this software
+
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdarg.h>
+#include <stdlib.h>
+#if defined(__CC_ARM)
+#include <stdio.h>
+#endif
+#include <math.h>
+#include "fsl_debug_console.h"
+
+#if defined(FSL_FEATURE_SOC_UART_COUNT) && (FSL_FEATURE_SOC_UART_COUNT > 0)
+#include "fsl_uart.h"
+#endif /* FSL_FEATURE_SOC_UART_COUNT */
+
+#if defined(FSL_FEATURE_SOC_LPSCI_COUNT) && (FSL_FEATURE_SOC_LPSCI_COUNT > 0)
+#include "fsl_lpsci.h"
+#endif /* FSL_FEATURE_SOC_LPSCI_COUNT */
+
+#if defined(FSL_FEATURE_SOC_LPUART_COUNT) && (FSL_FEATURE_SOC_LPUART_COUNT > 0)
+#include "fsl_lpuart.h"
+#endif /* FSL_FEATURE_SOC_LPUART_COUNT */
+
+#if defined(FSL_FEATURE_SOC_USB_COUNT) && (FSL_FEATURE_SOC_USB_COUNT > 0) && defined(BOARD_USE_VIRTUALCOM)
+#include "usb_device_config.h"
+#include "usb.h"
+#include "usb_device_cdc_acm.h"
+#include "usb_device_ch9.h"
+#include "virtual_com.h"
+#endif
+
+/*! @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 */
+
+#if SCANF_FLOAT_ENABLE
+static double fnum = 0.0;
+#endif /* SCANF_FLOAT_ENABLE */
+
+/*! @brief Operation functions definitions for debug console. */
+typedef struct DebugConsoleOperationFunctions
+{
+ union
+ {
+ void (*PutChar)(void *base, const uint8_t *buffer, size_t length);
+#if defined(FSL_FEATURE_SOC_UART_COUNT) && (FSL_FEATURE_SOC_UART_COUNT > 0)
+ void (*UART_PutChar)(UART_Type *base, const uint8_t *buffer, size_t length);
+#endif /* FSL_FEATURE_SOC_UART_COUNT */
+#if defined(FSL_FEATURE_SOC_LPSCI_COUNT) && (FSL_FEATURE_SOC_LPSCI_COUNT > 0)
+ void (*LPSCI_PutChar)(UART0_Type *base, const uint8_t *buffer, size_t length);
+#endif /* FSL_FEATURE_SOC_LPSCI_COUNT */
+#if defined(FSL_FEATURE_SOC_LPUART_COUNT) && (FSL_FEATURE_SOC_LPUART_COUNT > 0)
+ void (*LPUART_PutChar)(LPUART_Type *base, const uint8_t *buffer, size_t length);
+#endif /* FSL_FEATURE_SOC_LPUART_COUNT */
+#if defined(FSL_FEATURE_SOC_USB_COUNT) && (FSL_FEATURE_SOC_USB_COUNT > 0) && defined(BOARD_USE_VIRTUALCOM)
+ void (*USB_PutChar)(usb_device_handle base, const uint8_t *buf, size_t count);
+#endif /* FSL_FEATURE_SOC_USB_COUNT && BOARD_USE_VIRTUALCOM*/
+ } tx_union;
+ union
+ {
+ void (*GetChar)(void *base, const uint8_t *buffer, size_t length);
+#if defined(FSL_FEATURE_SOC_UART_COUNT) && (FSL_FEATURE_SOC_UART_COUNT > 0)
+ status_t (*UART_GetChar)(UART_Type *base, uint8_t *buffer, size_t length);
+#endif /* FSL_FEATURE_SOC_UART_COUNT */
+#if defined(FSL_FEATURE_SOC_LPSCI_COUNT) && (FSL_FEATURE_SOC_LPSCI_COUNT > 0)
+ status_t (*LPSCI_GetChar)(UART0_Type *base, uint8_t *buffer, size_t length);
+#endif /* FSL_FEATURE_SOC_LPSCI_COUNT */
+#if defined(FSL_FEATURE_SOC_LPUART_COUNT) && (FSL_FEATURE_SOC_LPUART_COUNT > 0)
+ status_t (*LPUART_GetChar)(LPUART_Type *base, uint8_t *buffer, size_t length);
+#endif /* FSL_FEATURE_SOC_LPUART_COUNT */
+#if defined(FSL_FEATURE_SOC_USB_COUNT) && (FSL_FEATURE_SOC_USB_COUNT > 0) && defined(BOARD_USE_VIRTUALCOM)
+ status_t (*USB_GetChar)(usb_device_handle base, uint8_t *buf, size_t count);
+#endif /* FSL_FEATURE_SOC_USB_COUNT && BOARD_USE_VIRTUALCOM*/
+ } rx_union;
+} debug_console_ops_t;
+
+/*! @brief State structure storing debug console. */
+typedef struct DebugConsoleState
+{
+ uint8_t type; /*!< Indicator telling whether the debug console is initialized. */
+ void *base; /*!< Base of the IP register. */
+ debug_console_ops_t ops; /*!< Operation function pointers for debug UART operations. */
+} debug_console_state_t;
+
+/*! @brief Type of KSDK printf function pointer. */
+typedef int (*PUTCHAR_FUNC)(int a);
+
+#if PRINTF_ADVANCED_ENABLE
+/*! @brief Specification modifier flags for printf. */
+enum _debugconsole_printf_flag
+{
+ kPRINTF_Minus = 0x01U, /*!< Minus FLag. */
+ kPRINTF_Plus = 0x02U, /*!< Plus Flag. */
+ kPRINTF_Space = 0x04U, /*!< Space Flag. */
+ kPRINTF_Zero = 0x08U, /*!< Zero Flag. */
+ kPRINTF_Pound = 0x10U, /*!< Pound Flag. */
+ kPRINTF_LengthChar = 0x20U, /*!< Length: Char Flag. */
+ kPRINTF_LengthShortInt = 0x40U, /*!< Length: Short Int Flag. */
+ kPRINTF_LengthLongInt = 0x80U, /*!< Length: Long Int Flag. */
+ kPRINTF_LengthLongLongInt = 0x100U, /*!< Length: Long Long Int Flag. */
+};
+#endif /* PRINTF_ADVANCED_ENABLE */
+
+/*! @brief Specification modifier flags for scanf. */
+enum _debugconsole_scanf_flag
+{
+ kSCANF_Suppress = 0x2U, /*!< Suppress Flag. */
+ kSCANF_DestMask = 0x7cU, /*!< Destination Mask. */
+ kSCANF_DestChar = 0x4U, /*!< Destination Char Flag. */
+ kSCANF_DestString = 0x8U, /*!< Destination String FLag. */
+ kSCANF_DestSet = 0x10U, /*!< Destination Set Flag. */
+ kSCANF_DestInt = 0x20U, /*!< Destination Int Flag. */
+ kSCANF_DestFloat = 0x30U, /*!< Destination Float Flag. */
+ kSCANF_LengthMask = 0x1f00U, /*!< Length Mask Flag. */
+#if SCANF_ADVANCED_ENABLE
+ kSCANF_LengthChar = 0x100U, /*!< Length Char Flag. */
+ kSCANF_LengthShortInt = 0x200U, /*!< Length ShortInt Flag. */
+ kSCANF_LengthLongInt = 0x400U, /*!< Length LongInt Flag. */
+ kSCANF_LengthLongLongInt = 0x800U, /*!< Length LongLongInt Flag. */
+#endif /* SCANF_ADVANCED_ENABLE */
+#if PRINTF_FLOAT_ENABLE
+ kSCANF_LengthLongLongDouble = 0x1000U, /*!< Length LongLongDuoble Flag. */
+#endif /*PRINTF_FLOAT_ENABLE */
+ kSCANF_TypeSinged = 0x2000U, /*!< TypeSinged Flag. */
+};
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+/*! @brief Debug UART state information. */
+static debug_console_state_t s_debugConsole = {.type = DEBUG_CONSOLE_DEVICE_TYPE_NONE, .base = NULL, .ops = {{0}, {0}}};
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+#if SDK_DEBUGCONSOLE
+static int DbgConsole_PrintfFormattedData(PUTCHAR_FUNC func_ptr, const char *fmt, va_list ap);
+static int DbgConsole_ScanfFormattedData(const char *line_ptr, char *format, va_list args_ptr);
+double modf(double input_dbl, double *intpart_ptr);
+#endif /* SDK_DEBUGCONSOLE */
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+/*************Code for DbgConsole Init, Deinit, Printf, Scanf *******************************/
+
+/* See fsl_debug_console.h for documentation of this function. */
+status_t DbgConsole_Init(uint32_t baseAddr, uint32_t baudRate, uint8_t device, uint32_t clkSrcFreq)
+{
+ if (s_debugConsole.type != DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return kStatus_Fail;
+ }
+
+ /* Set debug console to initialized to avoid duplicated initialized operation. */
+ s_debugConsole.type = device;
+
+ /* Switch between different device. */
+ switch (device)
+ {
+#if defined(FSL_FEATURE_SOC_UART_COUNT) && (FSL_FEATURE_SOC_UART_COUNT > 0)
+ case DEBUG_CONSOLE_DEVICE_TYPE_UART:
+ {
+ uart_config_t uart_config;
+ s_debugConsole.base = (UART_Type *)baseAddr;
+ UART_GetDefaultConfig(&uart_config);
+ uart_config.baudRate_Bps = baudRate;
+ /* Enable clock and initial UART module follow user configure structure. */
+ UART_Init(s_debugConsole.base, &uart_config, clkSrcFreq);
+ UART_EnableTx(s_debugConsole.base, true);
+ UART_EnableRx(s_debugConsole.base, true);
+ /* Set the function pointer for send and receive for this kind of device. */
+ s_debugConsole.ops.tx_union.UART_PutChar = UART_WriteBlocking;
+ s_debugConsole.ops.rx_union.UART_GetChar = UART_ReadBlocking;
+ }
+ break;
+#endif /* FSL_FEATURE_SOC_UART_COUNT */
+#if defined(FSL_FEATURE_SOC_LPSCI_COUNT) && (FSL_FEATURE_SOC_LPSCI_COUNT > 0)
+ case DEBUG_CONSOLE_DEVICE_TYPE_LPSCI:
+ {
+ lpsci_config_t lpsci_config;
+ s_debugConsole.base = (UART0_Type *)baseAddr;
+ LPSCI_GetDefaultConfig(&lpsci_config);
+ lpsci_config.baudRate_Bps = baudRate;
+ /* Enable clock and initial UART module follow user configure structure. */
+ LPSCI_Init(s_debugConsole.base, &lpsci_config, clkSrcFreq);
+ LPSCI_EnableTx(s_debugConsole.base, true);
+ LPSCI_EnableRx(s_debugConsole.base, true);
+ /* Set the function pointer for send and receive for this kind of device. */
+ s_debugConsole.ops.tx_union.LPSCI_PutChar = LPSCI_WriteBlocking;
+ s_debugConsole.ops.rx_union.LPSCI_GetChar = LPSCI_ReadBlocking;
+ }
+ break;
+#endif /* FSL_FEATURE_SOC_LPSCI_COUNT */
+#if defined(FSL_FEATURE_SOC_LPUART_COUNT) && (FSL_FEATURE_SOC_LPUART_COUNT > 0)
+ case DEBUG_CONSOLE_DEVICE_TYPE_LPUART:
+ {
+ lpuart_config_t lpuart_config;
+ s_debugConsole.base = (LPUART_Type *)baseAddr;
+ LPUART_GetDefaultConfig(&lpuart_config);
+ lpuart_config.baudRate_Bps = baudRate;
+ /* Enable clock and initial UART module follow user configure structure. */
+ LPUART_Init(s_debugConsole.base, &lpuart_config, clkSrcFreq);
+ LPUART_EnableTx(s_debugConsole.base, true);
+ LPUART_EnableRx(s_debugConsole.base, true);
+ /* Set the function pointer for send and receive for this kind of device. */
+ s_debugConsole.ops.tx_union.LPUART_PutChar = LPUART_WriteBlocking;
+ s_debugConsole.ops.rx_union.LPUART_GetChar = LPUART_ReadBlocking;
+ }
+ break;
+#endif /* FSL_FEATURE_SOC_LPUART_COUNT */
+#if defined(FSL_FEATURE_SOC_USB_COUNT) && (FSL_FEATURE_SOC_USB_COUNT > 0) && defined(BOARD_USE_VIRTUALCOM)
+ case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
+ {
+ s_debugConsole.base = USB_VcomInit();
+ s_debugConsole.ops.tx_union.USB_PutChar = USB_VcomWriteBlocking;
+ s_debugConsole.ops.rx_union.USB_GetChar = USB_VcomReadBlocking;
+ }
+ break;
+#endif /* FSL_FEATURE_SOC_USB_COUNT && BOARD_USE_VIRTUALCOM*/
+ /* If new device is required as the low level device for debug console,
+ * Add the case branch and add the preprocessor macro to judge whether
+ * this kind of device exist in this SOC. */
+ default:
+ /* Device identified is invalid, return invalid device error code. */
+ return kStatus_InvalidArgument;
+ }
+
+ return kStatus_Success;
+}
+
+/* See fsl_debug_console.h for documentation of this function. */
+status_t DbgConsole_Deinit(void)
+{
+ if (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return kStatus_Success;
+ }
+
+ switch (s_debugConsole.type)
+ {
+#if defined(FSL_FEATURE_SOC_UART_COUNT) && (FSL_FEATURE_SOC_UART_COUNT > 0)
+ case DEBUG_CONSOLE_DEVICE_TYPE_UART:
+ /* Disable UART module. */
+ UART_Deinit(s_debugConsole.base);
+ break;
+#endif /* FSL_FEATURE_SOC_UART_COUNT */
+#if defined(FSL_FEATURE_SOC_LPSCI_COUNT) && (FSL_FEATURE_SOC_LPSCI_COUNT > 0)
+ case DEBUG_CONSOLE_DEVICE_TYPE_LPSCI:
+ /* Disable LPSCI module. */
+ LPSCI_Deinit(s_debugConsole.base);
+ break;
+#endif /* FSL_FEATURE_SOC_LPSCI_COUNT */
+#if defined(FSL_FEATURE_SOC_LPUART_COUNT) && (FSL_FEATURE_SOC_LPUART_COUNT > 0)
+ case DEBUG_CONSOLE_DEVICE_TYPE_LPUART:
+ /* Disable LPUART module. */
+ LPUART_Deinit(s_debugConsole.base);
+ break;
+#endif /* FSL_FEATURE_SOC_LPUART_COUNT */
+#if defined(FSL_FEATURE_SOC_USB_COUNT) && (FSL_FEATURE_SOC_USB_COUNT > 0) && defined(BOARD_USE_VIRTUALCOM)
+ case DEBUG_CONSOLE_DEVICE_TYPE_USBCDC:
+ /* Disable USBCDC module. */
+ USB_VcomDeinit(s_debugConsole.base);
+ break;
+#endif /* FSL_FEATURE_SOC_USB_COUNT && BOARD_USE_VIRTUALCOM*/
+ default:
+ /* Device identified is invalid, return invalid device error code. */
+ s_debugConsole.type = DEBUG_CONSOLE_DEVICE_TYPE_NONE;
+ return kStatus_InvalidArgument;
+ }
+ s_debugConsole.type = DEBUG_CONSOLE_DEVICE_TYPE_NONE;
+ return kStatus_Success;
+}
+
+#if SDK_DEBUGCONSOLE
+/* See fsl_debug_console.h for documentation of this function. */
+int DbgConsole_Printf(const char *fmt_s, ...)
+{
+ va_list ap;
+ int result;
+
+ /* Do nothing if the debug UART is not initialized. */
+ if (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+ va_start(ap, fmt_s);
+ result = DbgConsole_PrintfFormattedData(DbgConsole_Putchar, fmt_s, ap);
+ va_end(ap);
+
+ return result;
+}
+
+/* See fsl_debug_console.h for documentation of this function. */
+int DbgConsole_Putchar(int ch)
+{
+ /* Do nothing if the debug UART is not initialized. */
+ if (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+ s_debugConsole.ops.tx_union.PutChar(s_debugConsole.base, (uint8_t *)(&ch), 1);
+
+ return 1;
+}
+
+/* See fsl_debug_console.h for documentation of this function. */
+int DbgConsole_Scanf(char *fmt_ptr, ...)
+{
+ /* 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 (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+ va_start(ap, fmt_ptr);
+ temp_buf[0] = '\0';
+
+ for (i = 0; i < IO_MAXLINE; i++)
+ {
+ temp_buf[i] = result = DbgConsole_Getchar();
+
+ if ((result == '\r') || (result == '\n'))
+ {
+ /* End of Line. */
+ if(i == 0)
+ {
+ temp_buf[i] = '\0';
+ i = -1;
+ }
+ else
+ {
+ break;
+ }
+ }
+ }
+
+ if ((i == IO_MAXLINE))
+ {
+ temp_buf[i] = '\0';
+ }
+ else
+ {
+ temp_buf[i+1] = '\0';
+ }
+ result = DbgConsole_ScanfFormattedData(temp_buf, fmt_ptr, ap);
+ va_end(ap);
+
+ return result;
+}
+
+/* See fsl_debug_console.h for documentation of this function. */
+int DbgConsole_Getchar(void)
+{
+ char ch;
+ /* Do nothing if the debug UART is not initialized. */
+ if (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+ s_debugConsole.ops.rx_union.GetChar(s_debugConsole.base, (uint8_t *)(&ch), 1);
+
+ return ch;
+}
+
+/*************Code for process formatted data*******************************/
+/*!
+ * @brief Scanline function which ignores white spaces.
+ *
+ * @param[in] s The address of the string pointer to update.
+ * @return String without white spaces.
+ */
+static uint32_t DbgConsole_ScanIgnoreWhiteSpace(const char **s)
+{
+ uint8_t count = 0;
+ uint8_t c;
+
+ c = **s;
+ while ((c == ' ') || (c == '\t') || (c == '\n') || (c == '\r') || (c == '\v') || (c == '\f'))
+ {
+ count++;
+ (*s)++;
+ c = **s;
+ }
+ return count;
+}
+
+/*!
+ * @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++)
+ {
+ 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
+ int64_t a;
+ int64_t b;
+ int64_t c;
+
+ uint64_t ua;
+ uint64_t ub;
+ uint64_t uc;
+#else
+ int32_t a;
+ int32_t b;
+ int32_t c;
+
+ uint32_t ua;
+ uint32_t ub;
+ uint32_t uc;
+#endif /* PRINTF_ADVANCED_ENABLE */
+
+ int32_t nlen;
+ char *nstrp;
+
+ nlen = 0;
+ nstrp = numstr;
+ *nstrp++ = '\0';
+
+ if (neg)
+ {
+#if PRINTF_ADVANCED_ENABLE
+ a = *(int64_t *)nump;
+#else
+ a = *(int32_t *)nump;
+#endif /* PRINTF_ADVANCED_ENABLE */
+ if (a == 0)
+ {
+ *nstrp = '0';
+ ++nlen;
+ return nlen;
+ }
+ while (a != 0)
+ {
+#if PRINTF_ADVANCED_ENABLE
+ b = (int64_t)a / (int64_t)radix;
+ c = (int64_t)a - ((int64_t)b * (int64_t)radix);
+ if (c < 0)
+ {
+ uc = (uint64_t)c;
+ c = (int64_t)(~uc) + 1 + '0';
+ }
+#else
+ b = a / radix;
+ c = a - (b * radix);
+ if (c < 0)
+ {
+ uc = (uint32_t)c;
+ c = (uint32_t)(~uc) + 1 + '0';
+ }
+#endif /* PRINTF_ADVANCED_ENABLE */
+ else
+ {
+ c = c + '0';
+ }
+ a = b;
+ *nstrp++ = (char)c;
+ ++nlen;
+ }
+ }
+ else
+ {
+#if PRINTF_ADVANCED_ENABLE
+ ua = *(uint64_t *)nump;
+#else
+ ua = *(uint32_t *)nump;
+#endif /* PRINTF_ADVANCED_ENABLE */
+ if (ua == 0)
+ {
+ *nstrp = '0';
+ ++nlen;
+ return nlen;
+ }
+ while (ua != 0)
+ {
+#if PRINTF_ADVANCED_ENABLE
+ ub = (uint64_t)ua / (uint64_t)radix;
+ uc = (uint64_t)ua - ((uint64_t)ub * (uint64_t)radix);
+#else
+ ub = ua / (uint32_t)radix;
+ uc = ua - (ub * (uint32_t)radix);
+#endif /* PRINTF_ADVANCED_ENABLE */
+
+ if (uc < 10)
+ {
+ uc = uc + '0';
+ }
+ else
+ {
+ uc = uc - 10 + (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;
+ int32_t i;
+ uint32_t uc;
+ 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 (!r)
+ {
+ *nstrp = '0';
+ ++nlen;
+ return nlen;
+ }
+ fractpart = modf((double)r, (double *)&intpart);
+ /* Process fractional part. */
+ for (i = 0; i < precision_width; i++)
+ {
+ fractpart *= radix;
+ }
+ if (r >= 0)
+ {
+ fa = fractpart + (double)0.5;
+ if (fa >= pow(10, precision_width))
+ {
+ intpart++;
+ }
+ }
+ else
+ {
+ fa = fractpart - (double)0.5;
+ if (fa <= -pow(10, precision_width))
+ {
+ intpart--;
+ }
+ }
+ for (i = 0; i < precision_width; i++)
+ {
+ fb = fa / (int32_t)radix;
+ dc = (fa - (int64_t)fb * (int32_t)radix);
+ c = (int32_t)dc;
+ if (c < 0)
+ {
+ uc = (uint32_t)c;
+ c = (int32_t)(~uc) + 1 + '0';
+ }
+ 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)
+ {
+ uc = (uint32_t)c;
+ c = (int32_t)(~uc) + 1 + '0';
+ }
+ 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_ptr Format string for printf.
+ * @param[in] args_ptr Arguments to printf.
+ *
+ * @return Number of characters
+ */
+static int DbgConsole_PrintfFormattedData(PUTCHAR_FUNC func_ptr, const char *fmt, va_list ap)
+{
+ /* va_list ap; */
+ char *p;
+ int32_t c;
+
+ char vstr[33];
+ char *vstrp = NULL;
+ int32_t vlen = 0;
+
+ int32_t 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;
+ int32_t schar, dschar;
+ int64_t ival;
+ uint64_t uval = 0;
+#else
+ int32_t ival;
+ uint32_t 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. */
+ for (p = (char *)fmt; (c = *p) != 0; 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 != '%')
+ {
+ func_ptr(c);
+ count++;
+ /* 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 |= kPRINTF_Minus;
+ break;
+ case '+':
+ flags_used |= kPRINTF_Plus;
+ break;
+ case ' ':
+ flags_used |= kPRINTF_Space;
+ break;
+ case '0':
+ flags_used |= kPRINTF_Zero;
+ break;
+ case '#':
+ flags_used |= 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 * 10) + (c - '0');
+ }
+ else
+ {
+ /* We've gone one char too far. */
+ --p;
+ done = true;
+ }
+ }
+ /* Next check for the width and precision field separator. */
+ precision_width = 6;
+ if (*++p == '.')
+ {
+ /* Must get precision field width, if present. */
+ precision_width = 0;
+ done = false;
+ while (!done)
+ {
+ c = *++p;
+ if ((c >= '0') && (c <= '9'))
+ {
+ precision_width = (precision_width * 10) + (c - '0');
+ }
+ 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 |= kPRINTF_LengthShortInt;
+ --p;
+ }
+ else
+ {
+ flags_used |= kPRINTF_LengthChar;
+ }
+ break;
+ case 'l':
+ if (*++p != 'l')
+ {
+ flags_used |= kPRINTF_LengthLongInt;
+ --p;
+ }
+ else
+ {
+ flags_used |= kPRINTF_LengthLongLongInt;
+ }
+ 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 (flags_used & kPRINTF_LengthLongLongInt)
+ {
+ ival = (int64_t)va_arg(ap, int64_t);
+ }
+ else
+#endif /* PRINTF_ADVANCED_ENABLE */
+ {
+ ival = (int32_t)va_arg(ap, int32_t);
+ }
+ vlen = DbgConsole_ConvertRadixNumToString(vstr, &ival, true, 10, use_caps);
+ vstrp = &vstr[vlen];
+#if PRINTF_ADVANCED_ENABLE
+ if (ival < 0)
+ {
+ schar = '-';
+ ++vlen;
+ }
+ else
+ {
+ if (flags_used & kPRINTF_Plus)
+ {
+ schar = '+';
+ ++vlen;
+ }
+ else
+ {
+ if (flags_used & kPRINTF_Space)
+ {
+ schar = ' ';
+ ++vlen;
+ }
+ else
+ {
+ schar = 0;
+ }
+ }
+ }
+ dschar = false;
+ /* Do the ZERO pad. */
+ if (flags_used & kPRINTF_Zero)
+ {
+ if (schar)
+ {
+ func_ptr(schar);
+ count++;
+ }
+ dschar = true;
+
+ DbgConsole_PrintfPaddingCharacter('0', vlen, field_width, &count, func_ptr);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!(flags_used & kPRINTF_Minus))
+ {
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+ if (schar)
+ {
+ func_ptr(schar);
+ count++;
+ }
+ dschar = true;
+ }
+ }
+ /* The string was built in reverse order, now display in correct order. */
+ if ((!dschar) && schar)
+ {
+ 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)
+ {
+ schar = '-';
+ ++vlen;
+ }
+ else
+ {
+ if (flags_used & kPRINTF_Plus)
+ {
+ schar = '+';
+ ++vlen;
+ }
+ else
+ {
+ if (flags_used & kPRINTF_Space)
+ {
+ schar = ' ';
+ ++vlen;
+ }
+ else
+ {
+ schar = 0;
+ }
+ }
+ }
+ dschar = false;
+ if (flags_used & kPRINTF_Zero)
+ {
+ if (schar)
+ {
+ func_ptr(schar);
+ count++;
+ }
+ dschar = true;
+ DbgConsole_PrintfPaddingCharacter('0', vlen, field_width, &count, func_ptr);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!(flags_used & kPRINTF_Minus))
+ {
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+ if (schar)
+ {
+ func_ptr(schar);
+ count++;
+ }
+ dschar = true;
+ }
+ }
+ if ((!dschar) && schar)
+ {
+ 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 (flags_used & kPRINTF_LengthLongLongInt)
+ {
+ uval = (uint64_t)va_arg(ap, uint64_t);
+ }
+ else
+#endif /* PRINTF_ADVANCED_ENABLE */
+ {
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ }
+ vlen = DbgConsole_ConvertRadixNumToString(vstr, &uval, false, 16, use_caps);
+ vstrp = &vstr[vlen];
+
+#if PRINTF_ADVANCED_ENABLE
+ dschar = false;
+ if (flags_used & kPRINTF_Zero)
+ {
+ if (flags_used & kPRINTF_Pound)
+ {
+ func_ptr('0');
+ func_ptr((use_caps ? 'X' : 'x'));
+ count += 2;
+ /*vlen += 2;*/
+ dschar = true;
+ }
+ DbgConsole_PrintfPaddingCharacter('0', vlen, field_width, &count, func_ptr);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!(flags_used & kPRINTF_Minus))
+ {
+ if (flags_used & kPRINTF_Pound)
+ {
+ vlen += 2;
+ }
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+ if (flags_used & kPRINTF_Pound)
+ {
+ func_ptr('0');
+ func_ptr(use_caps ? 'X' : 'x');
+ count += 2;
+
+ dschar = true;
+ }
+ }
+ }
+
+ if ((flags_used & kPRINTF_Pound) && (!dschar))
+ {
+ func_ptr('0');
+ func_ptr(use_caps ? 'X' : 'x');
+ count += 2;
+ vlen += 2;
+ }
+#endif /* PRINTF_ADVANCED_ENABLE */
+ }
+ if (c == 'o')
+ {
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ radix = 8;
+ }
+ if (c == 'b')
+ {
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ radix = 2;
+ vstrp = &vstr[vlen];
+ }
+ if (c == 'p')
+ {
+ uval = (uint32_t)va_arg(ap, void *);
+ radix = 16;
+ vstrp = &vstr[vlen];
+ }
+ if (c == 'u')
+ {
+ uval = (uint32_t)va_arg(ap, uint32_t);
+ radix = 10;
+ vstrp = &vstr[vlen];
+ }
+ if ((c == 'o') || (c == 'b') || (c == 'p') || (c == 'u'))
+ {
+ vlen = DbgConsole_ConvertRadixNumToString(vstr, &uval, false, radix, use_caps);
+ vstrp = &vstr[vlen];
+#if PRINTF_ADVANCED_ENABLE
+ if (flags_used & kPRINTF_Zero)
+ {
+ DbgConsole_PrintfPaddingCharacter('0', vlen, field_width, &count, func_ptr);
+ vlen = field_width;
+ }
+ else
+ {
+ if (!(flags_used & kPRINTF_Minus))
+ {
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+ }
+ }
+#endif /* PRINTF_ADVANCED_ENABLE */
+ }
+#if !PRINTF_ADVANCED_ENABLE
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+#endif /* !PRINTF_ADVANCED_ENABLE */
+ if (vstrp != NULL)
+ {
+ while (*vstrp)
+ {
+ func_ptr(*vstrp--);
+ count++;
+ }
+ }
+#if PRINTF_ADVANCED_ENABLE
+ if (flags_used & kPRINTF_Minus)
+ {
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+ }
+#endif /* PRINTF_ADVANCED_ENABLE */
+ }
+ else if (c == 'c')
+ {
+ cval = (char)va_arg(ap, uint32_t);
+ func_ptr(cval);
+ count++;
+ }
+ else if (c == 's')
+ {
+ sval = (char *)va_arg(ap, char *);
+ if (sval)
+ {
+ vlen = strlen(sval);
+#if PRINTF_ADVANCED_ENABLE
+ if (!(flags_used & kPRINTF_Minus))
+#endif /* PRINTF_ADVANCED_ENABLE */
+ {
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+ }
+ while (*sval)
+ {
+ func_ptr(*sval++);
+ count++;
+ }
+#if PRINTF_ADVANCED_ENABLE
+ if (flags_used & kPRINTF_Minus)
+ {
+ DbgConsole_PrintfPaddingCharacter(' ', vlen, field_width, &count, func_ptr);
+ }
+#endif /* PRINTF_ADVANCED_ENABLE */
+ }
+ }
+ else
+ {
+ func_ptr(c);
+ count++;
+ }
+ }
+ }
+ return count;
+}
+
+/*!
+ * @brief Converts an input line of ASCII characters based upon a provided
+ * string format.
+ *
+ * @param[in] line_ptr The input line of ASCII data.
+ * @param[in] format Format first points to the format string.
+ * @param[in] args_ptr The list of parameters.
+ *
+ * @return Number of input items converted and assigned.
+ * @retval IO_EOF When line_ptr is empty string "".
+ */
+static int DbgConsole_ScanfFormattedData(const char *line_ptr, char *format, va_list args_ptr)
+{
+ uint8_t base;
+ int8_t neg;
+ /* Identifier for the format string. */
+ char *c = format;
+ char temp;
+ char *buf;
+ /* Flag telling the conversion specification. */
+ uint32_t flag = 0;
+ /* Filed width for the matching input streams. */
+ uint32_t field_width;
+ /* How many arguments are assigned except the suppress. */
+ uint32_t nassigned = 0;
+ /* How many characters are read from the input streams. */
+ uint32_t n_decode = 0;
+
+ int32_t val;
+
+ const char *s;
+ /* Identifier for the input string. */
+ const char *p = line_ptr;
+
+ /* Return EOF error before any conversion. */
+ if (*p == '\0')
+ {
+ return -1;
+ }
+
+ /* Decode directives. */
+ while ((*c) && (*p))
+ {
+ /* Ignore all white-spaces in the format strings. */
+ if (DbgConsole_ScanIgnoreWhiteSpace((const char **)&c))
+ {
+ n_decode += DbgConsole_ScanIgnoreWhiteSpace(&p);
+ }
+ else if ((*c != '%') || ((*c == '%') && (*(c + 1) == '%')))
+ {
+ /* Ordinary characters. */
+ c++;
+ if (*p == *c)
+ {
+ n_decode++;
+ p++;
+ c++;
+ }
+ else
+ {
+ /* Match failure. Misalignment with C99, the unmatched characters need to be pushed back to stream.
+ * However, it is deserted now. */
+ break;
+ }
+ }
+ else
+ {
+ /* convernsion specification */
+ c++;
+ /* Reset. */
+ flag = 0;
+ field_width = 0;
+ base = 0;
+
+ /* Loop to get full conversion specification. */
+ while ((*c) && (!(flag & kSCANF_DestMask)))
+ {
+ switch (*c)
+ {
+#if SCANF_ADVANCED_ENABLE
+ case '*':
+ if (flag & kSCANF_Suppress)
+ {
+ /* Match failure. */
+ return nassigned;
+ }
+ flag |= kSCANF_Suppress;
+ c++;
+ break;
+ case 'h':
+ if (flag & kSCANF_LengthMask)
+ {
+ /* Match failure. */
+ return nassigned;
+ }
+
+ if (c[1] == 'h')
+ {
+ flag |= kSCANF_LengthChar;
+ c++;
+ }
+ else
+ {
+ flag |= kSCANF_LengthShortInt;
+ }
+ c++;
+ break;
+ case 'l':
+ if (flag & kSCANF_LengthMask)
+ {
+ /* Match failure. */
+ return nassigned;
+ }
+
+ if (c[1] == 'l')
+ {
+ flag |= kSCANF_LengthLongLongInt;
+ c++;
+ }
+ else
+ {
+ flag |= kSCANF_LengthLongInt;
+ }
+ c++;
+ break;
+#endif /* SCANF_ADVANCED_ENABLE */
+#if SCANF_FLOAT_ENABLE
+ case 'L':
+ if (flag & kSCANF_LengthMask)
+ {
+ /* Match failure. */
+ return nassigned;
+ }
+ flag |= kSCANF_LengthLongLongDouble;
+ c++;
+ break;
+#endif /* SCANF_FLOAT_ENABLE */
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ if (field_width)
+ {
+ /* Match failure. */
+ return nassigned;
+ }
+ do
+ {
+ field_width = field_width * 10 + *c - '0';
+ c++;
+ } while ((*c >= '0') && (*c <= '9'));
+ break;
+ case 'd':
+ base = 10;
+ flag |= kSCANF_TypeSinged;
+ flag |= kSCANF_DestInt;
+ c++;
+ break;
+ case 'u':
+ base = 10;
+ flag |= kSCANF_DestInt;
+ c++;
+ break;
+ case 'o':
+ base = 8;
+ flag |= kSCANF_DestInt;
+ c++;
+ break;
+ case 'x':
+ case 'X':
+ base = 16;
+ flag |= kSCANF_DestInt;
+ c++;
+ break;
+ case 'i':
+ base = 0;
+ flag |= kSCANF_DestInt;
+ c++;
+ break;
+#if SCANF_FLOAT_ENABLE
+ case 'a':
+ case 'A':
+ case 'e':
+ case 'E':
+ case 'f':
+ case 'F':
+ case 'g':
+ case 'G':
+ flag |= kSCANF_DestFloat;
+ c++;
+ break;
+#endif /* SCANF_FLOAT_ENABLE */
+ case 'c':
+ flag |= kSCANF_DestChar;
+ if (!field_width)
+ {
+ field_width = 1;
+ }
+ c++;
+ break;
+ case 's':
+ flag |= kSCANF_DestString;
+ c++;
+ break;
+ default:
+ return nassigned;
+ }
+ }
+
+ if (!(flag & kSCANF_DestMask))
+ {
+ /* Format strings are exhausted. */
+ return nassigned;
+ }
+
+ if (!field_width)
+ {
+ /* Large than length of a line. */
+ field_width = 99;
+ }
+
+ /* Matching strings in input streams and assign to argument. */
+ switch (flag & kSCANF_DestMask)
+ {
+ case kSCANF_DestChar:
+ s = (const char *)p;
+ buf = va_arg(args_ptr, char *);
+ while ((field_width--) && (*p))
+ {
+ if (!(flag & kSCANF_Suppress))
+ {
+ *buf++ = *p++;
+ }
+ else
+ {
+ p++;
+ }
+ n_decode++;
+ }
+
+ if ((!(flag & kSCANF_Suppress)) && (s != p))
+ {
+ nassigned++;
+ }
+ break;
+ case kSCANF_DestString:
+ n_decode += DbgConsole_ScanIgnoreWhiteSpace(&p);
+ s = p;
+ buf = va_arg(args_ptr, char *);
+ while ((field_width--) && (*p != '\0') && (*p != ' ') && (*p != '\t') && (*p != '\n') &&
+ (*p != '\r') && (*p != '\v') && (*p != '\f'))
+ {
+ if (flag & kSCANF_Suppress)
+ {
+ p++;
+ }
+ else
+ {
+ *buf++ = *p++;
+ }
+ n_decode++;
+ }
+
+ if ((!(flag & kSCANF_Suppress)) && (s != p))
+ {
+ /* Add NULL to end of string. */
+ *buf = '\0';
+ nassigned++;
+ }
+ break;
+ case kSCANF_DestInt:
+ n_decode += DbgConsole_ScanIgnoreWhiteSpace(&p);
+ s = p;
+ val = 0;
+ if ((base == 0) || (base == 16))
+ {
+ if ((s[0] == '0') && ((s[1] == 'x') || (s[1] == 'X')))
+ {
+ base = 16;
+ if (field_width >= 1)
+ {
+ p += 2;
+ n_decode += 2;
+ field_width -= 2;
+ }
+ }
+ }
+
+ if (base == 0)
+ {
+ if (s[0] == '0')
+ {
+ base = 8;
+ }
+ else
+ {
+ base = 10;
+ }
+ }
+
+ neg = 1;
+ switch (*p)
+ {
+ case '-':
+ neg = -1;
+ n_decode++;
+ p++;
+ field_width--;
+ break;
+ case '+':
+ neg = 1;
+ n_decode++;
+ p++;
+ field_width--;
+ break;
+ default:
+ break;
+ }
+
+ while ((*p) && (field_width--))
+ {
+ if ((*p <= '9') && (*p >= '0'))
+ {
+ temp = *p - '0';
+ }
+ else if ((*p <= 'f') && (*p >= 'a'))
+ {
+ temp = *p - 'a' + 10;
+ }
+ else if ((*p <= 'F') && (*p >= 'A'))
+ {
+ temp = *p - 'A' + 10;
+ }
+ else
+ {
+ temp = base;
+ }
+
+ if (temp >= base)
+ {
+ break;
+ }
+ else
+ {
+ val = base * val + temp;
+ }
+ p++;
+ n_decode++;
+ }
+ val *= neg;
+ if (!(flag & kSCANF_Suppress))
+ {
+#if SCANF_ADVANCED_ENABLE
+ switch (flag & kSCANF_LengthMask)
+ {
+ case kSCANF_LengthChar:
+ if (flag & kSCANF_TypeSinged)
+ {
+ *va_arg(args_ptr, signed char *) = (signed char)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned char *) = (unsigned char)val;
+ }
+ break;
+ case kSCANF_LengthShortInt:
+ if (flag & kSCANF_TypeSinged)
+ {
+ *va_arg(args_ptr, signed short *) = (signed short)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned short *) = (unsigned short)val;
+ }
+ break;
+ case kSCANF_LengthLongInt:
+ if (flag & kSCANF_TypeSinged)
+ {
+ *va_arg(args_ptr, signed long int *) = (signed long int)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned long int *) = (unsigned long int)val;
+ }
+ break;
+ case kSCANF_LengthLongLongInt:
+ if (flag & kSCANF_TypeSinged)
+ {
+ *va_arg(args_ptr, signed long long int *) = (signed long long int)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned long long int *) = (unsigned long long int)val;
+ }
+ break;
+ default:
+ /* The default type is the type int. */
+ if (flag & kSCANF_TypeSinged)
+ {
+ *va_arg(args_ptr, signed int *) = (signed int)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned int *) = (unsigned int)val;
+ }
+ break;
+ }
+#else
+ /* The default type is the type int. */
+ if (flag & kSCANF_TypeSinged)
+ {
+ *va_arg(args_ptr, signed int *) = (signed int)val;
+ }
+ else
+ {
+ *va_arg(args_ptr, unsigned int *) = (unsigned int)val;
+ }
+#endif /* SCANF_ADVANCED_ENABLE */
+ nassigned++;
+ }
+ break;
+#if SCANF_FLOAT_ENABLE
+ case kSCANF_DestFloat:
+ n_decode += DbgConsole_ScanIgnoreWhiteSpace(&p);
+ fnum = strtod(p, (char **)&s);
+
+ if ((fnum >= HUGE_VAL) || (fnum <= -HUGE_VAL))
+ {
+ break;
+ }
+
+ n_decode += (int)(s) - (int)(p);
+ p = s;
+ if (!(flag & kSCANF_Suppress))
+ {
+ if (flag & kSCANF_LengthLongLongDouble)
+ {
+ *va_arg(args_ptr, double *) = fnum;
+ }
+ else
+ {
+ *va_arg(args_ptr, float *) = (float)fnum;
+ }
+ nassigned++;
+ }
+ break;
+#endif /* SCANF_FLOAT_ENABLE */
+ default:
+ return nassigned;
+ }
+ }
+ }
+ return nassigned;
+}
+#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__))
+#pragma weak __write
+size_t __write(int handle, const unsigned char *buffer, size_t size)
+{
+ if (buffer == 0)
+ {
+ /*
+ * 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.)
+ */
+ return 0;
+ }
+
+ /* This function only writes to "standard out" and "standard err" for all other file handles it returns failure. */
+ if ((handle != 1) && (handle != 2))
+ {
+ return ((size_t)-1);
+ }
+
+ /* Do nothing if the debug UART is not initialized. */
+ if (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return ((size_t)-1);
+ }
+
+ /* Send data. */
+ s_debugConsole.ops.tx_union.PutChar(s_debugConsole.base, buffer, 1);
+ return size;
+}
+
+#pragma weak __read
+size_t __read(int handle, unsigned char *buffer, size_t size)
+{
+ /* This function only reads from "standard in", for all other file handles it returns failure. */
+ if (handle != 0)
+ {
+ return ((size_t)-1);
+ }
+
+ /* Do nothing if the debug UART is not initialized. */
+ if (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return ((size_t)-1);
+ }
+
+ /* Receive data. */
+ s_debugConsole.ops.rx_union.GetChar(s_debugConsole.base, buffer, size);
+
+ return size;
+}
+/* These function __write and __read is used to support ARM_GCC, KDS, Atollic toolchains to printf and scanf*/
+#elif(defined(__GNUC__))
+#pragma weak __write
+int _write(int handle, char *buffer, int size)
+{
+ if (buffer == 0)
+ {
+ /* 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 (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+
+ /* Send data. */
+ s_debugConsole.ops.tx_union.PutChar(s_debugConsole.base, (uint8_t *)buffer, size);
+ return size;
+}
+
+#pragma weak __read
+int _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 (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+
+ /* Receive data. */
+ s_debugConsole.ops.rx_union.GetChar(s_debugConsole.base, (uint8_t *)buffer, size);
+ return size;
+}
+/* These function fputc and fgetc is used to support KEIL toolchain to printf and scanf*/
+#elif 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.
+ */
+};
+
+/* FILE is typedef in stdio.h. */
+#pragma weak __stdout
+FILE __stdout;
+FILE __stdin;
+
+#pragma weak fputc
+int fputc(int ch, FILE *f)
+{
+ /* Do nothing if the debug UART is not initialized. */
+ if (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+
+ /* Send data. */
+ s_debugConsole.ops.tx_union.PutChar(s_debugConsole.base, (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 (s_debugConsole.type == DEBUG_CONSOLE_DEVICE_TYPE_NONE)
+ {
+ return -1;
+ }
+
+ /* Receive data. */
+ s_debugConsole.ops.rx_union.GetChar(s_debugConsole.base, (uint8_t *)(&ch), 1);
+ return ch;
+}
+#endif /* __ICCARM__ */
diff --git a/utilities/fsl_debug_console.h b/utilities/fsl_debug_console.h
new file mode 100644
index 0000000..3ef50cf
--- /dev/null
+++ b/utilities/fsl_debug_console.h
@@ -0,0 +1,193 @@
+/*
+ * Copyright (c) 2013 - 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * Debug console shall provide input and output functions to scan and print formatted data.
+ * o Support a format specifier for PRINTF follows this prototype "%[flags][width][.precision][length]specifier"
+ * - [flags] :'-', '+', '#', ' ', '0'
+ * - [width]: number (0,1...)
+ * - [.precision]: number (0,1...)
+ * - [length]: do not support
+ * - [specifier]: 'd', 'i', 'f', 'F', 'x', 'X', 'o', 'p', 'u', 'c', 's', 'n'
+ * o Support a format specifier for SCANF follows this prototype " %[*][width][length]specifier"
+ * - [*]: is supported.
+ * - [width]: number (0,1...)
+ * - [length]: 'h', 'hh', 'l','ll','L'. ignore ('j','z','t')
+ * - [specifier]: 'd', 'i', 'u', 'f', 'F', 'e', 'E', 'g', 'G', 'a', 'A', 'o', 'c', 's'
+ */
+
+#ifndef _FSL_DEBUGCONSOLE_H_
+#define _FSL_DEBUGCONSOLE_H_
+
+#include "fsl_common.h"
+
+/*
+ * @addtogroup debugconsole
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*! @brief Definition to select sdk or toolchain printf, scanf. */
+#ifndef SDK_DEBUGCONSOLE
+#define SDK_DEBUGCONSOLE 1U
+#endif
+
+#if defined(SDK_DEBUGCONSOLE) && !(SDK_DEBUGCONSOLE)
+#include <stdio.h>
+#endif
+
+/*! @brief Definition to printf float number. */
+#ifndef PRINTF_FLOAT_ENABLE
+#define PRINTF_FLOAT_ENABLE 0U
+#endif /* PRINTF_FLOAT_ENABLE */
+
+/*! @brief Definition to scanf float number. */
+#ifndef SCANF_FLOAT_ENABLE
+#define SCANF_FLOAT_ENABLE 0U
+#endif /* SCANF_FLOAT_ENABLE */
+
+/*! @brief Definition to support advanced format specifier for printf. */
+#ifndef PRINTF_ADVANCED_ENABLE
+#define PRINTF_ADVANCED_ENABLE 0U
+#endif /* PRINTF_ADVANCED_ENABLE */
+
+/*! @brief Definition to support advanced format specifier for scanf. */
+#ifndef SCANF_ADVANCED_ENABLE
+#define SCANF_ADVANCED_ENABLE 0U
+#endif /* SCANF_ADVANCED_ENABLE */
+
+#if SDK_DEBUGCONSOLE /* Select printf, scanf, putchar, getchar of SDK version. */
+#define PRINTF DbgConsole_Printf
+#define SCANF DbgConsole_Scanf
+#define PUTCHAR DbgConsole_Putchar
+#define GETCHAR DbgConsole_Getchar
+#else /* Select printf, scanf, putchar, getchar of toolchain. */
+#define PRINTF printf
+#define SCANF scanf
+#define PUTCHAR putchar
+#define GETCHAR getchar
+#endif /* SDK_DEBUGCONSOLE */
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* __cplusplus */
+
+/*! @name Initialization*/
+/* @{ */
+
+/*!
+ * @brief Initialize the the peripheral used for debug messages.
+ *
+ * Call this function to enable debug log messages to be output via the specified peripheral,
+ * frequency of peripheral source clock, base address at the specified baud rate.
+ * After this function has returned, stdout and stdin will be connected to the selected peripheral.
+ *
+ * @param baseAddr Which address of peripheral is used to send debug messages.
+ * @param baudRate The desired baud rate in bits per second.
+ * @param device Low level device type for the debug console, could be one of:
+ * @arg DEBUG_CONSOLE_DEVICE_TYPE_UART,
+ * @arg DEBUG_CONSOLE_DEVICE_TYPE_LPUART,
+ * @arg DEBUG_CONSOLE_DEVICE_TYPE_LPSCI,
+ * @arg DEBUG_CONSOLE_DEVICE_TYPE_USBCDC.
+ * @param clkSrcFreq Frequency of peripheral source clock.
+ *
+ * @return Whether initialization was successful or not.
+ * @retval kStatus_Success Execution successfully
+ * @retval kStatus_Fail Execution failure
+ * @retval kStatus_InvalidArgument Invalid argument existed
+ */
+status_t DbgConsole_Init(uint32_t baseAddr, uint32_t baudRate, uint8_t device, uint32_t clkSrcFreq);
+
+/*!
+ * @brief De-initialize the peripheral used for debug messages.
+ *
+ * Call this function to disable debug log messages to be output via the specified peripheral
+ * base address and at the specified baud rate.
+ *
+ * @return Whether de-initialization was successful or not.
+ */
+status_t DbgConsole_Deinit(void);
+
+#if SDK_DEBUGCONSOLE
+/*!
+ * @brief Writes formatted output to the standard output stream.
+ *
+ * Call this function to Writes formatted output to the standard output stream.
+ *
+ * @param fmt_s Format control string.
+ * @return Returns the number of characters printed, or a negative value if an error occurs.
+ */
+int DbgConsole_Printf(const char *fmt_s, ...);
+
+/*!
+ * @brief Writes a character to stdout.
+ *
+ * Call this function to write a character to stdout.
+ *
+ * @param ch Character to be written.
+ * @return Returns the character written.
+ */
+int DbgConsole_Putchar(int ch);
+
+/*!
+ * @brief Reads formatted data from the standard input stream.
+ *
+ * Call this function to read formatted data from the standard input stream.
+ *
+ * @param fmt_ptr Format control string.
+ * @return Returns the number of fields successfully converted and assigned.
+ */
+int DbgConsole_Scanf(char *fmt_ptr, ...);
+
+/*!
+ * @brief Reads a character from standard input.
+ *
+ * Call this function to read a character from standard input.
+ *
+ * @return Returns the character read.
+ */
+int DbgConsole_Getchar(void);
+
+#endif /* SDK_DEBUGCONSOLE */
+
+/*! @} */
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+/*! @} */
+
+#endif /* _FSL_DEBUGCONSOLE_H_ */
diff --git a/utilities/fsl_notifier.c b/utilities/fsl_notifier.c
new file mode 100644
index 0000000..3e2744f
--- /dev/null
+++ b/utilities/fsl_notifier.c
@@ -0,0 +1,182 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "fsl_notifier.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+
+status_t NOTIFIER_CreateHandle(notifier_handle_t *notifierHandle,
+ notifier_user_config_t **configs,
+ uint8_t configsNumber,
+ notifier_callback_config_t *callbacks,
+ uint8_t callbacksNumber,
+ notifier_user_function_t userFunction,
+ void *userData)
+{
+ /* Check input parameter - at least one configuration is required and userFunction must exist */
+ if ((configs == NULL) || (configsNumber == 0U) || (userFunction == NULL))
+ {
+ return kStatus_Fail;
+ }
+ /* Initialize handle structure */
+ memset(notifierHandle, 0, sizeof(notifier_handle_t));
+ /* Store references to user-defined configurations */
+ notifierHandle->configsTable = configs;
+ notifierHandle->configsNumber = configsNumber;
+ /* Store references to user-defined callback configurations */
+ if (callbacks != NULL)
+ {
+ notifierHandle->callbacksTable = callbacks;
+ notifierHandle->callbacksNumber = callbacksNumber;
+ /* If all callbacks return success, then the errorCallbackIndex is callbacksNumber */
+ notifierHandle->errorCallbackIndex = callbacksNumber;
+ }
+ notifierHandle->userFunction = userFunction;
+ notifierHandle->userData = userData;
+
+ return kStatus_Success;
+}
+
+status_t NOTIFIER_SwitchConfig(notifier_handle_t *notifierHandle, uint8_t configIndex, notifier_policy_t policy)
+{
+ uint8_t currentStaticCallback = 0U; /* Index to array of statically registered call-backs */
+ status_t returnCode = kStatus_Success; /* Function return */
+
+ notifier_notification_block_t notifyBlock; /* Callback notification block */
+ notifier_callback_config_t *callbackConfig; /* Pointer to callback configuration */
+
+ /* Set errorcallbackindex as callbacksNumber, which means no callback error now */
+ notifierHandle->errorCallbackIndex = notifierHandle->callbacksNumber;
+
+ /* Requested configuration availability check */
+ if (configIndex >= notifierHandle->configsNumber)
+ {
+ return kStatus_OutOfRange;
+ }
+
+ /* Initialization of local variables from the Notifier handle structure */
+
+ notifyBlock.policy = policy;
+ notifyBlock.targetConfig = notifierHandle->configsTable[configIndex];
+ notifyBlock.notifyType = kNOTIFIER_NotifyBefore;
+
+ /* From all statically registered call-backs... */
+ for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber; currentStaticCallback++)
+ {
+ callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]);
+ /* ...notify only those which asked to be called before the configuration switch */
+ if (((uint32_t)callbackConfig->callbackType) & kNOTIFIER_CallbackBefore)
+ {
+ /* In case that call-back returned error code mark it, store the call-back handle and eventually cancel
+ * the configuration switch */
+ if (callbackConfig->callback(&notifyBlock, callbackConfig->callbackData) != kStatus_Success)
+ {
+ returnCode = kStatus_NOTIFIER_ErrorNotificationBefore;
+ notifierHandle->errorCallbackIndex = currentStaticCallback;
+ /* If not forcing configuration switch, call all already notified call-backs to revert their state
+ * as the switch is canceled */
+ if (policy != kNOTIFIER_PolicyForcible)
+ {
+ break;
+ }
+ }
+ }
+ }
+
+ /* Set configuration */
+
+ /* In case that any call-back returned error code and policy doesn't force the configuration set, go to after
+ * switch call-backs */
+ if ((policy == kNOTIFIER_PolicyForcible) || (returnCode == kStatus_Success))
+ {
+ returnCode = notifierHandle->userFunction(notifierHandle->configsTable[configIndex], notifierHandle->userData);
+ if (returnCode != kStatus_Success)
+ {
+ return returnCode;
+ }
+ /* Update current configuration index */
+ notifierHandle->currentConfigIndex = configIndex;
+ notifyBlock.notifyType = kNOTIFIER_NotifyAfter;
+ /* From all statically registered call-backs... */
+ for (currentStaticCallback = 0U; currentStaticCallback < notifierHandle->callbacksNumber;
+ currentStaticCallback++)
+ {
+ callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]);
+ /* ...notify only those which asked to be called after the configruation switch */
+ if (((uint32_t)callbackConfig->callbackType) & kNOTIFIER_CallbackAfter)
+ {
+ /* In case that call-back returned error code mark it and store the call-back handle */
+ if (callbackConfig->callback(&notifyBlock, callbackConfig->callbackData) != kStatus_Success)
+ {
+ returnCode = kStatus_NOTIFIER_ErrorNotificationAfter;
+ notifierHandle->errorCallbackIndex = currentStaticCallback;
+ if (policy != kNOTIFIER_PolicyForcible)
+ {
+ break;
+ }
+ }
+ }
+ }
+ }
+ else
+ {
+ /* End of unsuccessful switch */
+ notifyBlock.notifyType = kNOTIFIER_NotifyRecover;
+ while (currentStaticCallback--)
+ {
+ callbackConfig = &(notifierHandle->callbacksTable[currentStaticCallback]);
+ if (((uint32_t)callbackConfig->callbackType) & kNOTIFIER_CallbackBefore)
+ {
+ callbackConfig->callback(&notifyBlock, callbackConfig->callbackData);
+ }
+ }
+ }
+
+ return returnCode;
+}
+
+uint8_t NOTIFIER_GetErrorCallbackIndex(notifier_handle_t *notifierHandle)
+{
+ return notifierHandle->errorCallbackIndex;
+}
diff --git a/utilities/fsl_notifier.h b/utilities/fsl_notifier.h
new file mode 100644
index 0000000..1d39134
--- /dev/null
+++ b/utilities/fsl_notifier.h
@@ -0,0 +1,259 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FSL_NOTIFIER_H_
+#define _FSL_NOTIFIER_H_
+
+#include "fsl_common.h"
+/*!
+ * @addtogroup notifier
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+
+/*!
+ * @brief Notifier error codes.
+ *
+ * Used as return value of Notifier functions.
+ */
+enum _notifier_status
+{
+ kStatus_NOTIFIER_ErrorNotificationBefore =
+ MAKE_STATUS(kStatusGroup_NOTIFIER, 0), /*!< Error occurs during send "BEFORE" notification. */
+ kStatus_NOTIFIER_ErrorNotificationAfter =
+ MAKE_STATUS(kStatusGroup_NOTIFIER, 1), /*!< Error occurs during send "AFTER" notification. */
+};
+
+/*!
+ * @brief Notifier policies.
+ *
+ * Defines whether user function execution is forced or not.
+ * For kNOTIFIER_PolicyForcible, the user function is executed regardless of the callback results,
+ * while kNOTIFIER_PolicyAgreement policy is used to exit NOTIFIER_SwitchConfig()
+ * when any of the callbacks returns error code.
+ * See also NOTIFIER_SwitchConfig() description.
+ */
+typedef enum _notifier_policy
+{
+ kNOTIFIER_PolicyAgreement, /*!< NOTIFIER_SwitchConfig() method is exited when any of the callbacks returns error
+ code. */
+ kNOTIFIER_PolicyForcible, /*!< user function is executed regardless of the results. */
+} notifier_policy_t;
+
+/*! @brief Notification type. Used to notify registered callbacks */
+typedef enum _notifier_notification_type
+{
+ kNOTIFIER_NotifyRecover = 0x00U, /*!< Notify IP to recover to previous work state. */
+ kNOTIFIER_NotifyBefore = 0x01U, /*!< Notify IP that configuration setting is going to change. */
+ kNOTIFIER_NotifyAfter = 0x02U, /*!< Notify IP that configuration setting has been changed. */
+} notifier_notification_type_t;
+
+/*!
+ * @brief The callback type, indicates what kinds of notification the callback handles.
+ *
+ * Used in the callback configuration structure (notifier_callback_config_t)
+ * to specify when the registered callback is called during configuration switch initiated by
+ * NOTIFIER_SwitchConfig().
+ * Callback can be invoked in following situations:
+ * - before the configuration switch (Callback return value can affect NOTIFIER_SwitchConfig()
+ * execution. See the NOTIFIER_SwitchConfig() and notifier_policy_t documentation).
+ * - after unsuccessful attempt to switch configuration
+ * - after successful configuration switch
+ */
+typedef enum _notifier_callback_type
+{
+ kNOTIFIER_CallbackBefore = 0x01U, /*!< Callback handles BEFORE notification. */
+ kNOTIFIER_CallbackAfter = 0x02U, /*!< Callback handles AFTER notification. */
+ kNOTIFIER_CallbackBeforeAfter = 0x03U, /*!< Callback handles BEFORE and AFTER notification. */
+} notifier_callback_type_t;
+
+/*! @brief Notifier user configuration type.
+ *
+ * Reference of user defined configuration is stored in an array; the notifier switches between these configurations
+ * based on this array.
+ */
+typedef void notifier_user_config_t;
+
+/*! @brief Notifier user function prototype
+ * Use this function to execute specific operations in configuration switch.
+ * Before and after this function execution, different notification is sent to registered callbacks.
+ * If this function returns any error code, NOTIFIER_SwitchConfig() exits.
+ *
+ * @param targetConfig target Configuration.
+ * @param userData Refers to other specific data passed to user function.
+ * @return An error code or kStatus_Success.
+ */
+typedef status_t (*notifier_user_function_t)(notifier_user_config_t *targetConfig, void *userData);
+
+/*! @brief notification block passed to the registered callback function. */
+typedef struct _notifier_notification_block
+{
+ notifier_user_config_t *targetConfig; /*!< Pointer to target configuration. */
+ notifier_policy_t policy; /*!< Configure transition policy. */
+ notifier_notification_type_t notifyType; /*!< Configure notification type. */
+} notifier_notification_block_t;
+
+/*!
+ * @brief Callback prototype.
+ *
+ * Declaration of callback. It is common for registered callbacks.
+ * Reference to function of this type is part of notifier_callback_config_t callback configuration structure.
+ * Depending on callback type, function of this prototype is called (see NOTIFIER_SwitchConfig())
+ * before configuration switch, after it or in both use cases to notify about
+ * the switch progress (see notifier_callback_type_t). When called, type of the notification
+ * is passed as parameter along with reference to the target configuration structure (see notifier_notification_block_t)
+ * and any data passed during the callback registration.
+ * When notified before configuration switch, depending on the configuration switch policy (see
+ * notifier_policy_t) the callback may deny the execution of user function by returning any error code different
+ * from kStatus_Success (see NOTIFIER_SwitchConfig()).
+ *
+ * @param notify Notification block.
+ * @param data Callback data. Refers to the data passed during callback registration. Intended to
+ * pass any driver or application data such as internal state information.
+ * @return An error code or kStatus_Success.
+ */
+typedef status_t (*notifier_callback_t)(notifier_notification_block_t *notify, void *data);
+
+/*!
+ * @brief Callback configuration structure
+ *
+ * This structure holds configuration of callbacks.
+ * Callbacks of this type are expected to be statically allocated.
+ * This structure contains following application-defined data:
+ * callback - pointer to the callback function
+ * callbackType - specifies when the callback is called
+ * callbackData - pointer to the data passed to the callback.
+ */
+typedef struct _notifier_callback_config
+{
+ notifier_callback_t callback; /*!< Pointer to the callback function. */
+ notifier_callback_type_t callbackType; /*!< Callback type. */
+ void *callbackData; /*!< Pointer to the data passed to the callback. */
+} notifier_callback_config_t;
+
+/*!
+ * @brief Notifier handle structure.
+ *
+ * Notifier handle structure. Contains data necessary for Notifier proper function.
+ * Stores references to registered configurations, callbacks, information about their numbers,
+ * user function, user data and other internal data.
+ * NOTIFIER_CreateHandle() must be called to initialize this handle.
+ */
+typedef struct _notifier_handle
+{
+ notifier_user_config_t **configsTable; /*!< Pointer to configure table. */
+ uint8_t configsNumber; /*!< Number of configurations. */
+ notifier_callback_config_t *callbacksTable; /*!< Pointer to callback table. */
+ uint8_t callbacksNumber; /*!< Maximum number of callback configurations. */
+ uint8_t errorCallbackIndex; /*!< Index of callback returns error. */
+ uint8_t currentConfigIndex; /*!< Index of current configuration. */
+ notifier_user_function_t userFunction; /*!< user function. */
+ void *userData; /*!< user data passed to user function. */
+} notifier_handle_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif
+
+/*!
+ * @brief Create Notifier handle.
+ *
+ * @param notifierHandle A pointer to notifier handle
+ * @param configs A pointer to an array with references to all configurations which is handled by the Notifier.
+ * @param configsNumber Number of configurations. Size of the configuration array.
+ * @param callbacks A pointer to an array of callback configurations.
+ * If there are no callbacks to register during Notifier initialization, use NULL value.
+ * @param callbacksNumber Number of registered callbacks. Size of callbacks array.
+ * @param userFunction user function.
+ * @param userData user data passed to user function.
+ * @return An error code or kStatus_Success.
+ */
+status_t NOTIFIER_CreateHandle(notifier_handle_t *notifierHandle,
+ notifier_user_config_t **configs,
+ uint8_t configsNumber,
+ notifier_callback_config_t *callbacks,
+ uint8_t callbacksNumber,
+ notifier_user_function_t userFunction,
+ void *userData);
+
+/*!
+ * @brief Switch configuration according to a pre-defined structure.
+ *
+ * This function sets the system to the target configuration. Before transition,
+ * the Notifier sends notifications to all callbacks registered to the callback table.
+ * Callbacks are invoked in the following order: All registered callbacks are notified
+ * ordered by index in the callbacks array. The same order is used for before and after switch notifications.
+ * The notifications before the configuration switch can be used to obtain confirmation about
+ * the change from registered callbacks. If any registered callback denies the
+ * configuration change, further execution of this function depends on the notifier policy: the
+ * configuration change is either forced (kNOTIFIER_PolicyForcible) or exited (kNOTIFIER_PolicyAgreement).
+ * When configuration change is forced, the result of the before switch notifications are ignored. If
+ * agreement is required, if any callback returns an error code then further notifications
+ * before switch notifications are cancelled and all already notified callbacks are re-invoked
+ * The index of the callback which returned error code during pre-switch notifications is stored
+ * (any error codes during callbacks re-invocation are ignored) and NOTIFIER_GetErrorCallback() can be used to get it.
+ * Regardless of the policies, if any callback returned an error code, an error code denoting in which phase
+ * the error occurred is returned when NOTIFIER_SwitchConfig() exits.
+ * @param notifierHandle pointer to notifier handle
+ * @param configIndex Index of the target configuration.
+ * @param policy Transaction policy, kNOTIFIER_PolicyAgreement or kNOTIFIER_PolicyForcible.
+ *
+ * @return An error code or kStatus_Success.
+ *
+ */
+status_t NOTIFIER_SwitchConfig(notifier_handle_t *notifierHandle, uint8_t configIndex, notifier_policy_t policy);
+
+/*!
+ * @brief This function returns the last failed notification callback.
+ *
+ * This function returns index of the last callback that failed during the configuration switch while
+ * the last NOTIFIER_SwitchConfig() was called. If the last NOTIFIER_SwitchConfig() call ended successfully
+ * value equal to callbacks number is returned. Returned value represents index in the array of
+ * static call-backs.
+ *
+ * @param notifierHandle pointer to notifier handle
+ * @return Callback index of last failed callback or value equal to callbacks count.
+ */
+uint8_t NOTIFIER_GetErrorCallbackIndex(notifier_handle_t *notifierHandle);
+
+#if defined(__cplusplus)
+}
+#endif /* __cplusplus */
+
+/*! @}*/
+
+#endif /* _FSL_NOTIFIER_H_ */
diff --git a/utilities/fsl_sbrk.c b/utilities/fsl_sbrk.c
new file mode 100644
index 0000000..aae6b1e
--- /dev/null
+++ b/utilities/fsl_sbrk.c
@@ -0,0 +1,66 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+#if defined(__GNUC__)
+#include <stdio.h>
+#include <errno.h>
+#endif
+
+#if defined(__GNUC__)
+/*!
+ * @brief Function to override ARMGCC default function _sbrk
+ *
+ * _sbrk is called by malloc. ARMGCC default _sbrk compares "SP" register and
+ * heap end, if heap end is larger than "SP", then _sbrk returns error and
+ * memory allocation failed. This function changes to compare __HeapLimit with
+ * heap end.
+ */
+caddr_t _sbrk(int incr)
+{
+ extern char end __asm("end");
+ extern char heap_limit __asm("__HeapLimit");
+ static char *heap_end;
+ char *prev_heap_end;
+
+ if (heap_end == NULL)
+ heap_end = &end;
+
+ prev_heap_end = heap_end;
+
+ if (heap_end + incr > &heap_limit)
+ {
+ errno = ENOMEM;
+ return (caddr_t)-1;
+ }
+
+ heap_end += incr;
+
+ return (caddr_t)prev_heap_end;
+}
+#endif
diff --git a/utilities/fsl_shell.c b/utilities/fsl_shell.c
new file mode 100644
index 0000000..75ce7e8
--- /dev/null
+++ b/utilities/fsl_shell.c
@@ -0,0 +1,621 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ *
+ * POSIX getopt for Windows
+ * Code given out at the 1985 UNIFORUM conference in Dallas.
+ *
+ * From std-unix@ut-sally.UUCP (Moderator, John Quarterman) Sun Nov 3 14:34:15 1985
+ * Relay-Version: version B 2.10.3 4.3bsd-beta 6/6/85; site gatech.CSNET
+ * Posting-Version: version B 2.10.2 9/18/84; site ut-sally.UUCP
+ * Path: gatech!akgua!mhuxv!mhuxt!mhuxr!ulysses!allegra!mit-eddie!genrad!panda!talcott!harvard!seismo!ut-sally!std-unix
+ * From: std-unix@ut-sally.UUCP (Moderator, John Quarterman)
+ * Newsgroups: mod.std.unix
+ * Subject: public domain AT&T getopt source
+ * Message-ID: <3352@ut-sally.UUCP>
+ * Date: 3 Nov 85 19:34:15 GMT
+ * Date-Received: 4 Nov 85 12:25:09 GMT
+ * Organization: IEEE/P1003 Portable Operating System Environment Committee
+ * Lines: 91
+ * Approved: jsq@ut-sally.UUC
+ * Here's something you've all been waiting for: the AT&T public domain
+ * source for getopt(3). It is the code which was given out at the 1985
+ * UNIFORUM conference in Dallas. I obtained it by electronic mail
+ * directly from AT&T. The people there assure me that it is indeed
+ * in the public domain
+ * There is no manual page. That is because the one they gave out at
+ * UNIFORUM was slightly different from the current System V Release 2
+ * manual page. The difference apparently involved a note about the
+ * famous rules 5 and 6, recommending using white space between an option
+ * and its first argument, and not grouping options that have arguments.
+ * Getopt itself is currently lenient about both of these things White
+ * space is allowed, but not mandatory, and the last option in a group can
+ * have an argument. That particular version of the man page evidently
+ * has no official existence, and my source at AT&T did not send a copy.
+ * The current SVR2 man page reflects the actual behavor of this getopt.
+ * However, I am not about to post a copy of anything licensed by AT&T.
+ */
+
+#include <assert.h>
+#include "fsl_shell.h"
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+#define KEY_ESC (0x1BU)
+#define KET_DEL (0x7FU)
+
+/*******************************************************************************
+ * Prototypes
+ ******************************************************************************/
+static int32_t HelpCommand(p_shell_context_t context, int32_t argc, char **argv); /*!< help command */
+
+static int32_t ExitCommand(p_shell_context_t context, int32_t argc, char **argv); /*!< exit command */
+
+static int32_t ParseLine(const char *cmd, uint32_t len, char *argv[SHELL_MAX_ARGS]); /*!< parse line command */
+
+static int32_t StrCompare(const char *str1, const char *str2, int32_t count); /*!< compare string command */
+
+static void ProcessCommand(p_shell_context_t context, const char *cmd); /*!< process a command */
+
+static void GetHistoryCommand(p_shell_context_t context, uint8_t hist_pos); /*!< get commands history */
+
+static void AutoComplete(p_shell_context_t context); /*!< auto complete command */
+
+static uint8_t GetChar(p_shell_context_t context); /*!< get a char from communication interface */
+
+static int32_t StrLen(const char *str); /*!< get string length */
+
+static char *StrCopy(char *dest, const char *src, int32_t count); /*!< string copy */
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+static const shell_command_context_t xHelpCommand = {"help", "\r\n\"help\": Lists all the registered commands\r\n",
+ HelpCommand, 0};
+
+static const shell_command_context_t xExitCommand = {"exit", "\r\n\"exit\": Exit program\r\n", ExitCommand, 0};
+
+static shell_command_context_list_t g_RegisteredCommands;
+
+static char g_paramBuffer[SHELL_BUFFER_SIZE];
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+void SHELL_Init(
+ p_shell_context_t context, send_data_cb_t send_cb, recv_data_cb_t recv_cb, printf_data_t shell_printf, char *prompt)
+{
+ assert(send_cb != NULL);
+ assert(recv_cb != NULL);
+ assert(prompt != NULL);
+ assert(shell_printf != NULL);
+
+ /* Memset for context */
+ memset(context, 0, sizeof(shell_context_struct));
+ context->send_data_func = send_cb;
+ context->recv_data_func = recv_cb;
+ context->printf_data_func = shell_printf;
+ context->prompt = prompt;
+
+ SHELL_RegisterCommand(&xHelpCommand);
+ SHELL_RegisterCommand(&xExitCommand);
+}
+
+int32_t SHELL_Main(p_shell_context_t context)
+{
+ uint8_t ch;
+ int32_t i;
+
+ if (!context)
+ {
+ return -1;
+ }
+
+ context->exit = false;
+ context->printf_data_func("\r\nSHELL (build: %s)\r\n", __DATE__);
+ context->printf_data_func("Copyright (c) 2015 Freescale Semiconductor\r\n");
+ context->printf_data_func(context->prompt);
+
+ while (1)
+ {
+ if (context->exit)
+ {
+ break;
+ }
+ ch = GetChar(context);
+ /* Special key */
+ if (ch == KEY_ESC)
+ {
+ context->stat = kSHELL_Special;
+ continue;
+ }
+ else if (context->stat == kSHELL_Special)
+ {
+ /* Function key */
+ if (ch == '[')
+ {
+ context->stat = kSHELL_Function;
+ continue;
+ }
+ context->stat = kSHELL_Normal;
+ }
+ else if (context->stat == kSHELL_Function)
+ {
+ context->stat = kSHELL_Normal;
+
+ switch ((uint8_t)ch)
+ {
+ /* History operation here */
+ case 'A': /* Up key */
+ GetHistoryCommand(context, context->hist_current);
+ if (context->hist_current < (context->hist_count - 1))
+ {
+ context->hist_current++;
+ }
+ break;
+ case 'B': /* Down key */
+ GetHistoryCommand(context, context->hist_current);
+ if (context->hist_current > 0)
+ {
+ context->hist_current--;
+ }
+ break;
+ case 'D': /* Left key */
+ if (context->c_pos)
+ {
+ context->printf_data_func("\b");
+ context->c_pos--;
+ }
+ break;
+ case 'C': /* Right key */
+ if (context->c_pos < context->l_pos)
+ {
+ context->printf_data_func("%c", context->line[context->c_pos]);
+ context->c_pos++;
+ }
+ break;
+ default:
+ break;
+ }
+ continue;
+ }
+ /* Handle tab key */
+ else if (ch == '\t')
+ {
+#if SHELL_AUTO_COMPLETE
+ /* Move the cursor to the beginning of line */
+ for (i = 0; i < context->c_pos; i++)
+ {
+ context->printf_data_func("\b");
+ }
+ /* Do auto complete */
+ AutoComplete(context);
+ /* Move position to end */
+ context->c_pos = context->l_pos = StrLen(context->line);
+#endif
+ continue;
+ }
+#if SHELL_SEARCH_IN_HIST
+ /* Search command in history */
+ else if ((ch == '`') && (context->l_pos == 0) && (context->line[0] == 0x00))
+ {
+ }
+#endif
+ /* Handle backspace key */
+ else if ((ch == KET_DEL) || (ch == '\b'))
+ {
+ /* There must be at last one char */
+ if (context->c_pos == 0)
+ {
+ continue;
+ }
+
+ context->l_pos--;
+ context->c_pos--;
+
+ if (context->l_pos > context->c_pos)
+ {
+ memmove(&context->line[context->c_pos], &context->line[context->c_pos + 1],
+ context->l_pos - context->c_pos);
+ context->line[context->l_pos] = 0;
+ context->printf_data_func("\b%s \b", &context->line[context->c_pos]);
+
+ /* Reset position */
+ for (i = context->c_pos; i <= context->l_pos; i++)
+ {
+ context->printf_data_func("\b");
+ }
+ }
+ else /* Normal backspace operation */
+ {
+ context->printf_data_func("\b \b");
+ context->line[context->l_pos] = 0;
+ }
+ continue;
+ }
+ else
+ {
+ }
+
+ /* Input too long */
+ if (context->l_pos >= (SHELL_BUFFER_SIZE - 1))
+ {
+ context->l_pos = 0;
+ }
+
+ /* Handle end of line, break */
+ if ((ch == '\r') || (ch == '\n'))
+ {
+ context->printf_data_func("\r\n");
+ ProcessCommand(context, context->line);
+ /* Reset all params */
+ context->c_pos = context->l_pos = 0;
+ context->hist_current = 0;
+ context->printf_data_func(context->prompt);
+ memset(context->line, 0, sizeof(context->line));
+ continue;
+ }
+
+ /* Normal character */
+ if (context->c_pos < context->l_pos)
+ {
+ memmove(&context->line[context->c_pos + 1], &context->line[context->c_pos],
+ context->l_pos - context->c_pos);
+ context->line[context->c_pos] = ch;
+ context->printf_data_func("%s", &context->line[context->c_pos]);
+ /* Move the cursor to new position */
+ for (i = context->c_pos; i < context->l_pos; i++)
+ {
+ context->printf_data_func("\b");
+ }
+ }
+ else
+ {
+ context->line[context->l_pos] = ch;
+ context->printf_data_func("%c", ch);
+ }
+
+ ch = 0;
+ context->l_pos++;
+ context->c_pos++;
+ }
+ return 0;
+}
+
+static int32_t HelpCommand(p_shell_context_t context, int32_t argc, char **argv)
+{
+ uint8_t i = 0;
+
+ for (i = 0; i < g_RegisteredCommands.numberOfCommandInList; i++)
+ {
+ context->printf_data_func(g_RegisteredCommands.CommandList[i]->pcHelpString);
+ }
+ return 0;
+}
+
+static int32_t ExitCommand(p_shell_context_t context, int32_t argc, char **argv)
+{
+ /* Skip warning */
+ context->printf_data_func("\r\nSHELL exited\r\n");
+ context->exit = true;
+ return 0;
+}
+
+static void ProcessCommand(p_shell_context_t context, const char *cmd)
+{
+ static const shell_command_context_t *tmpCommand = NULL;
+ static const char *tmpCommandString;
+ int32_t argc;
+ char *argv[SHELL_BUFFER_SIZE];
+ uint8_t flag = 1;
+ uint8_t tmpCommandLen;
+ uint8_t tmpLen;
+ uint8_t i = 0;
+
+ tmpLen = StrLen(cmd);
+ argc = ParseLine(cmd, tmpLen, argv);
+
+ if ((tmpCommand == NULL) && (argc > 0))
+ {
+ for (i = 0; i < g_RegisteredCommands.numberOfCommandInList; i++)
+ {
+ tmpCommand = g_RegisteredCommands.CommandList[i];
+ tmpCommandString = tmpCommand->pcCommand;
+ tmpCommandLen = StrLen(tmpCommandString);
+ /* Compare with space or end of string */
+ if ((cmd[tmpCommandLen] == ' ') || (cmd[tmpCommandLen] == 0x00))
+ {
+ if (StrCompare(tmpCommandString, argv[0], tmpCommandLen) == 0)
+ {
+ if ((tmpCommand->cExpectedNumberOfParameters == 0) && (argc == 1))
+ {
+ flag = 0;
+ }
+ else if (tmpCommand->cExpectedNumberOfParameters > 0)
+ {
+ if ((argc - 1) == tmpCommand->cExpectedNumberOfParameters)
+ {
+ flag = 0;
+ }
+ }
+ else
+ {
+ flag = 1;
+ }
+ break;
+ }
+ }
+ }
+ }
+
+ if ((tmpCommand != NULL) && (flag == 1U))
+ {
+ context->printf_data_func(
+ "\r\nIncorrect command parameter(s). Enter \"help\" to view a list of available commands.\r\n\r\n");
+ tmpCommand = NULL;
+ }
+ else if (tmpCommand != NULL)
+ {
+ tmpLen = StrLen(cmd);
+ /* Compare with last command. Push back to history buffer if different */
+ if (tmpLen != StrCompare(cmd, context->hist_buf[0], StrLen(cmd)))
+ {
+ for (i = SHELL_HIST_MAX - 1; i > 0; i--)
+ {
+ memset(context->hist_buf[i], '\0', SHELL_BUFFER_SIZE);
+ tmpLen = StrLen(context->hist_buf[i - 1]);
+ StrCopy(context->hist_buf[i], context->hist_buf[i - 1], tmpLen);
+ }
+ memset(context->hist_buf[0], '\0', SHELL_BUFFER_SIZE);
+ tmpLen = StrLen(cmd);
+ StrCopy(context->hist_buf[0], cmd, tmpLen);
+ if (context->hist_count < SHELL_HIST_MAX)
+ {
+ context->hist_count++;
+ }
+ }
+ tmpCommand->pFuncCallBack(context, argc, argv);
+ tmpCommand = NULL;
+ }
+ else
+ {
+ context->printf_data_func(
+ "\r\nCommand not recognised. Enter 'help' to view a list of available commands.\r\n\r\n");
+ tmpCommand = NULL;
+ }
+}
+
+static void GetHistoryCommand(p_shell_context_t context, uint8_t hist_pos)
+{
+ uint8_t i;
+ uint32_t tmp;
+
+ if (context->hist_buf[0][0] == '\0')
+ {
+ context->hist_current = 0;
+ return;
+ }
+ if (hist_pos > SHELL_HIST_MAX)
+ {
+ hist_pos = SHELL_HIST_MAX - 1;
+ }
+ tmp = StrLen(context->line);
+ /* Clear current if have */
+ if (tmp > 0)
+ {
+ memset(context->line, '\0', tmp);
+ for (i = 0; i < tmp; i++)
+ {
+ context->printf_data_func("\b \b");
+ }
+ }
+
+ context->l_pos = StrLen(context->hist_buf[hist_pos]);
+ context->c_pos = context->l_pos;
+ StrCopy(context->line, context->hist_buf[hist_pos], context->l_pos);
+ context->printf_data_func(context->hist_buf[hist_pos]);
+}
+
+static void AutoComplete(p_shell_context_t context)
+{
+ int32_t len;
+ int32_t minLen;
+ uint8_t i = 0;
+ const shell_command_context_t *tmpCommand = NULL;
+ const char *namePtr;
+ const char *cmdName;
+
+ minLen = 0;
+ namePtr = NULL;
+
+ if (!StrLen(context->line))
+ {
+ return;
+ }
+ context->printf_data_func("\r\n");
+ /* Empty tab, list all commands */
+ if (context->line[0] == '\0')
+ {
+ HelpCommand(context, 0, NULL);
+ return;
+ }
+ /* Do auto complete */
+ for (i = 0; i < g_RegisteredCommands.numberOfCommandInList; i++)
+ {
+ tmpCommand = g_RegisteredCommands.CommandList[i];
+ cmdName = tmpCommand->pcCommand;
+ if (StrCompare(context->line, cmdName, StrLen(context->line)) == 0)
+ {
+ if (minLen == 0)
+ {
+ namePtr = cmdName;
+ minLen = StrLen(namePtr);
+ /* Show possible matches */
+ context->printf_data_func("%s\r\n", cmdName);
+ continue;
+ }
+ len = StrCompare(namePtr, cmdName, StrLen(namePtr));
+ if (len < 0)
+ {
+ len = len * (-1);
+ }
+ if (len < minLen)
+ {
+ minLen = len;
+ }
+ }
+ }
+ /* Auto complete string */
+ if (namePtr)
+ {
+ StrCopy(context->line, namePtr, minLen);
+ }
+ context->printf_data_func("%s%s", context->prompt, context->line);
+ return;
+}
+
+static char *StrCopy(char *dest, const char *src, int32_t count)
+{
+ char *ret = dest;
+ int32_t i = 0;
+
+ for (i = 0; i < count; i++)
+ {
+ dest[i] = src[i];
+ }
+
+ return ret;
+}
+
+static int32_t StrLen(const char *str)
+{
+ int32_t i = 0;
+
+ while (*str)
+ {
+ str++;
+ i++;
+ }
+ return i;
+}
+
+static int32_t StrCompare(const char *str1, const char *str2, int32_t count)
+{
+ while (count--)
+ {
+ if (*str1++ != *str2++)
+ {
+ return *(unsigned char *)(str1 - 1) - *(unsigned char *)(str2 - 1);
+ }
+ }
+ return 0;
+}
+
+static int32_t ParseLine(const char *cmd, uint32_t len, char *argv[SHELL_MAX_ARGS])
+{
+ uint32_t argc;
+ char *p;
+ uint32_t position;
+
+ /* Init params */
+ memset(g_paramBuffer, '\0', len + 1);
+ StrCopy(g_paramBuffer, cmd, len);
+
+ p = g_paramBuffer;
+ position = 0;
+ argc = 0;
+
+ while (position < len)
+ {
+ /* Skip all blanks */
+ while (((char)(*p) == ' ') && (position < len))
+ {
+ *p = '\0';
+ p++;
+ position++;
+ }
+ /* Process begin of a string */
+ if (*p == '"')
+ {
+ p++;
+ position++;
+ argv[argc] = p;
+ argc++;
+ /* Skip this string */
+ while ((*p != '"') && (position < len))
+ {
+ p++;
+ position++;
+ }
+ /* Skip '"' */
+ *p = '\0';
+ p++;
+ position++;
+ }
+ else /* Normal char */
+ {
+ argv[argc] = p;
+ argc++;
+ while (((char)*p != ' ') && ((char)*p != '\t') && (position < len))
+ {
+ p++;
+ position++;
+ }
+ }
+ }
+ return argc;
+}
+
+int32_t SHELL_RegisterCommand(const shell_command_context_t *command_context)
+{
+ int32_t result = 0;
+
+ /* If have room in command list */
+ if (g_RegisteredCommands.numberOfCommandInList < SHELL_MAX_CMD)
+ {
+ g_RegisteredCommands.CommandList[g_RegisteredCommands.numberOfCommandInList++] = command_context;
+ }
+ else
+ {
+ result = -1;
+ }
+ return result;
+}
+
+static uint8_t GetChar(p_shell_context_t context)
+{
+ uint8_t ch;
+
+#if SHELL_USE_FILE_STREAM
+ ch = fgetc(context->STDIN);
+#else
+ context->recv_data_func(&ch, 1U);
+#endif
+ return ch;
+}
diff --git a/utilities/fsl_shell.h b/utilities/fsl_shell.h
new file mode 100644
index 0000000..c1472d9
--- /dev/null
+++ b/utilities/fsl_shell.h
@@ -0,0 +1,204 @@
+/*
+ * Copyright (c) 2015, Freescale Semiconductor, Inc.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without modification,
+ * are permitted provided that the following conditions are met:
+ *
+ * o Redistributions of source code must retain the above copyright notice, this list
+ * of conditions and the following disclaimer.
+ *
+ * o Redistributions in binary form must reproduce the above copyright notice, this
+ * list of conditions and the following disclaimer in the documentation and/or
+ * other materials provided with the distribution.
+ *
+ * o Neither the name of Freescale Semiconductor, Inc. nor the names of its
+ * contributors may be used to endorse or promote products derived from this
+ * software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
+ * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
+ * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
+ * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
+ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef _FSL_SHELL_H_
+#define _FSL_SHELL_H_
+
+#include "fsl_common.h"
+
+/*!
+ * @addtogroup SHELL
+ * @{
+ */
+
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+/*! @brief Macro to set on/off history feature. */
+#ifndef SHELL_USE_HISTORY
+#define SHELL_USE_HISTORY (0U)
+#endif
+
+/*! @brief Macro to set on/off history feature. */
+#ifndef SHELL_SEARCH_IN_HIST
+#define SHELL_SEARCH_IN_HIST (1U)
+#endif
+
+/*! @brief Macro to select method stream. */
+#ifndef SHELL_USE_FILE_STREAM
+#define SHELL_USE_FILE_STREAM (0U)
+#endif
+
+/*! @brief Macro to set on/off auto-complete feature. */
+#ifndef SHELL_AUTO_COMPLETE
+#define SHELL_AUTO_COMPLETE (1U)
+#endif
+
+/*! @brief Macro to set console buffer size. */
+#ifndef SHELL_BUFFER_SIZE
+#define SHELL_BUFFER_SIZE (64U)
+#endif
+
+/*! @brief Macro to set maximum arguments in command. */
+#ifndef SHELL_MAX_ARGS
+#define SHELL_MAX_ARGS (8U)
+#endif
+
+/*! @brief Macro to set maximum count of history commands. */
+#ifndef SHELL_HIST_MAX
+#define SHELL_HIST_MAX (3U)
+#endif
+
+/*! @brief Macro to set maximum count of commands. */
+#ifndef SHELL_MAX_CMD
+#define SHELL_MAX_CMD (6U)
+#endif
+
+/*! @brief Shell user send data callback prototype.*/
+typedef void (*send_data_cb_t)(uint8_t *buf, uint32_t len);
+
+/*! @brief Shell user receiver data callback prototype.*/
+typedef void (*recv_data_cb_t)(uint8_t *buf, uint32_t len);
+
+/*! @brief Shell user printf data prototype.*/
+typedef int (*printf_data_t)(const char *format, ...);
+
+/*! @brief A type for the handle special key. */
+typedef enum _fun_key_status
+{
+ kSHELL_Normal = 0U, /*!< Normal key */
+ kSHELL_Special = 1U, /*!< Special key */
+ kSHELL_Function = 2U, /*!< Function key */
+} fun_key_status_t;
+
+/*! @brief Data structure for Shell environment. */
+typedef struct _shell_context_struct
+{
+ char *prompt; /*!< Prompt string */
+ enum _fun_key_status stat; /*!< Special key status */
+ char line[SHELL_BUFFER_SIZE]; /*!< Consult buffer */
+ uint8_t cmd_num; /*!< Number of user commands */
+ uint8_t l_pos; /*!< Total line position */
+ uint8_t c_pos; /*!< Current line position */
+#if SHELL_USE_FILE_STREAM
+ FILE *STDOUT, *STDIN, *STDERR;
+#else
+ send_data_cb_t send_data_func; /*!< Send data interface operation */
+ recv_data_cb_t recv_data_func; /*!< Receive data interface operation */
+ printf_data_t printf_data_func;
+#endif
+ uint16_t hist_current; /*!< Current history command in hist buff*/
+ uint16_t hist_count; /*!< Total history command in hist buff*/
+ char hist_buf[SHELL_HIST_MAX][SHELL_BUFFER_SIZE]; /*!< History buffer*/
+ bool exit; /*!< Exit Flag*/
+} shell_context_struct, *p_shell_context_t;
+
+/*! @brief User command function prototype. */
+typedef int32_t (*cmd_function_t)(p_shell_context_t context, int32_t argc, char **argv);
+
+/*! @brief User command data structure. */
+typedef struct _shell_command_context
+{
+ const char *pcCommand; /*!< The command that is executed. For example "help". It must be all lower case. */
+ char *pcHelpString; /*!< String that describes how to use the command. It should start with the command itself,
+ and end with "\r\n". For example "help: Returns a list of all the commands\r\n". */
+ const cmd_function_t
+ pFuncCallBack; /*!< A pointer to the callback function that returns the output generated by the command. */
+ uint8_t cExpectedNumberOfParameters; /*!< Commands expect a fixed number of parameters, which may be zero. */
+} shell_command_context_t;
+
+/*! @brief Structure list command. */
+typedef struct _shell_command_context_list
+{
+ const shell_command_context_t *CommandList[SHELL_MAX_CMD]; /*!< The command table list */
+ uint8_t numberOfCommandInList; /*!< The total command in list */
+} shell_command_context_list_t;
+
+/*******************************************************************************
+ * API
+ ******************************************************************************/
+
+#if defined(__cplusplus)
+extern "C" {
+#endif /* _cplusplus */
+
+/*!
+ * @name Shell functional Operation
+ * @{
+ */
+
+/*!
+* @brief Enables the clock gate and configure the Shell module according to the configuration structure.
+*
+* This function must be called before calling all other Shell functions.
+* Call operation the Shell commands with user-defined settings.
+* The example below shows how to set up the middleware Shell and
+* how to call the SHELL_Init function by passing in these parameters:
+* Example:
+* @code
+* shell_context_struct user_context;
+* SHELL_Init(&user_context, SendDataFunc, ReceiveDataFunc, "SHELL>> ");
+* @endcode
+* @param context The pointer to the Shell environment and runtime states.
+* @param send_cb The pointer to call back send data function.
+* @param recv_cb The pointer to call back receive data function.
+* @param prompt The string prompt of Shell
+*/
+void SHELL_Init(p_shell_context_t context,
+ send_data_cb_t send_cb,
+ recv_data_cb_t recv_cb,
+ printf_data_t shell_printf,
+ char *prompt);
+
+/*!
+ * @brief Shell register command.
+ * @param command_context The pointer to the command data structure.
+ * @return -1 if error or 0 if success
+ */
+int32_t SHELL_RegisterCommand(const shell_command_context_t *command_context);
+
+/*!
+ * @brief Main loop for Shell.
+ * Main loop for Shell; After this function is called, Shell begins to initialize the basic variables and starts to
+ * work.
+ * @param context The pointer to the Shell environment and runtime states.
+ * @return this function does not return until Shell command exit was called.
+ */
+int32_t SHELL_Main(p_shell_context_t context);
+
+/* @} */
+
+#if defined(__cplusplus)
+}
+#endif
+
+/*! @}*/
+
+#endif /* _FSL_SHELL_H_ */