move components to SDK dir

This commit is contained in:
Shuanglei Tao
2025-03-03 09:06:26 +08:00
parent 20d1297e57
commit f4f4c9e60d
1021 changed files with 58 additions and 35059 deletions

View File

@@ -0,0 +1,205 @@
/**
* Copyright (c) 2016 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
/**@file
*
* @defgroup nrf_log Logger module
* @{
* @ingroup app_common
*
* @brief The nrf_log module interface.
*/
#ifndef NRF_LOG_H_
#define NRF_LOG_H_
#include "sdk_config.h"
/** @brief Default module name prefix.
*
* The prefix can be defined in a module to override the default.
*/
#ifndef NRF_LOG_MODULE_NAME
#define NRF_LOG_MODULE_NAME ""
#endif
/** @brief Severity level for the module.
*
* The severity level can be defined in a module to override the default.
*/
#ifndef NRF_LOG_LEVEL
#define NRF_LOG_LEVEL NRF_LOG_DEFAULT_LEVEL
#endif
/** @brief Color prefix of debug logs for the module.
*
* This color prefix can be defined in a module to override the default.
*/
#ifndef NRF_LOG_DEBUG_COLOR
#define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT
#endif
/** @brief Color prefix of info logs for the module.
*
* This color prefix can be defined in a module to override the default.
*/
#ifndef NRF_LOG_INFO_COLOR
#define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT
#endif
#include "nrf_log_internal.h"
/** @def NRF_LOG_ERROR
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes error logs.
*/
/** @def NRF_LOG_WARNING
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs.
*/
/** @def NRF_LOG_INFO
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs.
*/
/** @def NRF_LOG_DEBUG
* @brief Macro for logging error messages. It takes a printf-like, formatted
* string with up to seven arguments.
*
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs.
*/
#define NRF_LOG_ERROR(...) NRF_LOG_INTERNAL_ERROR(__VA_ARGS__)
#define NRF_LOG_WARNING(...) NRF_LOG_INTERNAL_WARNING( __VA_ARGS__)
#define NRF_LOG_INFO(...) NRF_LOG_INTERNAL_INFO( __VA_ARGS__)
#define NRF_LOG_DEBUG(...) NRF_LOG_INTERNAL_DEBUG( __VA_ARGS__)
/**
* @brief A macro for logging a formatted string without any prefix or timestamp.
*/
#define NRF_LOG_RAW_INFO(...) NRF_LOG_INTERNAL_RAW_INFO( __VA_ARGS__)
/** @def NRF_LOG_HEXDUMP_ERROR
* @brief Macro for logging raw bytes.
* @details It is compiled in only if @ref NRF_LOG_LEVEL includes error logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_WARNING
* @brief Macro for logging raw bytes.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes warning logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_INFO
* @brief Macro for logging raw bytes.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes info logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
/** @def NRF_LOG_HEXDUMP_DEBUG
* @brief Macro for logging raw bytes.
* @details This macro is compiled only if @ref NRF_LOG_LEVEL includes debug logs.
*
* @param p_data Pointer to data.
* @param len Data length in bytes.
*/
#define NRF_LOG_HEXDUMP_ERROR(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len)
#define NRF_LOG_HEXDUMP_WARNING(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len)
#define NRF_LOG_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len)
#define NRF_LOG_HEXDUMP_DEBUG(p_data, len) NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len)
/**
* @brief Macro for logging hexdump without any prefix or timestamp.
*/
#define NRF_LOG_RAW_HEXDUMP_INFO(p_data, len) NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len)
/**
* @brief A macro for blocking reading from bidirectional backend used for logging.
*
* Macro call is blocking and returns when single byte is received.
*/
#define NRF_LOG_GETCHAR() NRF_LOG_INTERNAL_GETCHAR()
/**
* @brief Function for copying a string to the internal logger buffer if logs are deferred.
*
* Use this function to store a string that is volatile (for example allocated
* on stack) or that may change before the deferred logs are processed. Such string is copied
* into the internal logger buffer and is persistent until the log is processed.
*
* @note If the logs are not deferred, then this function returns the input parameter.
*
* @param p_str Pointer to the user string.
*
* @return Address to the location where the string is stored in the internal logger buffer.
*/
uint32_t nrf_log_push(char * const p_str);
/**
* @brief Macro to be used in a formatted string to a pass float number to the log.
*
* Macro should be used in formatted string instead of the %f specifier together with
* @ref NRF_LOG_FLOAT macro.
* Example: NRF_LOG_INFO("My float number" NRF_LOG_FLOAT_MARKER "\r\n", NRF_LOG_FLOAT(f)))
*/
#define NRF_LOG_FLOAT_MARKER "%d.%02d"
/**
* @brief Macro for dissecting a float number into two numbers (integer and residuum).
*/
#define NRF_LOG_FLOAT(val) (int32_t)(val), \
(int32_t)(((val > 0) ? (val) - (int32_t)(val) \
: (int32_t)(val) - (val))*100)
#endif // NRF_LOG_H_
/** @} */

View File

@@ -0,0 +1,91 @@
/**
* Copyright (c) 2016 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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.
*
*/
/**@file
* @addtogroup nrf_log Logger module
* @ingroup app_common
*
* @defgroup nrf_log_backend Backend of nrf_log
* @{
* @ingroup nrf_log
* @brief The nrf_log backend interface.
*/
#ifndef NRF_LOG_BACKEND_H__
#define NRF_LOG_BACKEND_H__
#include "nrf_log_ctrl.h"
#include "sdk_errors.h"
#include <stdbool.h>
/**
* @brief Function for initializing the logger backend.
*
* param blocking Set true if handler functions should block until completion.
*
* @return NRF_SUCCESS after successful initialization, error code otherwise.
*/
ret_code_t nrf_log_backend_init(bool blocking);
/**
* @brief Function for returning a pointer to a function for handling standard
* log entries (@ref NRF_LOG_ERROR, etc.).
*
* @return Pointer to a handler.
*/
nrf_log_std_handler_t nrf_log_backend_std_handler_get(void);
/**
* @brief Function for returning a pointer to a function for handling
* hexdumps (@ref NRF_LOG_HEXDUMP_ERROR, etc.).
*
* @return Pointer to a handler.
*/
nrf_log_hexdump_handler_t nrf_log_backend_hexdump_handler_get(void);
/**
* @brief Function for blocking reading of a byte from the backend.
*
* @return Byte.
*/
uint8_t nrf_log_backend_getchar(void);
#endif // NRF_LOG_BACKEND_H__
/** @} */

View File

