mirror of
https://github.com/jam422470459/EPD-nRF52-hema213.git
synced 2025-12-19 23:03:21 +08:00
move components to SDK dir
This commit is contained in:
@@ -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)
|
||||
@@ -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
|
||||
@@ -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 ? ×tamp : 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 ? ×tamp : 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)
|
||||
@@ -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__
|
||||
Reference in New Issue
Block a user