]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS/Demo/RISC-V_RV32M1_Vega_GCC_Eclipse/common/rv32m1_sdk_riscv/devices/RV32M1/utilities/fsl_log.c
Move the 'generic' version of freertos_risc_v_chip_specific_extensions.h back to...
[freertos] / FreeRTOS / Demo / RISC-V_RV32M1_Vega_GCC_Eclipse / common / rv32m1_sdk_riscv / devices / RV32M1 / utilities / fsl_log.c
diff --git a/FreeRTOS/Demo/RISC-V_RV32M1_Vega_GCC_Eclipse/common/rv32m1_sdk_riscv/devices/RV32M1/utilities/fsl_log.c b/FreeRTOS/Demo/RISC-V_RV32M1_Vega_GCC_Eclipse/common/rv32m1_sdk_riscv/devices/RV32M1/utilities/fsl_log.c
new file mode 100644 (file)
index 0000000..4dd3caa
--- /dev/null
@@ -0,0 +1,547 @@
+/*
+ * Copyright 2017 NXP
+ * All rights reserved.
+ *
+ * 
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ */
+#include "fsl_log.h"
+#include "fsl_debug_console_conf.h"
+#include "fsl_io.h"
+#ifdef FSL_RTOS_FREE_RTOS
+#include "FreeRTOS.h"
+#include "task.h"
+#include "semphr.h"
+#endif
+/*******************************************************************************
+ * Definitions
+ ******************************************************************************/
+#ifndef BACKSPACE
+/*! @brief character backspace ASCII value */
+#define BACKSPACE 127
+#endif
+
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+/*! @brief increase pop member */
+#define LOG_CHECK_BUFFER_INDEX_OVERFLOW(index)          \
+    {                                                   \
+        if (index >= DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN) \
+        {                                               \
+            index -= DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN; \
+        }                                               \
+    \
+\
+}
+
+/*! @brief get current runing environment is ISR or not */
+#ifdef __CA7_REV
+#define IS_RUNNING_IN_ISR() SystemGetIRQNestingLevel()
+#else
+#define IS_RUNNING_IN_ISR() __get_IPSR()
+#endif /* __CA7_REV */
+
+#else
+#define IS_RUNNING_IN_ISR() (0U)
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+/* define for rtos */
+#if (DEBUG_CONSOLE_SYNCHRONIZATION_MODE == DEBUG_CONSOLE_SYNCHRONIZATION_FREERTOS)
+/* metex semaphore */
+#define LOG_CREATE_MUTEX_SEMAPHORE(mutex) (mutex = xSemaphoreCreateMutex())
+
+#define LOG_GIVE_MUTEX_SEMAPHORE(mutex) \
+    \
+{                                \
+        if (IS_RUNNING_IN_ISR() == 0U)  \
+        {                               \
+            xSemaphoreGive(mutex);      \
+        }                               \
+    \
+}
+
+#define LOG_TAKE_MUTEX_SEMAPHORE_BLOCKING(mutex)  \
+    \
+{                                          \
+        if (IS_RUNNING_IN_ISR() == 0U)            \
+        {                                         \
+            xSemaphoreTake(mutex, portMAX_DELAY); \
+        }                                         \
+    \
+}
+
+#define LOG_TAKE_MUTEX_SEMAPHORE_NONBLOCKING(mutex, result) \
+    \
+{                                                    \
+        if (IS_RUNNING_IN_ISR() == 0U)                      \
+        {                                                   \
+            result = xSemaphoreTake(mutex, 0U);             \
+        }                                                   \
+        else                                                \
+        {                                                   \
+            result = 1U;                                    \
+        }                                                   \
+    \
+}
+
+/* Binary semaphore */
+#define LOG_CREATE_BINARY_SEMAPHORE(binary) (binary = xSemaphoreCreateBinary())
+#define LOG_TAKE_BINARY_SEMAPHORE_BLOCKING(binary) (xSemaphoreTake(binary, portMAX_DELAY))
+#define LOG_GIVE_BINARY_SEMAPHORE_FROM_ISR(binary) (xSemaphoreGiveFromISR(binary, NULL))
+
+#elif(DEBUG_CONSOLE_SYNCHRONIZATION_MODE == DEBUG_CONSOLE_SYNCHRONIZATION_BM)
+
+#define LOG_CREATE_MUTEX_SEMAPHORE(mutex)
+#define LOG_TAKE_MUTEX_SEMAPHORE_BLOCKING(mutex)
+#define LOG_GIVE_MUTEX_SEMAPHORE(mutex)
+#define LOG_CREATE_BINARY_SEMAPHORE(binary)
+#define LOG_TAKE_MUTEX_SEMAPHORE_NONBLOCKING(mutex, result) (result = 1U)
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+#define LOG_TAKE_BINARY_SEMAPHORE_BLOCKING(binary) \
+    \
+{                                           \
+        while (!binary)                            \
+            ;                                      \
+        binary = false;                            \
+    \
+\
+}
+#define LOG_GIVE_BINARY_SEMAPHORE_FROM_ISR(binary) (binary = true)
+#else
+#define LOG_TAKE_BINARY_SEMAPHORE_BLOCKING(binary)
+#define LOG_GIVE_BINARY_SEMAPHORE_FROM_ISR(binary)
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+/* add other implementation here
+*such as :
+* #elif(DEBUG_CONSOLE_SYNCHRONIZATION_MODE == DEBUG_CONSOLE_SYNCHRONIZATION_xxx)
+*/
+
+#else
+
+#define LOG_CREATE_MUTEX_SEMAPHORE(mutex)
+#define LOG_TAKE_MUTEX_SEMAPHORE_BLOCKING(mutex)
+#define LOG_TAKE_MUTEX_SEMAPHORE_NONBLOCKING(mutex, result) (result = 1U)
+#define LOG_GIVE_MUTEX_SEMAPHORE(mutex)
+#define LOG_CREATE_BINARY_SEMAPHORE(binary)
+#define LOG_TAKE_BINARY_SEMAPHORE_BLOCKING(binary)
+#define LOG_GIVE_BINARY_SEMAPHORE(binary)
+#endif /* DEBUG_CONSOLE_SYNCHRONIZATION_MODE == DEBUG_CONSOLE_SYNCHRONIZATION_FREERTOS */
+
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+/*! @brief Define the buffer
+* The total buffer size should be calucate as (BUFFER_SUPPORT_LOG_LENGTH + 1) * BUFFER_SUPPORT_LOG_NUM * 4
+*/
+typedef struct _log_buffer
+{
+    volatile uint16_t totalIndex;                     /*!< indicate the total usage of the buffer */
+    volatile uint16_t pushIndex;                      /*!< indicate the next push index */
+    volatile uint16_t popIndex;                       /*!< indicate the pop index */
+    uint8_t txBuf[DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN]; /*!< buffer to store printf log */
+
+    uint8_t rxBuf[DEBUG_CONSOLE_RECEIVE_BUFFER_LEN]; /*!< buffer to store scanf log */
+} log_buffer_t;
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+/*******************************************************************************
+ * Variables
+ ******************************************************************************/
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+/* A global log buffer */
+static log_buffer_t s_log_buffer;
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+/* lock definition */
+#if (DEBUG_CONSOLE_SYNCHRONIZATION_MODE == DEBUG_CONSOLE_SYNCHRONIZATION_FREERTOS)
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+static SemaphoreHandle_t s_logPushSemaphore = NULL;
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+static SemaphoreHandle_t s_logPopSemaphore = NULL;
+static SemaphoreHandle_t s_logReadSemaphore = NULL;
+
+#elif(DEBUG_CONSOLE_SYNCHRONIZATION_MODE == DEBUG_CONSOLE_SYNCHRONIZATION_BM)
+
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+
+static volatile bool s_logReadSemaphore = false; /* transferred event from ISR for bare-metal + interrupt */
+
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+#else
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+/*******************************************************************************
+* Prototypes
+******************************************************************************/
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+/*!
+ * @brief callback function for IO layer to notify LOG
+ *
+ * @param size last transfer data size
+ * @param receive indicate a RX transfer
+ * @param transmit indicate a TX transfer
+ *
+ */
+static void LOG_Transferred(size_t *size, bool receive, bool transmit);
+
+/*!
+ * @brief log push function
+ *
+ * @param buf target buffer
+ * @param size log size
+ *
+ */
+static int LOG_BufPush(uint8_t *buf, size_t size);
+
+/*!
+ * @brief Get next avaliable log
+ *
+ * @param next avaliable size
+ * @return next avaliable address
+ */
+static uint8_t *LOG_BufGetNextAvaliableLog(size_t *size);
+
+/*!
+ * @brief buf pop
+ *
+ * @param size log size popped and next available log size
+ * @return next avaliable address
+ */
+static uint8_t *LOG_BufPop(size_t *size);
+
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+/*!
+ * @brief read one character
+ *
+ * @param ch character address
+ * @return indicate the read status
+ *
+ */
+static status_t LOG_ReadOneCharacter(uint8_t *ch);
+
+#if DEBUG_CONSOLE_ENABLE_ECHO_FUNCTION
+/*!
+ * @brief echo one character
+ *
+ * @param ch character address
+ * @param isGetchar flag to distinguish getchar from scanf
+ * @param index special for scanf to support backspace
+ * @return indicate the read status
+ *
+ */
+static status_t LOG_EchoCharacter(uint8_t *ch, bool isGetChar, int *index);
+#endif
+
+/*******************************************************************************
+ * Code
+ ******************************************************************************/
+status_t LOG_Init(uint32_t baseAddr, uint8_t device, uint32_t baudRate, uint32_t clkSrcFreq)
+{
+    io_state_t io;
+    /* init io */
+    io.ioBase = (void *)baseAddr;
+    io.ioType = device;
+
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+    /* memset the global queue */
+    memset(&s_log_buffer, 0U, sizeof(s_log_buffer));
+    /* init callback for NON-BLOCKING */
+    io.callBack = LOG_Transferred;
+    /* io init function */
+    IO_Init(&io, baudRate, clkSrcFreq, s_log_buffer.rxBuf);
+    /* Debug console buffer push lock create */
+    LOG_CREATE_MUTEX_SEMAPHORE(s_logPushSemaphore);
+#else
+    IO_Init(&io, baudRate, clkSrcFreq, NULL);
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+
+    /* Debug console lock create */
+    LOG_CREATE_MUTEX_SEMAPHORE(s_logPopSemaphore);
+    LOG_CREATE_BINARY_SEMAPHORE(s_logReadSemaphore);
+
+    return kStatus_Success;
+}
+
+void LOG_Deinit(void)
+{
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+    /* memset the global queue */
+    memset(&s_log_buffer, 0U, sizeof(s_log_buffer));
+#endif /*DEBUG_CONSOLE_TRANSFER_NON_BLOCKING*/
+    /* Deinit IO */
+    IO_Deinit();
+}
+
+status_t LOG_WaitIdle(void)
+{
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+    /* wait buffer empty */
+    while (!(s_log_buffer.totalIndex == 0U))
+        ;
+#endif /*DEBUG_CONSOLE_TRANSFER_NON_BLOCKING*/
+    /* wait IO idle */
+    IO_WaitIdle();
+
+    return kStatus_Success;
+}
+
+int LOG_Push(uint8_t *buf, size_t size)
+{
+    assert(buf != NULL);
+
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+    /* push to buffer */
+    LOG_BufPush(buf, size);
+    buf = LOG_BufGetNextAvaliableLog(&size);
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */
+    /* pop log */
+    return LOG_Pop(buf, size);
+}
+
+int LOG_Pop(uint8_t *buf, size_t size)
+{
+    uint8_t getLock = 0U;
+
+    if ((0 != size) && (NULL != buf))
+    {
+        /* take POP lock, should be non-blocking */
+        LOG_TAKE_MUTEX_SEMAPHORE_NONBLOCKING(s_logPopSemaphore, getLock);
+
+        if (getLock)
+        {
+            /* call IO transfer function */
+            if (IO_Transfer(buf, size, true) != kStatus_Success)
+            {
+                size = 0U;
+            }
+            /* release POP lock */
+            LOG_GIVE_MUTEX_SEMAPHORE(s_logPopSemaphore);
+        }
+    }
+
+    return size;
+}
+
+int LOG_ReadLine(uint8_t *buf, size_t size)
+{
+    assert(buf != NULL);
+
+    int i = 0;
+
+    /* take mutex lock function */
+    LOG_TAKE_MUTEX_SEMAPHORE_BLOCKING(s_logPushSemaphore);
+
+    for (i = 0; i < size; i++)
+    {
+        /* recieve one char every time */
+        if (LOG_ReadOneCharacter(&buf[i]) != kStatus_Success)
+        {
+            return -1;
+        }
+#if DEBUG_CONSOLE_ENABLE_ECHO_FUNCTION
+        LOG_EchoCharacter(&buf[i], false, &i);
+#endif
+        /* analysis data */
+        if ((buf[i] == '\r') || (buf[i] == '\n'))
+        {
+            /* End of Line. */
+            if (i == 0)
+            {
+                buf[i] = '\0';
+                i = -1;
+            }
+            else
+            {
+                break;
+            }
+        }
+    }
+    /* get char should not add '\0'*/
+    if (i == size)
+    {
+        buf[i] = '\0';
+    }
+    else
+    {
+        buf[i + 1] = '\0';
+    }
+
+    /* release mutex lock function */
+    LOG_GIVE_MUTEX_SEMAPHORE(s_logPushSemaphore);
+
+    return i;
+}
+
+int LOG_ReadCharacter(uint8_t *ch)
+{
+    assert(ch != NULL);
+    int ret = 0;
+
+    /* take mutex lock function */
+    LOG_TAKE_MUTEX_SEMAPHORE_BLOCKING(s_logPushSemaphore);
+    /* read one character */
+    if (LOG_ReadOneCharacter(ch) == kStatus_Success)
+    {
+        ret = 1;
+#if DEBUG_CONSOLE_ENABLE_ECHO_FUNCTION
+        LOG_EchoCharacter(ch, true, NULL);
+#endif
+    }
+    else
+    {
+        ret = -1;
+    }
+    /* release mutex lock function */
+    LOG_GIVE_MUTEX_SEMAPHORE(s_logPushSemaphore);
+
+    return ret;
+}
+
+static status_t LOG_ReadOneCharacter(uint8_t *ch)
+{
+    /* recieve one char every time */
+    if (IO_Transfer(ch, 1U, false) != kStatus_Success)
+    {
+        return kStatus_Fail;
+    }
+
+    /* wait release from ISR */
+    LOG_TAKE_BINARY_SEMAPHORE_BLOCKING(s_logReadSemaphore);
+
+    return kStatus_Success;
+}
+
+#if DEBUG_CONSOLE_ENABLE_ECHO_FUNCTION
+static status_t LOG_EchoCharacter(uint8_t *ch, bool isGetChar, int *index)
+{
+    /* Due to scanf take \n and \r as end of string,should not echo */
+    if (((*ch != '\r') && (*ch != '\n')) || (isGetChar))
+    {
+        /* recieve one char every time */
+        if (IO_Transfer(ch, 1U, true) != kStatus_Success)
+        {
+            return kStatus_Fail;
+        }
+    }
+
+    if (!isGetChar)
+    {
+        if ((*index > 0) && (*ch == BACKSPACE))
+        {
+            *index -= 2;
+        }
+    }
+
+    return kStatus_Success;
+}
+#endif
+
+#ifdef DEBUG_CONSOLE_TRANSFER_NON_BLOCKING
+static int LOG_BufPush(uint8_t *buf, size_t size)
+{
+    uint32_t pushIndex = 0U, i = 0U;
+    bool pushAvaliable = false;
+
+    /* take mutex lock function */
+    LOG_TAKE_MUTEX_SEMAPHORE_BLOCKING(s_logPushSemaphore);
+    if (size <= (DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN - s_log_buffer.totalIndex))
+    {
+        /* get push index */
+        pushIndex = s_log_buffer.pushIndex;
+        s_log_buffer.pushIndex += size;
+        /* check index overflow */
+        LOG_CHECK_BUFFER_INDEX_OVERFLOW(s_log_buffer.pushIndex);
+        /* update push/total index value */
+        s_log_buffer.totalIndex += size;
+        pushAvaliable = true;
+    }
+    /* release mutex lock function */
+    LOG_GIVE_MUTEX_SEMAPHORE(s_logPushSemaphore);
+
+    /* check the buffer if have enough space to store the log */
+    if (pushAvaliable)
+    {
+        for (i = size; i > 0; i--)
+        {
+            /* copy log to buffer, the buffer only support a fixed length argument, if the log argument
+            is longer than the fixed length, the left argument will be losed */
+            s_log_buffer.txBuf[pushIndex] = *buf++;
+            /* increase index */
+            pushIndex++;
+            /* check index overflow */
+            LOG_CHECK_BUFFER_INDEX_OVERFLOW(pushIndex);
+        }
+    }
+    else
+    {
+        size = 0U;
+    }
+
+    return size;
+}
+
+static uint8_t *LOG_BufGetNextAvaliableLog(size_t *size)
+{
+    uint16_t popIndex = s_log_buffer.popIndex;
+
+    /* get avaliable size */
+    if (s_log_buffer.totalIndex > (DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN - popIndex))
+    {
+        *size = (DEBUG_CONSOLE_TRANSMIT_BUFFER_LEN - popIndex);
+    }
+    else
+    {
+        *size = s_log_buffer.totalIndex;
+    }
+
+    /* return address */
+    return (&(s_log_buffer.txBuf[popIndex]));
+}
+
+static uint8_t *LOG_BufPop(size_t *size)
+{
+    if (s_log_buffer.totalIndex >= *size)
+    {
+        /* decrease the log total member */
+        s_log_buffer.totalIndex -= *size;
+        /* there is more log in the queue to be pushed */
+        if (s_log_buffer.totalIndex > 0U)
+        {
+            /* update the pop index */
+            s_log_buffer.popIndex += *size;
+            /* check index overflow */
+            LOG_CHECK_BUFFER_INDEX_OVERFLOW(s_log_buffer.popIndex);
+
+            return LOG_BufGetNextAvaliableLog(size);
+        }
+        else
+        {
+            /* reset push and pop */
+            s_log_buffer.popIndex = 0U;
+            s_log_buffer.pushIndex = 0U;
+            *size = 0U;
+        }
+    }
+
+    return NULL;
+}
+
+static void LOG_Transferred(size_t *size, bool receive, bool transmit)
+{
+    uint8_t *addr = NULL;
+
+    if (transmit)
+    {
+        addr = LOG_BufPop(size);
+        /* continue pop log from buffer */
+        LOG_Pop(addr, *size);
+    }
+
+    if (receive)
+    {
+        /* release from ISR */
+        LOG_GIVE_BINARY_SEMAPHORE_FROM_ISR(s_logReadSemaphore);
+    }
+}
+#endif /* DEBUG_CONSOLE_TRANSFER_NON_BLOCKING */