@@ -0,0 +1,229 @@
/**
* Copyright (c) 2016 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NRF_LOG_CTRL_H
#define NRF_LOG_CTRL_H
/**@file
* @addtogroup nrf_log Logger module
* @ingroup app_common
*
* @defgroup nrf_log_ctrl Functions for controlling nrf_log
* @{
* @ingroup nrf_log
* @brief The nrf_log control interface.
*/
#include "sdk_config.h"
#include "sdk_errors.h"
#include <stdint.h>
#include <stdbool.h>
#include "nrf_log_ctrl_internal.h"
/**
* @brief Timestamp function prototype.
*
* @return Timestamp value.
*/
typedef uint32_t (*nrf_log_timestamp_func_t)(void);
/**@brief Macro for initializing the logs.
*
* @note If timestamps are disabled in the configuration, then the provided pointer
* can be NULL. Otherwise, it is expected that timestamp_getter is not NULL.
*
* @param timestamp_func Function that returns the timestamp.
*
* @return NRF_SUCCESS after successful initialization, otherwise an error code.
*/
#define NRF_LOG_INIT(timestamp_func) NRF_LOG_INTERNAL_INIT(timestamp_func)
/**@brief Macro for processing a single log entry from a queue of deferred logs.
*
* You can call this macro from the main context or from the error handler to process
* log entries one by one.
*
* @note If logs are not deferred, this call has no use and is defined as 'false'.
*
* @retval true There are more logs to process in the buffer.
* @retval false No more logs in the buffer.
*/
#define NRF_LOG_PROCESS() NRF_LOG_INTERNAL_PROCESS()
/** @brief Macro for processing all log entries from the buffer.
* It blocks until all buffered entries are processed by the backend.
*
* @note If logs are not deferred, this call has no use and is empty.
*/
#define NRF_LOG_FLUSH() NRF_LOG_INTERNAL_FLUSH()
/** @brief Macro for flushing log data before reset.
*
* @note If logs are not deferred, this call has no use and is empty.
*
* @note If RTT is used, then a breakpoint is hit once flushed.
*/
#define NRF_LOG_FINAL_FLUSH() NRF_LOG_INTERNAL_FINAL_FLUSH()
/** @brief Macro for changing functions that are used to handle log entries.
*
* @param default_handler Function for handling log entries.
* @param bytes_handler Function for handling hexdump entries.
*
*/
#define NRF_LOG_HANDLERS_SET(default_handler, bytes_handler) \
NRF_LOG_INTERNAL_HANDLERS_SET(default_handler, bytes_handler)
/**
* @brief Function prototype for handling a log entry.
*
* The backend must implement such prototype.
*
* @param severity_level Severity level of the entry.
* @param p_timestamp Pointer to the timestamp value. No timestamp if NULL.
* @param p_str Pointer to a formatted string.
* @param p_args Pointer to an array of arguments for a formatted string.
* @param nargs Number of arguments in p_args.
*
* @retval true If entry is successfully processed.
* @retval false If entry is not processed.
*/
typedef bool (*nrf_log_std_handler_t)(
uint8_t severity_level,
const uint32_t * const p_timestamp,
const char * const p_str,
uint32_t * p_args,
uint32_t nargs);
/**
* @brief Function prototype for handling a bytes-dumping log entry.
*
* The backend must implement such prototype. Two buffers are needed because data
* is stored internally in a circular buffer so it can be fragmented into up to
* two pieces.
*
* @param severity_level Severity level of the entry.
* @param p_timestamp Pointer to a timestamp value. No timestamp if NULL.
* @param p_str Prefix string for the bytes dump.
* @param offset Indication of how many bytes have already been processed.
* @param p_buf0 Pointer to the first part of data.
* @param buf0_length Number of bytes in the first part.
* @param p_buf1 Pointer to the second part of data. Optional.
* @param buf1_length Number of bytes in the second part.
*
* @return Number of bytes processed. If all bytes are processed, it should be a sum of
* buf0_length and buf1_length
*/
typedef uint32_t (*nrf_log_hexdump_handler_t)(
uint8_t severity_level,
const uint32_t * const p_timestamp,
const char * const p_str,
uint32_t offset,
const uint8_t * const p_buf0,
uint32_t buf0_length,
const uint8_t * const p_buf1,
uint32_t buf1_length);
/**
* @brief Function for initializing the frontend and the default backend.
*
* @ref NRF_LOG_INIT calls this function to initialize the frontend and the backend.
* If custom backend is used, then @ref NRF_LOG_INIT should not be called.
* Instead, frontend and user backend should be verbosely initialized.
*
* @param timestamp_func Function for getting a 32-bit timestamp.
*
* @return Error status.
*
*/
ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func);
/**
* @brief Function for reinitializing the backend in blocking mode.
*/
ret_code_t nrf_log_blocking_backend_set(void);
/**
* @brief Function for initializing the logger frontend.
*
* The frontend is initialized with functions for handling log entries. Those
* functions are provided by the backend.
*
* @note This function needs to be called directly only if the @ref NRF_LOG_INIT macro
* is not used to initialize the logger.
*
* @param std_handler Function for handling standard log entries.
* @param hexdump_handler Function for handling hexdump log entries.
* @param timestamp_func Function for getting a timestamp. It cannot be NULL
* unless timestamping is disabled.
*/
void nrf_log_frontend_init(nrf_log_std_handler_t std_handler,
nrf_log_hexdump_handler_t hexdump_handler,
nrf_log_timestamp_func_t timestamp_func);
/**
* @brief Function for updating functions that handle log entries.
*
* @note Use this feature to change the log handling behavior in certain
* situations, like in a fault handler.
*
* @param std_handler Function for handling standard log entries.
* @param hexdump_handler Function for handling hexdump log entries.
*/
void nrf_log_handlers_set(nrf_log_std_handler_t std_handler,
nrf_log_hexdump_handler_t hexdump_handler);
/**
* @brief Function for handling a single log entry.
*
* Use this function only if the logs are buffered. It takes a single entry from the
* buffer and attempts to process it.
*
* @retval true If there are more entries to process.
* @retval false If there are no more entries to process.
*/
bool nrf_log_frontend_dequeue(void);
#endif // NRF_LOG_CTRL_H
/**
*@}
**/

View File

