/** * Copyright (c) 2016 - 2020, 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_str_formatter.h" #include "nrf_log_internal.h" #include "nrf_log_ctrl.h" #include "nrf_fprintf.h" #include #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_CHAR_CODE_MAX 0x7E static const char * severity_names[] = { NULL, "error", "warning", "info", "debug" }; static const char * m_colors[] = { NRF_LOG_COLOR_CODE_DEFAULT, NRF_LOG_COLOR_CODE_BLACK, NRF_LOG_COLOR_CODE_RED, NRF_LOG_COLOR_CODE_GREEN, NRF_LOG_COLOR_CODE_YELLOW, NRF_LOG_COLOR_CODE_BLUE, NRF_LOG_COLOR_CODE_MAGENTA, NRF_LOG_COLOR_CODE_CYAN, NRF_LOG_COLOR_CODE_WHITE, }; static uint32_t m_freq; static uint32_t m_timestamp_div; static void timestamp_print(nrf_fprintf_ctx_t * p_ctx, uint32_t timestamp) { if (NRF_LOG_USES_TIMESTAMP) { if (NRF_LOG_STR_FORMATTER_TIMESTAMP_FORMAT_ENABLED) { timestamp /= m_timestamp_div; uint32_t seconds = timestamp/m_freq; uint32_t hours = seconds/3600; seconds -= hours * 3600; uint32_t mins = seconds/60; seconds -= mins * 60; uint32_t reminder = timestamp % m_freq; uint32_t ms = (reminder * 1000)/m_freq; uint32_t us = (1000*(1000*reminder - (ms * m_freq)))/m_freq; nrf_fprintf(p_ctx, "[%02d:%02d:%02d.%03d,%03d] ", hours, mins, seconds, ms, us); } else { nrf_fprintf(p_ctx, "[%08lu] ", timestamp); } } } static void prefix_process(nrf_log_str_formatter_entry_params_t * p_params, nrf_fprintf_ctx_t * p_ctx) { if (p_params->dropped) { nrf_fprintf(p_ctx, "%sLogs dropped (%d)%s\r\n", NRF_LOG_COLOR_CODE_RED, p_params->dropped, NRF_LOG_COLOR_CODE_DEFAULT); } if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW)) { if (p_params->use_colors) { nrf_fprintf(p_ctx, "%s", m_colors[nrf_log_color_id_get( p_params->module_id, p_params->severity)]); } timestamp_print(p_ctx, p_params->timestamp); nrf_fprintf(p_ctx, "<%s> %s: ", severity_names[p_params->severity], nrf_log_module_name_get(p_params->module_id, false)); } } static void postfix_process(nrf_log_str_formatter_entry_params_t * p_params, nrf_fprintf_ctx_t * p_ctx, bool newline) { if (!(p_params->severity == NRF_LOG_SEVERITY_INFO_RAW)) { if (p_params->use_colors) { nrf_fprintf(p_ctx, "%s", m_colors[0]); } nrf_fprintf(p_ctx, "\r\n"); } else if (newline) { nrf_fprintf(p_ctx, "\r\n"); } nrf_fprintf_buffer_flush(p_ctx); } void nrf_log_std_entry_process(char const * p_str, uint32_t const * p_args, uint32_t nargs, nrf_log_str_formatter_entry_params_t * p_params, nrf_fprintf_ctx_t * p_ctx) { bool auto_flush = p_ctx->auto_flush; p_ctx->auto_flush = false; prefix_process(p_params, p_ctx); switch (nargs) { case 0: nrf_fprintf(p_ctx, p_str); break; case 1: nrf_fprintf(p_ctx, p_str, p_args[0]); break; case 2: nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1]); break; case 3: nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2]); break; case 4: nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3]); break; case 5: nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4]); break; case 6: nrf_fprintf(p_ctx, p_str, p_args[0], p_args[1], p_args[2], p_args[3], p_args[4], p_args[5]); break; default: break; } postfix_process(p_params, p_ctx, false); p_ctx->auto_flush = auto_flush; } #define HEXDUMP_BYTES_IN_LINE 8 void nrf_log_hexdump_entry_process(uint8_t * p_data, uint32_t data_len, nrf_log_str_formatter_entry_params_t * p_params, nrf_fprintf_ctx_t * p_ctx) { if (data_len > HEXDUMP_BYTES_IN_LINE) { return; } bool auto_flush = p_ctx->auto_flush; p_ctx->auto_flush = false; prefix_process(p_params, p_ctx); uint32_t i; for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) { if (i < data_len) { nrf_fprintf(p_ctx, " %02x", p_data[i]); } else { nrf_fprintf(p_ctx, " "); } } nrf_fprintf(p_ctx, "|"); for (i = 0; i < HEXDUMP_BYTES_IN_LINE; i++) { if (i < data_len) { char c = (char)p_data[i]; nrf_fprintf(p_ctx, "%c", ((c <= NRF_LOG_CHAR_CODE_MAX) && isprint((int)c)) ? c :'.'); } else { nrf_fprintf(p_ctx, " "); } } postfix_process(p_params, p_ctx, true); p_ctx->auto_flush = auto_flush; } void nrf_log_str_formatter_timestamp_freq_set(uint32_t freq) { m_timestamp_div = 1; /* There is no point to have frequency higher than 1MHz (ns are not printed) and too high * frequency leads to overflows in calculations. */ while (freq > 1000000) { freq /= 2; m_timestamp_div *= 2; } m_freq = freq; } #endif //NRF_LOG_ENABLED