@@ -0,0 +1,496 @@
/**
* Copyright (c) 2016 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG)
#include "nrf_log_backend.h"
#include "nrf_error.h"
#include <stdarg.h>
#include <string.h>
#include <stdio.h>
#include <ctype.h>
#if NRF_LOG_BACKEND_SERIAL_USES_RTT
#include <SEGGER_RTT_Conf.h>
#include <SEGGER_RTT.h>
#endif
#if NRF_LOG_BACKEND_SERIAL_USES_UART
#include "nrf_drv_uart.h"
#endif
#if NRF_LOG_BACKEND_SERIAL_USES_UART
static char m_uart_buffer[NRF_LOG_BACKEND_MAX_STRING_LENGTH];
static nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(NRF_LOG_BACKEND_UART_INSTANCE);
#if !NRF_MODULE_ENABLED(UART)
#error "UART driver must be enabled to use UART in nrf_log."
#endif
#endif //NRF_LOG_BACKEND_SERIAL_USES_UART
#define HEXDUMP_BYTES_PER_LINE 16
#define HEXDUMP_HEXBYTE_AREA 3 // Two bytes for hexbyte and space to separate
#define TIMESTAMP_STR(val) "[%0" NUM_TO_STR(val) "d]"
#define RTT_RETRY_COUNTER 10 //Number of retries before skipping processing
#define HEXDUMP_MAX_STR_LEN (NRF_LOG_BACKEND_MAX_STRING_LENGTH - \
(HEXDUMP_HEXBYTE_AREA*HEXDUMP_BYTES_PER_LINE +\
NRF_LOG_TIMESTAMP_DIGITS + \
4 +/* Color ANSI Escape Code */ \
2)) /* Separators */
static bool m_initialized = false;
static bool m_blocking_mode = false;
static const char m_default_color[] = "\x1B[0m";
#if (NRF_LOG_BACKEND_SERIAL_USES_UART)
static volatile bool m_rx_done = false;
#endif
#if (NRF_LOG_BACKEND_SERIAL_USES_UART)
static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context)
{
// Dummy handler since is_busy feature is used for determining readiness.
if (p_event->type == NRF_DRV_UART_EVT_RX_DONE)
{
m_rx_done = true;
}
}
#endif //NRF_LOG_BACKEND_SERIAL_USES_UART
ret_code_t nrf_log_backend_init(bool blocking)
{
if (m_initialized && (blocking == m_blocking_mode))
{
return NRF_SUCCESS;
}
#if (NRF_LOG_BACKEND_SERIAL_USES_RTT)
SEGGER_RTT_Init();
#endif
#if (NRF_LOG_BACKEND_SERIAL_USES_UART)
uint32_t ret_code;
nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
uart_config.hwfc =
(nrf_uart_hwfc_t)NRF_LOG_BACKEND_SERIAL_UART_FLOW_CONTROL;
uart_config.pseltxd = NRF_LOG_BACKEND_SERIAL_UART_TX_PIN;
uart_config.pselrxd = NRF_LOG_BACKEND_SERIAL_UART_RX_PIN;
uart_config.pselrts = NRF_LOG_BACKEND_SERIAL_UART_RTS_PIN;
uart_config.pselcts = NRF_LOG_BACKEND_SERIAL_UART_CTS_PIN;
uart_config.baudrate =
(nrf_uart_baudrate_t)NRF_LOG_BACKEND_SERIAL_UART_BAUDRATE;
nrf_drv_uart_uninit(&m_uart);
ret_code = nrf_drv_uart_init(&m_uart, &uart_config,
blocking ? NULL : uart_event_handler);
if (ret_code != NRF_SUCCESS)
{
return ret_code;
}
#endif //NRF_LOG_BACKEND_SERIAL_USES_UART
m_initialized = true;
m_blocking_mode = blocking;
return NRF_SUCCESS;
}
static bool serial_is_busy(void)
{
bool res = false;
#if (NRF_LOG_BACKEND_SERIAL_USES_UART)
res = nrf_drv_uart_tx_in_progress(&m_uart);
#endif
#if (NRF_LOG_BACKEND_SERIAL_USES_RTT)
#endif
return res;
}
static bool serial_tx(uint8_t * p_buf, uint32_t len)
{
bool ret = true;
#if NRF_LOG_BACKEND_SERIAL_USES_UART
memcpy(m_uart_buffer, p_buf, len);
uint32_t ret_code = nrf_drv_uart_tx(&m_uart, (uint8_t *)m_uart_buffer, len);
if (ret_code != NRF_SUCCESS)
{
ret = false;
}
#endif //NRF_LOG_BACKEND_SERIAL_USES_UART
#if NRF_LOG_BACKEND_SERIAL_USES_RTT
uint32_t idx = 0;
uint32_t length = len;
uint32_t processed;
uint32_t watchdog_counter = RTT_RETRY_COUNTER;
do
{
processed = SEGGER_RTT_WriteNoLock(0, &p_buf[idx], length);
idx += processed;
length -= processed;
if (processed == 0)
{
// If RTT is not connected then ensure that logger does not block
watchdog_counter--;
if (watchdog_counter == 0)
{
break;
}
}
} while (length);
#endif //NRF_LOG_BACKEND_SERIAL_USES_RTT
return ret;
}
static uint8_t serial_get_byte(void)
{
uint8_t data;
#if NRF_LOG_BACKEND_SERIAL_USES_UART
if (m_blocking_mode)
{
(void)nrf_drv_uart_rx(&m_uart, &data, 1);
}
else
{
m_rx_done = false;
(void)nrf_drv_uart_rx(&m_uart, &data, 1);
while(!m_rx_done);
}
#elif NRF_LOG_BACKEND_SERIAL_USES_RTT
data = (uint8_t)SEGGER_RTT_WaitKey();
#endif //NRF_LOG_BACKEND_SERIAL_USES_RTT
return data;
}
static bool buf_len_update(uint32_t * p_buf_len, int32_t new_len)
{
bool ret;
if (new_len < 0)
{
ret = false;
}
else
{
*p_buf_len += (uint32_t)new_len;
ret = true;
}
return ret;
}
static bool timestamp_process(const uint32_t * const p_timestamp, char * p_str, uint32_t * p_len)
{
int32_t len = 0;
bool ret = true;
if (p_timestamp)
{
#if NRF_LOG_USES_COLORS
len = sizeof(m_default_color) - 1;
memcpy(p_str, m_default_color, len);
*p_len += len;
#endif //NRF_LOG_USES_COLORS
len = snprintf(&p_str[len],NRF_LOG_BACKEND_MAX_STRING_LENGTH, TIMESTAMP_STR(NRF_LOG_TIMESTAMP_DIGITS), (int)*p_timestamp);
ret = buf_len_update(p_len, len);
}
else
{
*p_len = 0;
}
return ret;
}
static bool nrf_log_backend_serial_std_handler(
uint8_t severity_level,
const uint32_t * const p_timestamp,
const char * const p_str,
uint32_t * p_args,
uint32_t nargs)
{
char str[NRF_LOG_BACKEND_MAX_STRING_LENGTH];
int32_t tmp_str_len = 0;
uint32_t buffer_len = 0;
bool status = true;
if (serial_is_busy())
{
return false;
}
if (!timestamp_process(p_timestamp, &str[buffer_len], &buffer_len))
{
return false;
}
switch (nargs)
{
case 0:
{
tmp_str_len = strlen(p_str);
if ((tmp_str_len + buffer_len) < NRF_LOG_BACKEND_MAX_STRING_LENGTH)
{
memcpy(&str[buffer_len], p_str, tmp_str_len);
}
break;
}
case 1:
tmp_str_len = snprintf(&str[buffer_len], NRF_LOG_BACKEND_MAX_STRING_LENGTH-buffer_len, p_str, p_args[0]);
break;
case 2:
tmp_str_len = snprintf(&str[buffer_len], NRF_LOG_BACKEND_MAX_STRING_LENGTH-buffer_len, p_str, p_args[0], p_args[1]);
break;
case 3:
tmp_str_len = snprintf(&str[buffer_len], NRF_LOG_BACKEND_MAX_STRING_LENGTH-buffer_len, p_str, p_args[0], p_args[1], p_args[2]);
break;
case 4:
tmp_str_len =
snprintf(&str[buffer_len], NRF_LOG_BACKEND_MAX_STRING_LENGTH-buffer_len, p_str, p_args[0], p_args[1], p_args[2], p_args[3]);
break;
case 5:
tmp_str_len =
snprintf(&str[buffer_len],
NRF_LOG_BACKEND_MAX_STRING_LENGTH-buffer_len,
p_str,
p_args[0],
p_args[1],
p_args[2],
p_args[3],
p_args[4]);
break;
case 6:
tmp_str_len =
snprintf(&str[buffer_len],
NRF_LOG_BACKEND_MAX_STRING_LENGTH-buffer_len,
p_str,
p_args[0],
p_args[1],
p_args[2],
p_args[3],
p_args[4],
p_args[5]);
break;
default:
break;
}
status = buf_len_update(&buffer_len, tmp_str_len);
uint32_t full_buff_len = NRF_LOG_USES_COLORS ?
buffer_len + sizeof(m_default_color)-1 : buffer_len;
if (status && (full_buff_len <= NRF_LOG_BACKEND_MAX_STRING_LENGTH))
{
if (NRF_LOG_USES_COLORS)
{
memcpy(&str[buffer_len], m_default_color, sizeof(m_default_color)-1);
buffer_len = full_buff_len;
}
return serial_tx((uint8_t *)str, buffer_len);
}
else
{
// error, snprintf failed.
return false;
}
}
static void byte2hex(const uint8_t c, char * p_out)
{
uint8_t nibble;
uint32_t i = 2;
while (i-- != 0)
{
nibble = (c >> (4 * i)) & 0x0F;
p_out[1 - i] = (nibble > 9) ? ('A' + nibble - 10) : ('0' + nibble);
}
}
static uint32_t nrf_log_backend_serial_hexdump_handler(
uint8_t severity_level,
const uint32_t * const p_timestamp,
const char * const p_str,
uint32_t offset,
const uint8_t * const p_buf0,
uint32_t buf0_length,
const uint8_t * const p_buf1,
uint32_t buf1_length)
{
char str[NRF_LOG_BACKEND_MAX_STRING_LENGTH];
uint32_t slen;
char * p_hex_part;
char * p_char_part;
uint8_t c;
uint32_t byte_in_line;
uint32_t buffer_len = 0;
uint32_t byte_cnt = offset;
uint32_t length = buf0_length + buf1_length;
uint32_t timestamp_len = p_timestamp ?
NRF_LOG_TIMESTAMP_DIGITS+2 : 0; //+2 since timestamp is in brackets
if (serial_is_busy())
{
return offset;
}
// If it is the first part of hexdump print the header
if (offset == 0)
{
if (!timestamp_process(p_timestamp, &str[buffer_len], &buffer_len))
{
return offset;
}
slen = strlen(p_str);
// Saturate string if it's too long.
slen = (slen > HEXDUMP_MAX_STR_LEN) ? HEXDUMP_MAX_STR_LEN : slen;
memcpy(&str[buffer_len], p_str, slen);
buffer_len += slen;
}
do
{
uint32_t i;
uint32_t hex_part_offset = buffer_len;
uint32_t char_part_offset = hex_part_offset +
(HEXDUMP_BYTES_PER_LINE * HEXDUMP_HEXBYTE_AREA + 1) + // +1 - separator between hexdump and characters.
timestamp_len;
p_hex_part = &str[hex_part_offset];
p_char_part = &str[char_part_offset];
// Fill the blanks to align to timestamp print
for (i = 0; i < timestamp_len; i++)
{
*p_hex_part = ' ';
++p_hex_part;
}
for (byte_in_line = 0; byte_in_line < HEXDUMP_BYTES_PER_LINE; byte_in_line++)
{
if (byte_cnt >= length)
{
// file the blanks
*p_hex_part++ = ' ';
*p_hex_part++ = ' ';
*p_hex_part++ = ' ';
*p_char_part++ = ' ';
}
else
{
if (byte_cnt < buf0_length)
{
c = p_buf0[byte_cnt];
}
else
{
c = p_buf1[byte_cnt - buf0_length];
}
byte2hex(c, p_hex_part);
p_hex_part += 2; // move the pointer since byte in hex was added.
*p_hex_part++ = ' ';
*p_char_part++ = isprint(c) ? c : '.';
byte_cnt++;
}
}
*p_char_part++ = '\r';
*p_char_part++ = '\n';
*p_hex_part++ = ' ';
buffer_len += timestamp_len +
(HEXDUMP_BYTES_PER_LINE * HEXDUMP_HEXBYTE_AREA + 1) + // space for hex dump and separator between hexdump and string
HEXDUMP_BYTES_PER_LINE + // space for stringS dump
2; // space for new line
if (NRF_LOG_USES_COLORS)
{
memcpy(&str[buffer_len], m_default_color, sizeof(m_default_color)-1);
buffer_len += sizeof(m_default_color)-1;
}
if (!serial_tx((uint8_t *)str, buffer_len))
{
return byte_cnt;
}
if (serial_is_busy())
{
return byte_cnt;
}
buffer_len = 0;
}
while (byte_cnt < length);
return byte_cnt;
}
nrf_log_std_handler_t nrf_log_backend_std_handler_get(void)
{
return nrf_log_backend_serial_std_handler;
}
nrf_log_hexdump_handler_t nrf_log_backend_hexdump_handler_get(void)
{
return nrf_log_backend_serial_hexdump_handler;
}
uint8_t nrf_log_backend_getchar(void)
{
return serial_get_byte();
}
#endif // NRF_MODULE_ENABLED(NRF_LOG)

View File

@@ -0,0 +1,97 @@
/**
* Copyright (c) 2016 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NRF_LOG_CTRL_INTERNAL_H
#define NRF_LOG_CTRL_INTERNAL_H
/**
* @cond (NODOX)
* @defgroup nrf_log_ctrl_internal Auxiliary internal types declarations
* @{
* @internal
*/
#include "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG)
#include "app_util_platform.h"
#define NRF_LOG_INTERNAL_INIT(timestamp_func) \
nrf_log_init(timestamp_func)
#if (NRF_LOG_DEFERRED == 0)
#define NRF_LOG_INTERNAL_PROCESS() false
#define NRF_LOG_INTERNAL_FLUSH()
#define NRF_LOG_INTERNAL_FINAL_FLUSH()
#else
#define NRF_LOG_INTERNAL_PROCESS() nrf_log_frontend_dequeue()
#define NRF_LOG_INTERNAL_FLUSH() \
do { \
while (NRF_LOG_INTERNAL_PROCESS()); \
} while(0)
#if NRF_LOG_BACKEND_SERIAL_USES_RTT
#define NRF_LOG_INTERNAL_BACKEND_FINAL NRF_BREAKPOINT_COND
#else
#define NRF_LOG_INTERNAL_BACKEND_FINAL
#endif
#define NRF_LOG_INTERNAL_FINAL_FLUSH() \
do { \
(void)nrf_log_blocking_backend_set(); \
NRF_LOG_INTERNAL_FLUSH(); \
NRF_LOG_INTERNAL_BACKEND_FINAL; \
} while(0)
#endif
#define NRF_LOG_INTERNAL_HANDLERS_SET(default_handler, bytes_handler) \
nrf_log_handlers_set(default_handler, bytes_handler)
#else // NRF_MODULE_ENABLED(NRF_LOG)
#define NRF_LOG_INTERNAL_PROCESS() false
#define NRF_LOG_INTERNAL_FLUSH()
#define NRF_LOG_INTERNAL_INIT(timestamp_func) NRF_SUCCESS
#define NRF_LOG_INTERNAL_HANDLERS_SET(default_handler, bytes_handler) \
UNUSED_PARAMETER(default_handler); UNUSED_PARAMETER(bytes_handler)
#define NRF_LOG_INTERNAL_FINAL_FLUSH()
#endif // NRF_MODULE_ENABLED(NRF_LOG)
/** @}
* @endcond
*/
#endif // NRF_LOG_CTRL_INTERNAL_H

View File

@@ -0,0 +1,826 @@
/**
* Copyright (c) 2016 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 "sdk_common.h"
#if NRF_MODULE_ENABLED(NRF_LOG)
#include "app_util.h"
#include "app_util_platform.h"
#include "nrf_log.h"
#include "nrf_log_internal.h"
#include "nrf_log_backend.h"
#include "nrf_log_ctrl.h"
#include <string.h>
#if NRF_LOG_DEFERRED
STATIC_ASSERT((NRF_LOG_DEFERRED_BUFSIZE == 0) || IS_POWER_OF_TWO(NRF_LOG_DEFERRED_BUFSIZE));
#else
#define NRF_LOG_DEFERRED_BUFSIZE 1
#endif
/**
* brief An internal control block of the logger
*
* @note Circular buffer is using never cleared indexes and a mask. It means
* that logger may break when indexes overflows. However, it is quite unlikely.
* With rate of 1000 log entries with 2 parameters per second such situation
* would happen after 12 days.
*/
typedef struct
{
uint32_t wr_idx; // Current write index (never reset)
uint32_t rd_idx; // Current read index (never_reset)
uint32_t mask; // Size of buffer (must be power of 2) presented as mask
uint32_t buffer[NRF_LOG_DEFERRED_BUFSIZE];
nrf_log_timestamp_func_t timestamp_func; // A pointer to function that returns timestamp
nrf_log_std_handler_t std_handler; // A handler used for processing standard log calls
nrf_log_hexdump_handler_t hexdump_handler; // A handler for processing hex dumps
} log_data_t;
static log_data_t m_log_data;
#if (NRF_LOG_DEFERRED == 1)
static const char * m_overflow_info = NRF_LOG_ERROR_COLOR_CODE "Overflow\r\n";
#endif //(NRF_LOG_DEFERRED == 1)
/**
* Set of macros for encoding and decoding header for log entries.
* There are 3 types of entries:
* 1. Standard entry (STD)
* An entry consists of header, pointer to string and values. Header contains
* severity leveland determines number of arguments and thus size of the entry.
* Since flash address space starts from 0x00000000 and is limited to kB rather
* than MB 22 bits are used to store the address (4MB). It is used that way to
* save one RAM memory.
*
* --------------------------------
* |TYPE|SEVERITY|NARGS| P_STR |
* |------------------------------|
* | TIMESTAMP (optional) |
* |------------------------------|
* | ARG0 |
* |------------------------------|
* | .... |
* |------------------------------|
* | ARG(nargs-1) |
* --------------------------------
*
* 2. Hexdump entry (HEXDUMP) is used for dumping raw data. An entry consists of
* header, optional timestamp, pointer to string and data. A header contains
* length (10bit) and offset which is updated after backend processes part of
* data.
*
* --------------------------------
* |TYPE|SEVERITY|NARGS|OFFSET|LEN|
* |------------------------------|
* | TIMESTAMP (optional) |
* |------------------------------|
* | P_STR |
* |------------------------------|
* | data |
* |------------------------------|
* | data | dummy |
* --------------------------------
*
* 3. Pushed string. If string is pushed into the logger internal buffer it is
* stored as PUSHED entry. It consists of header, unused data (optional) and
* string. Unused data is present if string does not not fit into a buffer
* without wrapping (and string cannot be wrapped). In that case header
* contains information about offset.
*
* --------------------------------
* |TYPE| OFFSET | LEN |
* |------------------------------|
* | OFFSET |
* |------------------------------|
* end| OFFSET |
* 0|------------------------------|
* | STRING |
* |------------------------------|
* | STRING | dummy |
* --------------------------------
*/
#define HEADER_SIZE ((NRF_LOG_USES_TIMESTAMP) ? 2 : 1)
#define STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U)
#define HEADER_TYPE_STD 1U
#define HEADER_TYPE_HEXDUMP 2U
#define HEADER_TYPE_PUSHED 0U
typedef struct
{
uint32_t type : 2;
uint32_t raw : 1;
uint32_t data : 29;
} nrf_log_generic_header_t;
typedef struct
{
uint32_t type : 2;
uint32_t raw : 1;
uint32_t severity : 3;
uint32_t nargs : 4;
uint32_t addr : 22;
} nrf_log_std_header_t;
typedef struct
{
uint32_t type : 2;
uint32_t raw : 1;
uint32_t severity : 3;
uint32_t offset : 10;
uint32_t reserved : 6;
uint32_t len : 10;
} nrf_log_hexdump_header_t;
typedef struct
{
uint32_t type : 2;
uint32_t reserved0 : 4;
uint32_t offset : 10;
uint32_t reserved1 : 6;
uint32_t len : 10;
} nrf_log_pushed_header_t;
typedef union
{
nrf_log_generic_header_t generic;
nrf_log_std_header_t std;
nrf_log_hexdump_header_t hexdump;
nrf_log_pushed_header_t pushed;
uint32_t raw;
} nrf_log_header_t;
/* IAR does not support initialization with non-constant variables */
#if defined ( __ICCARM__ )
#define STD_HEADER_DEF(NAME, P_STR, SEVERITY, NARGS) \
nrf_log_header_t NAME = { \
.std = { \
.type = HEADER_TYPE_STD, \
} \
}; \
NAME.std.type = HEADER_TYPE_STD; \
NAME.std.raw = ((SEVERITY) & NRF_LOG_RAW); \
NAME.std.severity = (SEVERITY) & NRF_LOG_LEVEL_MASK; \
NAME.std.nargs = (NARGS); \
NAME.std.addr = ((uint32_t)(P_STR) & STD_ADDR_MASK)
#else
#define STD_HEADER_DEF(NAME, P_STR, SEVERITY, NARGS) \
nrf_log_header_t NAME = { \
.std = { \
.type = HEADER_TYPE_STD, \
.raw = ((SEVERITY) & NRF_LOG_RAW), \
.severity = (SEVERITY) & NRF_LOG_LEVEL_MASK, \
.nargs = (NARGS), \
.addr = ((uint32_t)(P_STR) & STD_ADDR_MASK)\
} \
}
#endif
#if defined ( __ICCARM__ )
#define HEXDUMP_HEADER_DEF(NAME, SEVERITY, LENGTH) \
nrf_log_header_t NAME = { \
.hexdump = { \
.type = HEADER_TYPE_HEXDUMP, \
.offset = 0, \
} \
}; \
NAME.hexdump.raw = ((SEVERITY) & NRF_LOG_RAW); \
NAME.hexdump.severity = (SEVERITY) & NRF_LOG_LEVEL_MASK;\
NAME.hexdump.len = (LENGTH)
#else
#define HEXDUMP_HEADER_DEF(NAME, SEVERITY, LENGTH) \
nrf_log_header_t NAME = { \
.hexdump = { \
.type = HEADER_TYPE_HEXDUMP, \
.raw = ((SEVERITY) & NRF_LOG_RAW), \
.severity = (SEVERITY) & NRF_LOG_LEVEL_MASK, \
.offset = 0, \
.len = LENGTH, \
} \
}
#endif
#if defined ( __ICCARM__ )
#define PUSHED_HEADER_DEF(NAME, OFFSET, LENGTH) \
nrf_log_header_t NAME = { \
.pushed = { \
.type = HEADER_TYPE_PUSHED, \
} \
}; \
NAME.pushed.offset = (OFFSET); \
NAME.pushed.len = (LENGTH)
#else
#define PUSHED_HEADER_DEF(NAME, OFFSET, LENGTH) \
nrf_log_header_t NAME = { \
.pushed = { \
.type = HEADER_TYPE_PUSHED, \
.offset = (OFFSET), \
.len = (LENGTH), \
} \
}
#endif
ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func)
{
if (NRF_LOG_USES_TIMESTAMP && (timestamp_func == NULL))
{
return NRF_ERROR_INVALID_PARAM;
}
ret_code_t err_code = nrf_log_backend_init(NRF_LOG_DEFERRED ? false : true);
if (err_code == NRF_SUCCESS)
{
nrf_log_frontend_init(nrf_log_backend_std_handler_get(),
nrf_log_backend_hexdump_handler_get(),
timestamp_func);
}
return err_code;
}
ret_code_t nrf_log_blocking_backend_set(void)
{
// Return value is ommited because
return nrf_log_backend_init(true);
}
void nrf_log_frontend_init(nrf_log_std_handler_t std_handler,
nrf_log_hexdump_handler_t hexdump_handler,
nrf_log_timestamp_func_t timestamp_func)
{
#if NRF_LOG_DEFERRED
m_log_data.mask = NRF_LOG_DEFERRED_BUFSIZE - 1;
m_log_data.wr_idx = 0;
m_log_data.rd_idx = 0;
#endif //NRF_LOG_DEFERRED
#if NRF_LOG_USES_TIMESTAMP
m_log_data.timestamp_func = timestamp_func;
#endif //NRF_LOG_USES_TIMESTAMP
nrf_log_handlers_set(std_handler, hexdump_handler);
}
void nrf_log_handlers_set(nrf_log_std_handler_t std_handler,
nrf_log_hexdump_handler_t hexdump_handler)
{
m_log_data.std_handler = std_handler;
m_log_data.hexdump_handler = hexdump_handler;
}
#if (NRF_LOG_DEFERRED == 1)
/**
* @brief Allocates chunk in a buffer for one entry and injects overflow if
* there is no room for requested entry.
*
* @param nargs Number of 32bit arguments. In case of allocating for hex dump it
* is the size of the buffer in 32bit words (ceiled).
* @param p_wr_idx Pointer to write index.
*
* @return True if successful allocation, false otherwise.
*
*/
static inline bool buf_prealloc(uint32_t nargs, uint32_t * p_wr_idx)
{
nargs += HEADER_SIZE;
uint32_t ovflw_tag_size = HEADER_SIZE;
bool ret = true;
CRITICAL_REGION_ENTER();
*p_wr_idx = m_log_data.wr_idx;
uint32_t available_words = (m_log_data.mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx);
uint32_t required_words = nargs + ovflw_tag_size; // room for current entry and overflow
if (required_words > available_words)
{
if (available_words >= HEADER_SIZE)
{
// Overflow entry is injected
STD_HEADER_DEF(header, m_overflow_info, NRF_LOG_LEVEL_INTERNAL, 0);
m_log_data.buffer[m_log_data.wr_idx++ & m_log_data.mask] =
header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[m_log_data.wr_idx++ & m_log_data.mask] =
m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
}
// overflow case
ret = false;
}
else
{
m_log_data.wr_idx += nargs;
}
CRITICAL_REGION_EXIT();
return ret;
}
/**
* @brief Function for preallocating a continuous chunk of memory from circular buffer.
*
* If buffer does not fit starting from current position it will be allocated at
* the beginning of the circular buffer and offset will be returned indicating
* how much memory has been ommited at the end of the buffer. Function is
* using critical section.
*
* @param len32 Length of buffer to allocate. Given in words.
* @param p_offset Offset of the buffer.
* @param p_wr_idx Pointer to write index.
*
* @return A pointer to the allocated buffer. NULL if allocation failed.
*/
static inline uint32_t * cont_buf_prealloc(uint32_t len32,
uint32_t * p_offset,
uint32_t * p_wr_idx)
{
uint32_t * p_buf = NULL;
len32++; // Increment because 32bit header is needed to be stored.
CRITICAL_REGION_ENTER();
*p_wr_idx = m_log_data.wr_idx;
uint32_t available_words = (m_log_data.mask + 1) -
(m_log_data.wr_idx & m_log_data.mask);
if (len32 <= available_words)
{
// buffer will fit as is
p_buf = &m_log_data.buffer[(m_log_data.wr_idx + 1) & m_log_data.mask];
m_log_data.wr_idx += len32;
*p_offset = 0;
}
else if (len32 < (m_log_data.rd_idx & m_log_data.mask))
{
// wraping to the begining of the buffer
m_log_data.wr_idx += (len32 + available_words - 1);
*p_offset = available_words - 1;
p_buf = m_log_data.buffer;
}
available_words = (m_log_data.mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx);
// If there is no more room for even overflow tag indicate failed allocation.
if (available_words < HEADER_SIZE)
{
p_buf = NULL;
}
CRITICAL_REGION_EXIT();
return p_buf;
}
#endif //(NRF_LOG_DEFERRED == 1)
#if (NRF_LOG_DEFERRED == 0)
static inline void nrf_log_direct_feed(uint8_t type,
char const * const p_str,
uint32_t * p_args,
uint32_t nargs)
{
uint32_t timestamp = 0;
uint32_t * p_timestamp = NRF_LOG_USES_TIMESTAMP ? &timestamp : NULL;
#if NRF_LOG_USES_TIMESTAMP
timestamp = m_log_data.timestamp_func();
#else //NRF_LOG_USES_TIMESTAMP
UNUSED_VARIABLE(timestamp);
#endif //NRF_LOG_USES_TIMESTAMP
UNUSED_VARIABLE
(m_log_data.std_handler(type, p_timestamp, (char *)p_str, p_args, nargs));
}
#endif //(NRF_LOG_DEFERRED == 0)
uint32_t nrf_log_push(char * const p_str)
{
#if (NRF_LOG_DEFERRED == 0)
return (uint32_t)p_str;
#else //(NRF_LOG_DEFERRED == 0)
uint32_t mask = m_log_data.mask;
uint32_t slen = strlen(p_str) + 1;
uint32_t buflen = CEIL_DIV(slen, 4);
uint32_t offset = 0;
uint32_t wr_idx;
char * p_dst_str = (char *)cont_buf_prealloc(buflen, &offset, &wr_idx);
if (p_dst_str)
{
PUSHED_HEADER_DEF(header, offset, buflen);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
memcpy(p_dst_str, p_str, slen);
}
return (uint32_t)p_dst_str;
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_std_0(uint8_t severity, char const * const p_str)
{
#if (NRF_LOG_DEFERRED == 0)
nrf_log_direct_feed(severity, p_str, NULL, 0);
#else //(NRF_LOG_DEFERRED == 0)
uint32_t nargs = 0;
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(nargs, &wr_idx))
{
// Proceed only if buffer was successfully preallocated.
STD_HEADER_DEF(header, p_str, severity, nargs);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
}
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_std_1(uint8_t severity,
char const * const p_str,
uint32_t val0)
{
#if (NRF_LOG_DEFERRED == 0)
uint32_t args[] = {val0};
nrf_log_direct_feed(severity, p_str, args, ARRAY_SIZE(args));
#else //(NRF_LOG_DEFERRED == 0)
uint32_t nargs = 1;
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(nargs, &wr_idx))
{
// Proceed only if buffer was successfully preallocated.
STD_HEADER_DEF(header, p_str, severity, nargs);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx & mask] = val0;
}
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_std_2(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1)
{
#if (NRF_LOG_DEFERRED == 0)
uint32_t args[] = {val0, val1};
nrf_log_direct_feed(severity, p_str, args, ARRAY_SIZE(args));
#else //(NRF_LOG_DEFERRED == 0)
uint32_t nargs = 2;
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(nargs, &wr_idx))
{
// Proceed only if buffer was successfully preallocated.
STD_HEADER_DEF(header, p_str, severity, nargs);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = val0;
m_log_data.buffer[wr_idx & mask] = val1;
}
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_std_3(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2)
{
#if (NRF_LOG_DEFERRED == 0)
uint32_t args[] = {val0, val1, val2};
nrf_log_direct_feed(severity, p_str, args, ARRAY_SIZE(args));
#else //(NRF_LOG_DEFERRED == 0)
uint32_t nargs = 3;
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(nargs, &wr_idx))
{
// Proceed only if buffer was successfully preallocated.
STD_HEADER_DEF(header, p_str, severity, nargs);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = val0;
m_log_data.buffer[wr_idx++ & mask] = val1;
m_log_data.buffer[wr_idx & mask] = val2;
}
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_std_4(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3)
{
#if (NRF_LOG_DEFERRED == 0)
uint32_t args[] = {val0, val1, val2, val3};
nrf_log_direct_feed(severity, p_str, args, ARRAY_SIZE(args));
#else //(NRF_LOG_DEFERRED == 0)
uint32_t nargs = 4;
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(nargs, &wr_idx))
{
// Proceed only if buffer was successfully preallocated.
STD_HEADER_DEF(header, p_str, severity, nargs);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = val0;
m_log_data.buffer[wr_idx++ & mask] = val1;
m_log_data.buffer[wr_idx++ & mask] = val2;
m_log_data.buffer[wr_idx & mask] = val3;
}
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_std_5(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3,
uint32_t val4)
{
#if (NRF_LOG_DEFERRED == 0)
uint32_t args[] = {val0, val1, val2, val3, val4};
nrf_log_direct_feed(severity, p_str, args, ARRAY_SIZE(args));
#else //(NRF_LOG_DEFERRED == 0)
uint32_t nargs = 5;
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(nargs, &wr_idx))
{
// Proceed only if buffer was successfully preallocated.
STD_HEADER_DEF(header, p_str, severity, nargs);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = val0;
m_log_data.buffer[wr_idx++ & mask] = val1;
m_log_data.buffer[wr_idx++ & mask] = val2;
m_log_data.buffer[wr_idx++ & mask] = val3;
m_log_data.buffer[wr_idx & mask] = val4;
}
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_std_6(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3,
uint32_t val4,
uint32_t val5)
{
#if (NRF_LOG_DEFERRED == 0)
uint32_t args[] = {val0, val1, val2, val3, val4, val5};
nrf_log_direct_feed(severity, p_str, args, ARRAY_SIZE(args));
#else //(NRF_LOG_DEFERRED == 0)
uint32_t nargs = 6;
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(nargs, &wr_idx))
{
// Proceed only if buffer was successfully preallocated.
STD_HEADER_DEF(header, p_str, severity, nargs);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = val0;
m_log_data.buffer[wr_idx++ & mask] = val1;
m_log_data.buffer[wr_idx++ & mask] = val2;
m_log_data.buffer[wr_idx++ & mask] = val3;
m_log_data.buffer[wr_idx++ & mask] = val4;
m_log_data.buffer[wr_idx & mask] = val5;
}
#endif //(NRF_LOG_DEFERRED == 0)
}
void nrf_log_frontend_hexdump(uint8_t severity,
char const * const p_str,
const void * const p_data,
uint16_t length)
{
#if (NRF_LOG_DEFERRED == 0)
uint32_t timestamp = 0;
#if NRF_LOG_USES_TIMESTAMP
timestamp = m_log_data.timestamp_func();
#else //NRF_LOG_USES_TIMESTAMP
(void) timestamp;
#endif //NRF_LOG_USES_TIMESTAMP
uint32_t curr_offset = 0;
do
{
curr_offset = m_log_data.hexdump_handler(severity,
NRF_LOG_USES_TIMESTAMP ? &timestamp : NULL,
p_str,
curr_offset,
p_data,
length,
NULL,
0);
}
while (curr_offset < length);
#else //(NRF_LOG_DEFERRED == 0)
uint32_t mask = m_log_data.mask;
uint32_t wr_idx;
if (buf_prealloc(CEIL_DIV(length, 4) + 1, &wr_idx))
{
HEXDUMP_HEADER_DEF(header, severity, length);
m_log_data.buffer[wr_idx++ & mask] = header.raw;
#if NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = m_log_data.timestamp_func();
#endif //NRF_LOG_USES_TIMESTAMP
m_log_data.buffer[wr_idx++ & mask] = (uint32_t)p_str;
uint32_t space0 = sizeof(uint32_t) * (m_log_data.mask + 1 - (wr_idx & mask));
if (length <= space0)
{
memcpy(&m_log_data.buffer[wr_idx & mask], p_data, length);
}
else
{
memcpy(&m_log_data.buffer[wr_idx & mask], p_data, space0);
length -= space0;
memcpy(&m_log_data.buffer[0], &((uint8_t *)p_data)[space0], length);
}
}
#endif //(NRF_LOG_DEFERRED == 0)
}
bool buffer_is_empty(void)
{
return (m_log_data.rd_idx == m_log_data.wr_idx);
}
bool nrf_log_frontend_dequeue(void)
{
if (buffer_is_empty())
{
return false;
}
uint32_t rd_idx = m_log_data.rd_idx;
uint32_t mask = m_log_data.mask;
uint32_t header_rd_idx = rd_idx;
// uint32_t header = m_log_data.buffer[rd_idx++ & mask];
nrf_log_header_t header;
header.raw = m_log_data.buffer[rd_idx++ & mask];
// Skip any string that is pushed to the circular buffer.
while (header.generic.type == HEADER_TYPE_PUSHED)
{
rd_idx += (header.pushed.len + header.pushed.offset);
header_rd_idx = rd_idx;
header.raw = m_log_data.buffer[rd_idx++ & mask];
}
uint32_t * p_timestamp = NRF_LOG_USES_TIMESTAMP ?
&m_log_data.buffer[rd_idx++ & mask] : NULL;
if (header.generic.raw)
{
p_timestamp = NULL;
}
bool ret = false;
if (header.generic.type == HEADER_TYPE_HEXDUMP)
{
// buffer
char * p_str = (char *)m_log_data.buffer[rd_idx++ & mask];
uint32_t length = header.hexdump.len;
uint32_t offset = header.hexdump.offset;
uint32_t space0 = sizeof(uint32_t) * (mask + 1 - (rd_idx & mask));
if (length > space0)
{
uint8_t * ptr0 = space0 ?
(uint8_t *)&m_log_data.buffer[rd_idx & mask] :
(uint8_t *)&m_log_data.buffer[0];
uint8_t len0 = space0 ? space0 : length;
uint8_t * ptr1 = space0 ?
(uint8_t *)&m_log_data.buffer[0] : NULL;
uint8_t len1 = space0 ? length - space0 : 0;
offset = m_log_data.hexdump_handler(header.hexdump.severity,
p_timestamp, p_str,
offset,
ptr0, len0,
ptr1, len1);
}
else
{
offset = m_log_data.hexdump_handler(
header.hexdump.severity,
p_timestamp,
p_str,
offset,
(uint8_t *)&m_log_data.buffer[rd_idx & mask],
length,
NULL, 0);
}
if (offset == length)
{
rd_idx += CEIL_DIV(length, 4);
ret = true;
}
else
{
// If there is more log to process just updated the offset but
// do not move rd_idx.
header.hexdump.offset = offset;
m_log_data.buffer[header_rd_idx & mask] = header.raw;
}
}
else // standard entry
{
uint32_t args[6];
uint32_t * p_arg = args;
char * p_str = (char *)((uint32_t)header.std.addr);
uint32_t nargs = header.std.nargs;
uint32_t i;
for (i = 0; i < nargs; i++)
{
*p_arg = m_log_data.buffer[rd_idx++ & mask];
p_arg++;
}
ret = m_log_data.std_handler(header.std.severity,
p_timestamp,
p_str, args, nargs);
}
if (ret)
{
m_log_data.rd_idx = rd_idx;
}
return buffer_is_empty() ? false : true;
}
uint8_t nrf_log_getchar(void)
{
return nrf_log_backend_getchar();
}
#endif // NRF_MODULE_ENABLED(NRF_LOG)

View File

@@ -0,0 +1,309 @@
/**
* Copyright (c) 2016 - 2017, Nordic Semiconductor ASA
*
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without modification,
* are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice, this
* list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form, except as embedded into a Nordic
* Semiconductor ASA integrated circuit in a product or a software update for
* such product, 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.
*
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its
* contributors may be used to endorse or promote products derived from this
* software without specific prior written permission.
*
* 4. This software, with or without modification, must only be used with a
* Nordic Semiconductor ASA integrated circuit.
*
* 5. Any software provided in binary form under this license must not be reverse
* engineered, decompiled, modified and/or disassembled.
*
* THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
* OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA 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 NRF_LOG_INTERNAL_H__
#define NRF_LOG_INTERNAL_H__
#include "sdk_common.h"
#include "nrf.h"
#include "nrf_error.h"
#include "app_util.h"
#include <stdint.h>
#include <stdbool.h>
#ifndef NRF_LOG_DEFAULT_LEVEL
#define NRF_LOG_DEFAULT_LEVEL 0
#endif
#ifndef NRF_LOG_USES_COLORS
#define NRF_LOG_USES_COLORS 0
#endif
#define NRF_LOG_LEVEL_ERROR 1U
#define NRF_LOG_LEVEL_WARNING 2U
#define NRF_LOG_LEVEL_INFO 3U
#define NRF_LOG_LEVEL_DEBUG 4U
#define NRF_LOG_LEVEL_INTERNAL 5U
#define NRF_LOG_LEVEL_MASK 0x07
#define NRF_LOG_RAW_POS 4U
#define NRF_LOG_RAW (1U << NRF_LOG_RAW_POS)
#define NRF_LOG_LEVEL_INFO_RAW (NRF_LOG_RAW | NRF_LOG_LEVEL_INFO)
#define NRF_LOG_COLOR_CODE_DEFAULT "\x1B[0m"
#define NRF_LOG_COLOR_CODE_BLACK "\x1B[1;30m"
#define NRF_LOG_COLOR_CODE_RED "\x1B[1;31m"
#define NRF_LOG_COLOR_CODE_GREEN "\x1B[1;32m"
#define NRF_LOG_COLOR_CODE_YELLOW "\x1B[1;33m"
#define NRF_LOG_COLOR_CODE_BLUE "\x1B[1;34m"
#define NRF_LOG_COLOR_CODE_MAGENTA "\x1B[1;35m"
#define NRF_LOG_COLOR_CODE_CYAN "\x1B[1;36m"
#define NRF_LOG_COLOR_CODE_WHITE "\x1B[1;37m"
#define NRF_LOG_COLOR_0 NRF_LOG_COLOR_CODE_DEFAULT
#define NRF_LOG_COLOR_1 NRF_LOG_COLOR_CODE_BLACK
#define NRF_LOG_COLOR_2 NRF_LOG_COLOR_CODE_RED
#define NRF_LOG_COLOR_3 NRF_LOG_COLOR_CODE_GREEN
#define NRF_LOG_COLOR_4 NRF_LOG_COLOR_CODE_YELLOW
#define NRF_LOG_COLOR_5 NRF_LOG_COLOR_CODE_BLUE
#define NRF_LOG_COLOR_6 NRF_LOG_COLOR_CODE_MAGENTA
#define NRF_LOG_COLOR_7 NRF_LOG_COLOR_CODE_CYAN
#define NRF_LOG_COLOR_8 NRF_LOG_COLOR_CODE_WHITE
#define NRF_LOG_COLOR_DECODE(N) CONCAT_2(NRF_LOG_COLOR_, N)
#if NRF_LOG_USES_COLORS
#define NRF_LOG_ERROR_COLOR_CODE NRF_LOG_COLOR_DECODE(NRF_LOG_ERROR_COLOR)
#define NRF_LOG_WARNING_COLOR_CODE NRF_LOG_COLOR_DECODE(NRF_LOG_WARNING_COLOR)
#define NRF_LOG_INFO_COLOR_CODE NRF_LOG_COLOR_DECODE(NRF_LOG_INFO_COLOR)
#define NRF_LOG_DEBUG_COLOR_CODE NRF_LOG_COLOR_DECODE(NRF_LOG_DEBUG_COLOR)
#else // NRF_LOG_USES_COLORS
#define NRF_LOG_ERROR_COLOR_CODE
#define NRF_LOG_WARNING_COLOR_CODE
#define NRF_LOG_INFO_COLOR_CODE
#define NRF_LOG_DEBUG_COLOR_CODE
#endif // NRF_LOG_USES_COLORS
#define LOG_INTERNAL_0(type, prefix, str) \
nrf_log_frontend_std_0(type, prefix str)
#define LOG_INTERNAL_1(type, prefix, str, arg0) \
nrf_log_frontend_std_1(type, prefix str, arg0)
#define LOG_INTERNAL_2(type, prefix, str, arg0, arg1) \
nrf_log_frontend_std_2(type, prefix str, arg0, arg1)
#define LOG_INTERNAL_3(type, prefix, str, arg0, arg1, arg2) \
nrf_log_frontend_std_3(type, prefix str, arg0, arg1, arg2)
#define LOG_INTERNAL_4(type, prefix, str, arg0, arg1, arg2, arg3) \
nrf_log_frontend_std_4(type, prefix str, arg0, arg1, arg2, arg3)
#define LOG_INTERNAL_5(type, prefix, str, arg0, arg1, arg2, arg3, arg4) \
nrf_log_frontend_std_5(type, prefix str, arg0, arg1, arg2, arg3, arg4)
#define LOG_INTERNAL_6(type, prefix, str, arg0, arg1, arg2, arg3, arg4, arg5) \
nrf_log_frontend_std_6(type, prefix str, arg0, arg1, arg2, arg3, arg4, arg5)
#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__)
#define LOG_INTERNAL(type, prefix, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \
__VA_ARGS__), type, prefix, __VA_ARGS__)
#define NRF_LOG_BREAK ":"
#define LOG_ERROR_PREFIX NRF_LOG_ERROR_COLOR_CODE NRF_LOG_MODULE_NAME NRF_LOG_BREAK "ERROR:"
#define LOG_WARNING_PREFIX NRF_LOG_WARNING_COLOR_CODE NRF_LOG_MODULE_NAME NRF_LOG_BREAK "WARNING:"
#define LOG_INFO_PREFIX NRF_LOG_INFO_COLOR_CODE NRF_LOG_MODULE_NAME NRF_LOG_BREAK "INFO:"
#define LOG_DEBUG_PREFIX NRF_LOG_DEBUG_COLOR_CODE NRF_LOG_MODULE_NAME NRF_LOG_BREAK "DEBUG:"
#define NRF_LOG_INTERNAL_ERROR(...) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_ERROR) && \
(NRF_LOG_LEVEL_ERROR <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
LOG_INTERNAL(NRF_LOG_LEVEL_ERROR, LOG_ERROR_PREFIX, __VA_ARGS__); \
}
#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_ERROR) && \
(NRF_LOG_LEVEL_ERROR <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
nrf_log_frontend_hexdump(NRF_LOG_LEVEL_ERROR, LOG_ERROR_PREFIX "\r\n", (p_data), (len)); \
}
#define NRF_LOG_INTERNAL_WARNING(...) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_WARNING) && \
(NRF_LOG_LEVEL_WARNING <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
LOG_INTERNAL(NRF_LOG_LEVEL_WARNING, LOG_WARNING_PREFIX, __VA_ARGS__); \
}
#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_WARNING) && \
(NRF_LOG_LEVEL_WARNING <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
nrf_log_frontend_hexdump(NRF_LOG_LEVEL_WARNING, LOG_WARNING_PREFIX "\r\n", (p_data), (len)); \
}
#define NRF_LOG_INTERNAL_INFO(...) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \
(NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
LOG_INTERNAL(NRF_LOG_LEVEL_INFO, LOG_INFO_PREFIX, __VA_ARGS__); \
}
#define NRF_LOG_INTERNAL_RAW_INFO(...) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \
(NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
LOG_INTERNAL(NRF_LOG_LEVEL_INFO | NRF_LOG_RAW, "", __VA_ARGS__); \
}
#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \
(NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
nrf_log_frontend_hexdump(NRF_LOG_LEVEL_INFO, LOG_INFO_PREFIX "\r\n", (p_data), (len)); \
}
#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_INFO) && \
(NRF_LOG_LEVEL_INFO <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
nrf_log_frontend_hexdump(NRF_LOG_LEVEL_INFO | NRF_LOG_RAW, "", (p_data), (len)); \
}
#define NRF_LOG_INTERNAL_DEBUG(...) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_DEBUG) && \
(NRF_LOG_LEVEL_DEBUG <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
LOG_INTERNAL(NRF_LOG_LEVEL_DEBUG, LOG_DEBUG_PREFIX, __VA_ARGS__); \
}
#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \
if ((NRF_LOG_LEVEL >= NRF_LOG_LEVEL_DEBUG) && \
(NRF_LOG_LEVEL_DEBUG <= NRF_LOG_DEFAULT_LEVEL)) \
{ \
nrf_log_frontend_hexdump(NRF_LOG_LEVEL_DEBUG, LOG_DEBUG_PREFIX "\r\n", (p_data), (len)); \
}
#if NRF_MODULE_ENABLED(NRF_LOG)
#define NRF_LOG_INTERNAL_GETCHAR() nrf_log_getchar()
#else
#define NRF_LOG_INTERNAL_GETCHAR() (void)
#endif
/**
* @brief A function for logging raw string.
*
* @param severity Severity.
* @param p_str A pointer to a string.
*/
void nrf_log_frontend_std_0(uint8_t severity, char const * const p_str);
/**
* @brief A function for logging a formatted string with one argument.
*
* @param severity Severity.
* @param p_str A pointer to a formatted string.
* @param val0 An argument.
*/
void nrf_log_frontend_std_1(uint8_t severity,
char const * const p_str,
uint32_t val0);
/**
* @brief A function for logging a formatted string with 2 arguments.
*
* @param severity Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1 Arguments for formatting string.
*/
void nrf_log_frontend_std_2(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1);
/**
* @brief A function for logging a formatted string with 3 arguments.
*
* @param severity Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2 Arguments for formatting string.
*/
void nrf_log_frontend_std_3(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2);
/**
* @brief A function for logging a formatted string with 4 arguments.
*
* @param severity Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2, val3 Arguments for formatting string.
*/
void nrf_log_frontend_std_4(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3);
/**
* @brief A function for logging a formatted string with 5 arguments.
*
* @param severity Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2, val3, val4 Arguments for formatting string.
*/
void nrf_log_frontend_std_5(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3,
uint32_t val4);
/**
* @brief A function for logging a formatted string with 6 arguments.
*
* @param severity Severity.
* @param p_str A pointer to a formatted string.
* @param val0, val1, val2, val3, val4, val5 Arguments for formatting string.
*/
void nrf_log_frontend_std_6(uint8_t severity,
char const * const p_str,
uint32_t val0,
uint32_t val1,
uint32_t val2,
uint32_t val3,
uint32_t val4,
uint32_t val5);
/**
* @brief A function for logging raw data.
*
* @param severity Severity.
* @param p_str A pointer to a string which is prefixing the data.
* @param p_data A pointer to data to be dumped.
* @param length Length of data (in bytes).
*
*/
void nrf_log_frontend_hexdump(uint8_t severity,
char const * const p_str,
const void * const p_data,
uint16_t length);
/**
* @brief A function for reading a byte from log backend.
*
* @return Byte.
*/
uint8_t nrf_log_getchar(void);
#endif // NRF_LOG_INTERNAL_H__