aboutsummaryrefslogtreecommitdiff
path: root/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src
diff options
context:
space:
mode:
Diffstat (limited to 'thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src')
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_flash.c739
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_rtt.c123
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.c115
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.h77
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_uart.c116
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_ctrl_internal.h80
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_default_backends.c76
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_frontend.c1245
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_internal.h529
-rw-r--r--thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_str_formatter.c256
10 files changed, 3356 insertions, 0 deletions
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_flash.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_flash.c
new file mode 100644
index 0000000..0efd5d8
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_flash.c
@@ -0,0 +1,739 @@
+/**
+ * Copyright (c) 2016 - 2018, 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) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH)
+#include "nrf_log_backend_flash.h"
+#include "nrf_log_str_formatter.h"
+#include "nrf_fstorage_nvmc.h"
+#include "nrf_log.h"
+#include "nrf_atomic.h"
+#include "nrf_queue.h"
+#include "app_error.h"
+#include <stdbool.h>
+
+#if (NRF_LOG_BACKEND_FLASHLOG_ENABLED == 0) && (NRF_LOG_BACKEND_CRASHLOG_ENABLED == 0)
+#error "No flash backend enabled."
+#endif
+
+/** @brief Maximum logger message payload (arguments or data in hexdump) which can be stored. */
+#define FLASH_LOG_MAX_PAYLOAD_SIZE (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE - sizeof(nrf_log_header_t))
+
+/** @brief Size of serialization buffer in words. */
+#define FLASH_LOG_SER_BUFFER_WORDS (NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE/sizeof(uint32_t))
+
+/** @brief Length of logger header. */
+#define LOG_HEADER_LEN (sizeof(nrf_log_header_t))
+
+/** @brief Length of logger header given in 32 bit words. */
+#define LOG_HEADER_LEN_WORDS (LOG_HEADER_LEN/sizeof(uint32_t))
+
+/** @brief Maximum possible length of standard log message. */
+#define STD_LOG_MSG_MAX_LEN (LOG_HEADER_LEN + NRF_LOG_MAX_NUM_OF_ARGS*sizeof(uint32_t))
+
+/* Buffer must be multiple of 4. */
+STATIC_ASSERT((NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE % sizeof(uint32_t)) == 0);
+
+/* Buffer must fit standard log message. */
+STATIC_ASSERT(NRF_LOG_BACKEND_FLASH_SER_BUFFER_SIZE >= STD_LOG_MSG_MAX_LEN);
+
+/** @brief Flash page size in bytes. */
+#define CODE_PAGE_SIZE 4096
+
+/** @brief Start address of the area dedicated for flash log. */
+#define FLASH_LOG_START_ADDR (NRF_LOG_BACKEND_FLASH_START_PAGE * CODE_PAGE_SIZE)
+
+/** @brief End address of the area dedicated for flash log. */
+#define FLASH_LOG_END_ADDR (FLASH_LOG_START_ADDR + (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE) - 1)
+
+/** @brief Size of the area dedicated for flash log. */
+#define FLASH_LOG_SIZE (NRF_LOG_BACKEND_PAGES * CODE_PAGE_SIZE)
+
+/** @brief Start address determined in runtime.
+ *
+ * If configuration indicates that flash log should be placed after application.
+ * */
+#if defined ( __CC_ARM )
+#define RUNTIME_START_ADDR \
+ _Pragma("diag_suppress 170") \
+ ((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \
+ (CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR) \
+ _Pragma("diag_default 170")
+#else
+#define RUNTIME_START_ADDR ((NRF_LOG_BACKEND_FLASH_START_PAGE == 0) ? \
+ (CODE_PAGE_SIZE*CEIL_DIV((uint32_t)CODE_END, CODE_PAGE_SIZE)) : FLASH_LOG_START_ADDR)
+#endif
+static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt);
+
+/** @brief Message queue for run time flash log. */
+#if NRF_LOG_BACKEND_FLASHLOG_ENABLED
+NRF_QUEUE_DEF(nrf_log_entry_t *,
+ m_flashlog_queue,
+ NRF_LOG_BACKEND_FLASHLOG_QUEUE_SIZE,
+ NRF_QUEUE_MODE_NO_OVERFLOW);
+static const nrf_queue_t * mp_flashlog_queue = &m_flashlog_queue;
+#else
+static const nrf_queue_t * mp_flashlog_queue = NULL;
+#endif
+
+
+/** @brief Message FIFO for crash log. */
+#if NRF_LOG_BACKEND_CRASHLOG_ENABLED
+NRF_QUEUE_DEF(nrf_log_entry_t *,
+ m_crashlog_queue,
+ NRF_LOG_BACKEND_CRASHLOG_FIFO_SIZE,
+ NRF_QUEUE_MODE_NO_OVERFLOW);
+static const nrf_queue_t * mp_crashlog_queue = &m_crashlog_queue;
+#else
+static const nrf_queue_t * mp_crashlog_queue = NULL;
+#endif
+
+
+/** @brief Fstorage instance used for flash log. */
+NRF_FSTORAGE_DEF(nrf_fstorage_t m_log_flash_fstorage) =
+{
+ /* Set a handler for fstorage events. */
+ .evt_handler = fstorage_evt_handler,
+ .start_addr = FLASH_LOG_START_ADDR,
+ .end_addr = FLASH_LOG_END_ADDR,
+};
+
+/** @brief Flash log state. */
+typedef enum
+{
+ LOG_BACKEND_FLASH_ACTIVE, /**< Flash backend is active. */
+ LOG_BACKEND_FLASH_INACTIVE, /**< Flash backend is inactive. All incoming requests are skipped. */
+ LOG_BACKEND_FLASH_IN_PANIC, /**< Flash backend is in panic mode. Incoming messages are written to flash in synchronous mode. */
+} log_backend_flash_state_t;
+
+static log_backend_flash_state_t m_state; /**< Flash logger backend state. */
+static nrf_atomic_flag_t m_busy_flag; /**< Flag indicating if module performs flash writing. */
+static uint32_t m_flash_buf[FLASH_LOG_SER_BUFFER_WORDS]; /**< Buffer used for serializing messages. */
+static uint32_t m_curr_addr; /**< Address of free spot in the storage area. */
+static size_t m_curr_len; /**< Length of current message being written. */
+static uint32_t m_dropped; /**< Number of dropped messages. */
+
+/** @brief Log message string injected when entering panic mode. */
+static const char crashlog_str[] = "-----------CRASHLOG------------\r\n";
+
+/** @brief Function saturates input to maximum possible length and rounds up value to be multiple
+ * of word size.
+ *
+ * @param length Length value.
+ *
+ * @return Modified input length.
+ */
+static uint32_t saturate_align_length(uint32_t length)
+{
+ length = (length > FLASH_LOG_MAX_PAYLOAD_SIZE) ? FLASH_LOG_MAX_PAYLOAD_SIZE : length; //saturate
+ length = CEIL_DIV(length, sizeof(uint32_t))*sizeof(uint32_t);
+ return length;
+}
+
+
+/**
+ * @brief Function for copying logger message to the buffer.
+ *
+ * @param[in] p_msg Logger message.
+ * @param[out] p_buf Output buffer where serialized message is placed.
+ * @param[in,out] p_len Buffer size as input, length of prepared data as output.
+ *
+ * @return True if message fits into the buffer, false otherwise
+ */
+static bool msg_to_buf(nrf_log_entry_t * p_msg, uint8_t * p_buf, size_t * p_len)
+{
+ uint32_t data_len;
+ nrf_log_header_t header = {0};
+ uint32_t memobj_offset = HEADER_SIZE*sizeof(uint32_t);
+
+ nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), 0);
+
+ memcpy(p_buf, &header, sizeof(nrf_log_header_t));
+ p_buf += sizeof(nrf_log_header_t);
+
+ switch (header.base.generic.type)
+ {
+ case HEADER_TYPE_STD:
+ {
+ data_len = header.base.std.nargs * sizeof(uint32_t);
+ break;
+ }
+ case HEADER_TYPE_HEXDUMP:
+ {
+ data_len = saturate_align_length(header.base.hexdump.len);
+ break;
+ }
+ default:
+ *p_len = 0;
+ return false;
+ }
+ nrf_memobj_read(p_msg, p_buf, data_len, memobj_offset);
+
+ if (*p_len >= sizeof(nrf_log_header_t) + data_len)
+ {
+ *p_len = sizeof(nrf_log_header_t) + data_len;
+ return true;
+ }
+ else
+ {
+ return false;
+ }
+}
+
+/**
+ * @brief Function for getting logger message stored in flash.
+ *
+ * @param[in] p_buf Pointer to the location where message is stored.
+ * @param[out] pp_header Pointer to the log message header.
+ * @param[out] pp_data Pointer to the log message data (arguments or data in case of hexdump).
+ *
+ * @return True if message was successfully fetched, false otherwise.
+ */
+static bool msg_from_buf(uint32_t * p_buf,
+ nrf_log_header_t * * pp_header,
+ uint8_t * * pp_data,
+ uint32_t * p_len)
+{
+ *pp_header = (nrf_log_header_t *)p_buf;
+ *pp_data = (uint8_t *)&p_buf[LOG_HEADER_LEN_WORDS];
+
+ uint32_t data_len;
+
+ switch ((*pp_header)->base.generic.type)
+ {
+ case HEADER_TYPE_STD:
+ {
+ data_len = ((*pp_header)->base.std.nargs)*sizeof(uint32_t);
+ break;
+ }
+ case HEADER_TYPE_HEXDUMP:
+ {
+
+ data_len = saturate_align_length((*pp_header)->base.hexdump.len);
+ break;
+ }
+ default:
+ return false;
+ }
+
+ *p_len = LOG_HEADER_LEN + data_len;
+ return true;
+}
+
+/**
+ * @brief Function for processing log message queue.
+ *
+ * If writing to flash is synchronous then function drains the queue and writes all messages to flash.
+ * If writing to flash is asynchronous then function starts single write operation. In asynchronous mode
+ * function is called when new message is put into the queue from from flash operation callback.
+ *
+ * Function detects the situation that flash module reports attempt to write outside dedicated area.
+ * In that case flash backend stops writing any new messages.
+ *
+ * @param p_queue Queue will log messages
+ * @param fstorage_blocking If true it indicates that flash operations are blocking, event handler is not used.
+ */
+static void log_msg_queue_process(nrf_queue_t const * p_queue, bool fstorage_blocking)
+{
+ nrf_log_entry_t * p_msg;
+ bool busy = false;
+ while (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS)
+ {
+ ret_code_t err_code;
+
+ m_curr_len = sizeof(m_flash_buf);
+ if (!msg_to_buf(p_msg, (uint8_t *)m_flash_buf, &m_curr_len))
+ {
+ continue;
+ }
+
+ err_code = nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, m_curr_len, p_msg);
+
+ if (err_code == NRF_SUCCESS)
+ {
+ if (fstorage_blocking)
+ {
+ m_curr_addr += m_curr_len;
+
+ nrf_memobj_put(p_msg);
+ }
+ else
+ {
+ busy = true;
+ break;
+ }
+ }
+ else if (!fstorage_blocking && (err_code == NRF_ERROR_NO_MEM))
+ {
+ // fstorage queue got full. Drop entry.
+ nrf_memobj_put(p_msg);
+ m_dropped++;
+ break;
+ }
+ else if (err_code == NRF_ERROR_INVALID_ADDR)
+ {
+ // Trying to write outside the area, flash log is full. Skip any new writes.
+ nrf_memobj_put(p_msg);
+ m_state = LOG_BACKEND_FLASH_INACTIVE;
+ }
+ else
+ {
+ ASSERT(false);
+ }
+ }
+
+ if (!busy)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_flag_clear(&m_busy_flag));
+ }
+}
+
+static void queue_element_drop(nrf_queue_t const * p_queue)
+{
+ nrf_log_entry_t * p_msg;
+ if (nrf_queue_pop(p_queue, &p_msg) == NRF_SUCCESS)
+ {
+ m_dropped++;
+ nrf_memobj_put(p_msg);
+ }
+}
+
+static void fstorage_evt_handler(nrf_fstorage_evt_t * p_evt)
+{
+ if (m_state == LOG_BACKEND_FLASH_ACTIVE)
+ {
+ switch (p_evt->id)
+ {
+ case NRF_FSTORAGE_EVT_WRITE_RESULT:
+ {
+ if (p_evt->result == NRF_SUCCESS)
+ {
+ m_curr_addr += m_curr_len;
+ m_curr_len = 0;
+ log_msg_queue_process(mp_flashlog_queue, false);
+ }
+ else
+ {
+ m_dropped++;
+ }
+
+ if (p_evt->p_param)
+ {
+ nrf_memobj_put((nrf_log_entry_t *)p_evt->p_param);
+ }
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ else if ((m_state == LOG_BACKEND_FLASH_INACTIVE) &&
+ (p_evt->id == NRF_FSTORAGE_EVT_ERASE_RESULT) &&
+ (p_evt->addr == RUNTIME_START_ADDR))
+ {
+ m_state = LOG_BACKEND_FLASH_ACTIVE;
+ }
+}
+
+/**
+ * @brief Function for enqueueing new message.
+ *
+ * If queue is full then the oldest message is freed.
+ *
+ * @param p_queue Queue.
+ * @param p_msg Message.
+ *
+ * @return Number of dropped messages
+ */
+static uint32_t message_enqueue(nrf_queue_t const * p_queue, nrf_log_entry_t * p_msg)
+{
+ uint32_t dropped = 0;
+
+ //flag was set, busy so enqueue message
+ while (nrf_queue_push(p_queue, &p_msg) != NRF_SUCCESS)
+ {
+
+ nrf_log_entry_t * p_old_msg;
+ if (nrf_queue_pop(p_queue, &p_old_msg) == NRF_SUCCESS)
+ {
+ nrf_memobj_put(p_old_msg);
+ dropped++;
+ }
+ }
+
+ return dropped;
+}
+
+
+void nrf_log_backend_flashlog_put(nrf_log_backend_t const * p_backend,
+ nrf_log_entry_t * p_msg)
+{
+ if (m_state == LOG_BACKEND_FLASH_ACTIVE)
+ {
+ nrf_memobj_get(p_msg);
+
+ m_dropped += message_enqueue(mp_flashlog_queue, p_msg);
+
+ if (nrf_atomic_flag_set_fetch(&m_busy_flag) == 0)
+ {
+ log_msg_queue_process(mp_flashlog_queue, false);
+ }
+ }
+}
+
+
+void nrf_log_backend_crashlog_put(nrf_log_backend_t const * p_backend,
+ nrf_log_entry_t * p_msg)
+{
+ if (m_state != LOG_BACKEND_FLASH_INACTIVE)
+ {
+ nrf_memobj_get(p_msg);
+
+ UNUSED_RETURN_VALUE(message_enqueue(mp_crashlog_queue, p_msg));
+ }
+
+ if (m_state == LOG_BACKEND_FLASH_IN_PANIC)
+ {
+ log_msg_queue_process(mp_crashlog_queue, true);
+ }
+}
+
+void nrf_log_backend_flashlog_flush(nrf_log_backend_t const * p_backend)
+{
+ queue_element_drop(mp_flashlog_queue);
+}
+
+void nrf_log_backend_crashlog_flush(nrf_log_backend_t const * p_backend)
+{
+ queue_element_drop(mp_crashlog_queue);
+}
+
+void nrf_log_backend_flashlog_panic_set(nrf_log_backend_t const * p_backend)
+{
+ /* Empty */
+}
+
+/**
+ * @brief Function for injecting log message which will indicate start of crash log.
+ */
+static void crashlog_marker_inject(void)
+{
+ nrf_log_header_t crashlog_marker_hdr = {
+ .base = {
+ .std = {
+ .type = HEADER_TYPE_STD,
+ .severity = NRF_LOG_SEVERITY_INFO_RAW,
+ .nargs = 0,
+ .addr = (uint32_t)crashlog_str & STD_ADDR_MASK
+ }
+ },
+ .module_id = 0,
+ .timestamp = 0,
+ };
+ m_flash_buf[0] = crashlog_marker_hdr.base.raw;
+ m_flash_buf[1] = crashlog_marker_hdr.module_id;
+ m_flash_buf[2] = crashlog_marker_hdr.timestamp;
+ (void)nrf_fstorage_write(&m_log_flash_fstorage, m_curr_addr, m_flash_buf, LOG_HEADER_LEN, NULL);
+ m_curr_addr += LOG_HEADER_LEN;
+}
+
+
+void nrf_log_backend_crashlog_panic_set(nrf_log_backend_t const * p_backend)
+{
+ if (nrf_fstorage_init(&m_log_flash_fstorage, &nrf_fstorage_nvmc, NULL) == NRF_SUCCESS)
+ {
+ m_state = LOG_BACKEND_FLASH_IN_PANIC;
+
+ /* In case of Softdevice MWU may protect access to NVMC. */
+ NVIC_DisableIRQ(MWU_IRQn);
+
+ log_msg_queue_process(mp_flashlog_queue, true);
+
+ crashlog_marker_inject();
+
+ log_msg_queue_process(mp_crashlog_queue, true);
+ }
+ else
+ {
+ m_state = LOG_BACKEND_FLASH_INACTIVE;
+ }
+}
+
+/**
+ * @brief Function for determining first empty location in area dedicated for flash logger backend.
+ */
+static uint32_t empty_addr_get(void)
+{
+ uint32_t token = 0;
+ nrf_log_header_t * p_dummy_header;
+ uint8_t * p_dummy_data;
+
+ while(nrf_log_backend_flash_next_entry_get(&token, &p_dummy_header, &p_dummy_data) == NRF_SUCCESS)
+ {
+
+ }
+
+ return token;
+}
+
+
+ret_code_t nrf_log_backend_flash_init(nrf_fstorage_api_t const * p_fs_api)
+{
+ ret_code_t err_code;
+
+
+ uint32_t start_addr = RUNTIME_START_ADDR;
+ uint32_t end_addr = start_addr + FLASH_LOG_SIZE - 1;
+
+ m_log_flash_fstorage.start_addr = start_addr;
+ m_log_flash_fstorage.end_addr = end_addr;
+
+ err_code = nrf_fstorage_init(&m_log_flash_fstorage, p_fs_api, NULL);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ m_curr_addr = empty_addr_get();
+ m_state = LOG_BACKEND_FLASH_ACTIVE;
+
+ return err_code;
+}
+
+
+ret_code_t nrf_log_backend_flash_next_entry_get(uint32_t * p_token,
+ nrf_log_header_t * * pp_header,
+ uint8_t * * pp_data)
+{
+ uint32_t * p_addr = p_token;
+ uint32_t len;
+
+ *p_addr = (*p_addr == 0) ? RUNTIME_START_ADDR : *p_addr;
+
+ if (nrf_fstorage_rmap(&m_log_flash_fstorage, *p_addr) == NULL)
+ {
+ //Supports only memories which can be mapped for reading.
+ return NRF_ERROR_NOT_SUPPORTED;
+ }
+
+ if (msg_from_buf((uint32_t *)*p_addr, pp_header, pp_data, &len))
+ {
+ *p_addr += len;
+ return NRF_SUCCESS;
+ }
+ else
+ {
+ return NRF_ERROR_NOT_FOUND;
+ }
+}
+
+
+ret_code_t nrf_log_backend_flash_erase(void)
+{
+ ret_code_t err_code;
+
+ m_state = LOG_BACKEND_FLASH_INACTIVE;
+ err_code = nrf_fstorage_erase(&m_log_flash_fstorage, RUNTIME_START_ADDR, NRF_LOG_BACKEND_PAGES, NULL);
+
+ m_curr_addr = RUNTIME_START_ADDR;
+
+ return err_code;
+}
+
+#if NRF_LOG_BACKEND_FLASHLOG_ENABLED
+const nrf_log_backend_api_t nrf_log_backend_flashlog_api = {
+ .put = nrf_log_backend_flashlog_put,
+ .flush = nrf_log_backend_flashlog_flush,
+ .panic_set = nrf_log_backend_flashlog_panic_set,
+};
+#endif
+
+#if NRF_LOG_BACKEND_CRASHLOG_ENABLED
+const nrf_log_backend_api_t nrf_log_backend_crashlog_api = {
+ .put = nrf_log_backend_crashlog_put,
+ .flush = nrf_log_backend_crashlog_flush,
+ .panic_set = nrf_log_backend_crashlog_panic_set,
+};
+#endif
+
+#if NRF_LOG_BACKEND_FLASH_CLI_CMDS
+#include "nrf_cli.h"
+
+static uint8_t m_buffer[64];
+static nrf_cli_t const * mp_cli;
+
+static void cli_tx(void const * p_context, char const * p_buffer, size_t len);
+
+static nrf_fprintf_ctx_t m_fprintf_ctx =
+{
+ .p_io_buffer = (char *)m_buffer,
+ .io_buffer_size = sizeof(m_buffer)-1,
+ .io_buffer_cnt = 0,
+ .auto_flush = true,
+ .p_user_ctx = &mp_cli,
+ .fwrite = cli_tx
+};
+
+
+static void flashlog_clear_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
+{
+ if (nrf_cli_help_requested(p_cli))
+ {
+ nrf_cli_help_print(p_cli, NULL, 0);
+ }
+
+ UNUSED_RETURN_VALUE(nrf_log_backend_flash_erase());
+}
+
+#include "nrf_delay.h"
+static void cli_tx(void const * p_context, char const * p_buffer, size_t len)
+{
+ nrf_cli_t * * pp_cli = (nrf_cli_t * *)p_context;
+ char * p_strbuf = (char *)&p_buffer[len];
+ *p_strbuf = '\0';
+ nrf_cli_fprintf((nrf_cli_t const *)*pp_cli, NRF_CLI_DEFAULT, p_buffer);
+ // nrf_delay_ms(10);
+}
+
+
+static void entry_process(nrf_cli_t const * p_cli, nrf_log_header_t * p_header, uint8_t * p_data)
+{
+ mp_cli = p_cli;
+
+ nrf_log_str_formatter_entry_params_t params =
+ {
+ .timestamp = p_header->timestamp,
+ .module_id = p_header->module_id,
+ .use_colors = 0,
+ };
+
+ switch (p_header->base.generic.type)
+ {
+ case HEADER_TYPE_STD:
+ {
+ params.severity = (nrf_log_severity_t)p_header->base.std.severity;
+ nrf_log_std_entry_process((const char *)((uint32_t)p_header->base.std.addr),
+ (uint32_t *)p_data,
+ p_header->base.std.nargs,
+ &params,
+ &m_fprintf_ctx);
+ break;
+ }
+ case HEADER_TYPE_HEXDUMP:
+ {
+ params.severity = (nrf_log_severity_t)p_header->base.hexdump.severity;
+
+ nrf_log_hexdump_entry_process(p_data,
+ p_header->base.hexdump.len,
+ &params,
+ &m_fprintf_ctx);
+ break;
+ }
+ default:
+ ASSERT(0);
+ }
+
+}
+
+
+static void flashlog_read_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
+{
+ if (nrf_cli_help_requested(p_cli))
+ {
+ nrf_cli_help_print(p_cli, NULL, 0);
+ }
+
+ uint32_t token = 0;
+ uint8_t * p_data = NULL;
+ bool empty = true;
+ nrf_log_header_t * p_header;
+
+ while (1)
+ {
+ if (nrf_log_backend_flash_next_entry_get(&token, &p_header, &p_data) == NRF_SUCCESS)
+ {
+ entry_process(p_cli, p_header, p_data);
+ empty = false;
+ }
+ else
+ {
+ break;
+ }
+ }
+
+ if (empty)
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Flash log empty\r\n");
+ }
+}
+
+
+static void flashlog_status_cmd(nrf_cli_t const * p_cli, size_t argc, char ** argv)
+{
+ if (nrf_cli_help_requested(p_cli))
+ {
+ nrf_cli_help_print(p_cli, NULL, 0);
+ }
+
+ nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "Flash log status:\r\n");
+ nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Location (address: 0x%08X, length: %d)\r\n",
+ RUNTIME_START_ADDR, FLASH_LOG_SIZE);
+ nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Current usage:%d%% (%d of %d bytes used)\r\n",
+ 100ul * (m_curr_addr - RUNTIME_START_ADDR)/FLASH_LOG_SIZE,
+ m_curr_addr - RUNTIME_START_ADDR,
+ FLASH_LOG_SIZE);
+ nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "\t\t- Dropped logs: %d\r\n", m_dropped);
+
+
+}
+
+
+NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_flashlog_cmd)
+{
+ NRF_CLI_CMD(clear, NULL, "Remove logs", flashlog_clear_cmd),
+ NRF_CLI_CMD(read, NULL, "Read stored logs", flashlog_read_cmd),
+ NRF_CLI_CMD(status, NULL, "Flash log status", flashlog_status_cmd),
+ NRF_CLI_SUBCMD_SET_END
+};
+
+NRF_CLI_CMD_REGISTER(flashlog, &m_flashlog_cmd, "Commands for reading logs stored in non-volatile memory", NULL);
+
+#endif //NRF_LOG_BACKEND_FLASH_CLI_CMDS
+
+#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_FLASH)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_rtt.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_rtt.c
new file mode 100644
index 0000000..1ff3a26
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_rtt.c
@@ -0,0 +1,123 @@
+/**
+ * Copyright (c) 2016 - 2018, 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) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT)
+#include "nrf_log_backend_rtt.h"
+#include "nrf_log_backend_serial.h"
+#include "nrf_log_str_formatter.h"
+#include "nrf_log_internal.h"
+#include "nrf_delay.h"
+#include <SEGGER_RTT_Conf.h>
+#include <SEGGER_RTT.h>
+
+static bool m_host_present;
+
+static uint8_t m_string_buff[NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE];
+
+void nrf_log_backend_rtt_init(void)
+{
+ SEGGER_RTT_Init();
+}
+
+static void serial_tx(void const * p_context, char const * buffer, size_t len)
+{
+ if (len)
+ {
+ uint32_t idx = 0;
+ uint32_t processed;
+ uint32_t watchdog_counter = NRF_LOG_BACKEND_RTT_TX_RETRY_CNT;
+ do
+ {
+ processed = SEGGER_RTT_WriteNoLock(0, &buffer[idx], len);
+ idx += processed;
+ len -= processed;
+ if (processed == 0)
+ {
+ /* There are two possible reasons for not writing any data to RTT:
+ * - The host is not connected and not reading the data.
+ * - The buffer got full and will be read by the host.
+ * These two situations are distinguished using the following algorithm.
+ * At the begining, the module assumes that the host is active,
+ * so when no data is read, it busy waits and retries.
+ * If, after retrying, the host reads the data, the module assumes that the host is active.
+ * If it fails, the module assumes that the host is inactive and stores that information. On next
+ * call, only one attempt takes place. The host is marked as active if the attempt is successful.
+ */
+ if (!m_host_present)
+ {
+ break;
+ }
+ else
+ {
+ nrf_delay_ms(NRF_LOG_BACKEND_RTT_TX_RETRY_DELAY_MS);
+ watchdog_counter--;
+ if (watchdog_counter == 0)
+ {
+ m_host_present = false;
+ break;
+ }
+ }
+ }
+ m_host_present = true;
+ } while (len);
+ }
+}
+static void nrf_log_backend_rtt_put(nrf_log_backend_t const * p_backend,
+ nrf_log_entry_t * p_msg)
+{
+ nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff, NRF_LOG_BACKEND_RTT_TEMP_BUFFER_SIZE, serial_tx);
+}
+
+static void nrf_log_backend_rtt_flush(nrf_log_backend_t const * p_backend)
+{
+
+}
+
+static void nrf_log_backend_rtt_panic_set(nrf_log_backend_t const * p_backend)
+{
+
+}
+
+const nrf_log_backend_api_t nrf_log_backend_rtt_api = {
+ .put = nrf_log_backend_rtt_put,
+ .flush = nrf_log_backend_rtt_flush,
+ .panic_set = nrf_log_backend_rtt_panic_set,
+};
+#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_RTT)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.c
new file mode 100644
index 0000000..7db0074
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.c
@@ -0,0 +1,115 @@
+/**
+ * Copyright (c) 2016 - 2018, 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_serial.h"
+#include "nrf_log_str_formatter.h"
+#include "nrf_log_internal.h"
+
+void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend,
+ nrf_log_entry_t * p_msg,
+ uint8_t * p_buffer,
+ uint32_t length,
+ nrf_fprintf_fwrite tx_func)
+{
+ nrf_memobj_get(p_msg);
+
+ nrf_fprintf_ctx_t fprintf_ctx = {
+ .p_io_buffer = (char *)p_buffer,
+ .io_buffer_size = length,
+ .io_buffer_cnt = 0,
+ .auto_flush = false,
+ .p_user_ctx = NULL,
+ .fwrite = tx_func
+ };
+
+ nrf_log_str_formatter_entry_params_t params;
+
+ nrf_log_header_t header;
+ uint32_t memobj_offset = 0;
+ nrf_memobj_read(p_msg, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset);
+ memobj_offset = HEADER_SIZE*sizeof(uint32_t);
+
+ params.timestamp = header.timestamp;
+ params.module_id = header.module_id;
+ params.dropped = header.dropped;
+ params.use_colors = NRF_LOG_USES_COLORS;
+
+ /*lint -save -e438*/
+ if (header.base.generic.type == HEADER_TYPE_STD)
+ {
+ char const * p_log_str = (char const *)((uint32_t)header.base.std.addr);
+ params.severity = (nrf_log_severity_t)header.base.std.severity;
+ uint32_t nargs = header.base.std.nargs;
+ uint32_t args[NRF_LOG_MAX_NUM_OF_ARGS];
+
+ nrf_memobj_read(p_msg, args, nargs*sizeof(uint32_t), memobj_offset);
+ memobj_offset += (nargs*sizeof(uint32_t));
+
+ nrf_log_std_entry_process(p_log_str,
+ args,
+ nargs,
+ &params,
+ &fprintf_ctx);
+
+ }
+ else if (header.base.generic.type == HEADER_TYPE_HEXDUMP)
+ {
+ uint32_t data_len = header.base.hexdump.len;
+ params.severity = (nrf_log_severity_t)header.base.hexdump.severity;
+ uint8_t data_buf[8];
+ uint32_t chunk_len;
+ do
+ {
+ chunk_len = sizeof(data_buf) > data_len ? data_len : sizeof(data_buf);
+ nrf_memobj_read(p_msg, data_buf, chunk_len, memobj_offset);
+ memobj_offset += chunk_len;
+ data_len -= chunk_len;
+
+ nrf_log_hexdump_entry_process(data_buf,
+ chunk_len,
+ &params,
+ &fprintf_ctx);
+ } while (data_len > 0);
+ }
+ nrf_memobj_put(p_msg);
+ /*lint -restore*/
+}
+#endif //NRF_LOG_ENABLED
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.h
new file mode 100644
index 0000000..22d26f5
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_serial.h
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2017 - 2018, 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_BACKEND_SERIAL_H
+#define NRF_LOG_BACKEND_SERIAL_H
+/**@file
+ * @addtogroup nrf_log Logger module
+ * @ingroup app_common
+ *
+ * @defgroup nrf_log_backend_serial Common part of serial backends
+ * @{
+ * @ingroup nrf_log
+ * @brief The nrf_log serial backend common put function.
+ */
+
+
+#include "nrf_log_backend_interface.h"
+#include "nrf_fprintf.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * @brief A function for processing logger entry with simple serial interface as output.
+ *
+ *
+ */
+void nrf_log_backend_serial_put(nrf_log_backend_t const * p_backend,
+ nrf_log_entry_t * p_msg,
+ uint8_t * p_buffer,
+ uint32_t length,
+ nrf_fprintf_fwrite tx_func);
+
+#endif //NRF_LOG_BACKEND_SERIAL_H
+
+#ifdef __cplusplus
+}
+#endif
+
+/** @} */
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_uart.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_uart.c
new file mode 100644
index 0000000..76dad8a
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_backend_uart.c
@@ -0,0 +1,116 @@
+/**
+ * Copyright (c) 2016 - 2018, 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) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART)
+#include "nrf_log_backend_uart.h"
+#include "nrf_log_backend_serial.h"
+#include "nrf_log_internal.h"
+#include "nrf_drv_uart.h"
+#include "app_error.h"
+
+nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(0);
+
+static uint8_t m_string_buff[NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE];
+static volatile bool m_xfer_done;
+static bool m_async_mode;
+static void uart_evt_handler(nrf_drv_uart_event_t * p_event, void * p_context)
+{
+ m_xfer_done = true;
+}
+
+static void uart_init(bool async_mode)
+{
+ nrf_drv_uart_config_t config = NRF_DRV_UART_DEFAULT_CONFIG;
+ config.pseltxd = NRF_LOG_BACKEND_UART_TX_PIN;
+ config.pselrxd = NRF_UART_PSEL_DISCONNECTED;
+ config.pselcts = NRF_UART_PSEL_DISCONNECTED;
+ config.pselrts = NRF_UART_PSEL_DISCONNECTED;
+ config.baudrate = (nrf_uart_baudrate_t)NRF_LOG_BACKEND_UART_BAUDRATE;
+ ret_code_t err_code = nrf_drv_uart_init(&m_uart, &config, async_mode ? uart_evt_handler : NULL);
+ APP_ERROR_CHECK(err_code);
+
+ m_async_mode = async_mode;
+}
+
+void nrf_log_backend_uart_init(void)
+{
+ bool async_mode = NRF_LOG_DEFERRED ? true : false;
+ uart_init(async_mode);
+}
+
+static void serial_tx(void const * p_context, char const * p_buffer, size_t len)
+{
+ uint8_t len8 = (uint8_t)(len & 0x000000FF);
+ m_xfer_done = false;
+ ret_code_t err_code = nrf_drv_uart_tx(&m_uart, (uint8_t *)p_buffer, len8);
+ APP_ERROR_CHECK(err_code);
+ /* wait for completion since buffer is reused*/
+ while (m_async_mode && (m_xfer_done == false))
+ {
+
+ }
+
+}
+
+static void nrf_log_backend_uart_put(nrf_log_backend_t const * p_backend,
+ nrf_log_entry_t * p_msg)
+{
+ nrf_log_backend_serial_put(p_backend, p_msg, m_string_buff,
+ NRF_LOG_BACKEND_UART_TEMP_BUFFER_SIZE, serial_tx);
+}
+
+static void nrf_log_backend_uart_flush(nrf_log_backend_t const * p_backend)
+{
+
+}
+
+static void nrf_log_backend_uart_panic_set(nrf_log_backend_t const * p_backend)
+{
+ nrf_drv_uart_uninit(&m_uart);
+
+ uart_init(false);
+}
+
+const nrf_log_backend_api_t nrf_log_backend_uart_api = {
+ .put = nrf_log_backend_uart_put,
+ .flush = nrf_log_backend_uart_flush,
+ .panic_set = nrf_log_backend_uart_panic_set,
+};
+#endif //NRF_MODULE_ENABLED(NRF_LOG) && NRF_MODULE_ENABLED(NRF_LOG_BACKEND_UART)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_ctrl_internal.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_ctrl_internal.h
new file mode 100644
index 0000000..ba8a574
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_ctrl_internal.h
@@ -0,0 +1,80 @@
+/**
+ * Copyright (c) 2016 - 2018, 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)
+#define NRF_LOG_INTERNAL_INIT(...) \
+ nrf_log_init(GET_VA_ARG_1(__VA_ARGS__), \
+ GET_VA_ARG_1(GET_ARGS_AFTER_1(__VA_ARGS__, NRF_LOG_TIMESTAMP_DEFAULT_FREQUENCY)))
+
+#define NRF_LOG_INTERNAL_PROCESS() nrf_log_frontend_dequeue()
+#define NRF_LOG_INTERNAL_FLUSH() \
+ do { \
+ while (NRF_LOG_INTERNAL_PROCESS()); \
+ } while (0)
+
+#define NRF_LOG_INTERNAL_FINAL_FLUSH() \
+ do { \
+ nrf_log_panic(); \
+ NRF_LOG_INTERNAL_FLUSH(); \
+ } while (0)
+
+
+#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
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_default_backends.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_default_backends.c
new file mode 100644
index 0000000..c844f2e
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_default_backends.c
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2017 - 2018, 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_default_backends.h"
+#include "nrf_log_ctrl.h"
+#include "nrf_log_internal.h"
+#include "nrf_assert.h"
+
+#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED
+#include "nrf_log_backend_rtt.h"
+NRF_LOG_BACKEND_RTT_DEF(rtt_log_backend);
+#endif
+
+#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED
+#include "nrf_log_backend_uart.h"
+NRF_LOG_BACKEND_UART_DEF(uart_log_backend);
+#endif
+
+void nrf_log_default_backends_init(void)
+{
+ int32_t backend_id = -1;
+ (void)backend_id;
+#if defined(NRF_LOG_BACKEND_RTT_ENABLED) && NRF_LOG_BACKEND_RTT_ENABLED
+ nrf_log_backend_rtt_init();
+ backend_id = nrf_log_backend_add(&rtt_log_backend.backend, NRF_LOG_SEVERITY_DEBUG);
+ ASSERT(backend_id >= 0);
+ nrf_log_backend_enable(&rtt_log_backend.backend);
+#endif
+
+#if defined(NRF_LOG_BACKEND_UART_ENABLED) && NRF_LOG_BACKEND_UART_ENABLED
+ nrf_log_backend_uart_init();
+ backend_id = nrf_log_backend_add(&uart_log_backend.backend, NRF_LOG_SEVERITY_DEBUG);
+ ASSERT(backend_id >= 0);
+ nrf_log_backend_enable(&uart_log_backend.backend);
+#endif
+}
+#endif
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_frontend.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_frontend.c
new file mode 100644
index 0000000..4e65702
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_frontend.c
@@ -0,0 +1,1245 @@
+/**
+ * Copyright (c) 2016 - 2018, 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_ctrl.h"
+#include "nrf_log_str_formatter.h"
+#include "nrf_section.h"
+#include "nrf_memobj.h"
+#include "nrf_atomic.h"
+#include <string.h>
+
+STATIC_ASSERT((NRF_LOG_BUFSIZE % 4) == 0);
+STATIC_ASSERT(IS_POWER_OF_TWO(NRF_LOG_BUFSIZE));
+
+#define NRF_LOG_BUF_WORDS (NRF_LOG_BUFSIZE/4)
+
+#if NRF_LOG_BUF_WORDS < 32
+#warning "NRF_LOG_BUFSIZE too small, significant number of logs may be lost."
+#endif
+
+NRF_MEMOBJ_POOL_DEF(log_mempool, NRF_LOG_MSGPOOL_ELEMENT_SIZE, NRF_LOG_MSGPOOL_ELEMENT_COUNT);
+
+#define NRF_LOG_BACKENDS_FULL 0xFF
+#define NRF_LOG_FILTER_BITS_PER_BACKEND 3
+#define NRF_LOG_MAX_BACKENDS (32/NRF_LOG_FILTER_BITS_PER_BACKEND)
+#define NRF_LOG_MAX_HEXDUMP (NRF_LOG_MSGPOOL_ELEMENT_SIZE*NRF_LOG_MSGPOOL_ELEMENT_COUNT/2)
+
+/**
+ * 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_BUF_WORDS];
+ nrf_log_timestamp_func_t timestamp_func; // A pointer to function that returns timestamp
+ nrf_log_backend_t * p_backend_head;
+ nrf_atomic_flag_t log_skipping;
+ nrf_atomic_flag_t log_skipped;
+ nrf_atomic_u32_t log_dropped_cnt;
+ bool autoflush;
+} log_data_t;
+
+static log_data_t m_log_data;
+
+/*lint -save -esym(526,log_const_data*) -esym(526,log_dynamic_data*)*/
+NRF_SECTION_DEF(log_dynamic_data, NRF_LOG_DYNAMIC_STRUCT_NAME);
+NRF_SECTION_DEF(log_const_data, nrf_log_module_const_data_t);
+/*lint -restore*/
+NRF_LOG_MODULE_REGISTER();
+// Helper macros for section variables.
+#define NRF_LOG_DYNAMIC_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_dynamic_data, NRF_LOG_DYNAMIC_STRUCT_NAME, (i))
+
+#define NRF_LOG_CONST_SECTION_VARS_GET(i) NRF_SECTION_ITEM_GET(log_const_data, nrf_log_module_const_data_t, (i))
+#define NRF_LOG_CONST_SECTION_VARS_COUNT NRF_SECTION_ITEM_COUNT(log_const_data, nrf_log_module_const_data_t)
+
+#define PUSHED_HEADER_FILL(P_HDR, OFFSET, LENGTH) \
+ (P_HDR)->base.raw = 0; \
+ (P_HDR)->base.pushed.type = HEADER_TYPE_PUSHED; \
+ (P_HDR)->base.pushed.offset = OFFSET; \
+ (P_HDR)->base.pushed.len = LENGTH
+
+
+ret_code_t nrf_log_init(nrf_log_timestamp_func_t timestamp_func, uint32_t timestamp_freq)
+{
+ if (NRF_LOG_USES_TIMESTAMP && (timestamp_func == NULL))
+ {
+ return NRF_ERROR_INVALID_PARAM;
+ }
+
+ m_log_data.mask = NRF_LOG_BUF_WORDS - 1;
+ m_log_data.wr_idx = 0;
+ m_log_data.rd_idx = 0;
+ m_log_data.log_skipped = 0;
+ m_log_data.log_skipping = 0;
+ m_log_data.autoflush = NRF_LOG_DEFERRED ? false : true;
+ if (NRF_LOG_USES_TIMESTAMP)
+ {
+ nrf_log_str_formatter_timestamp_freq_set(timestamp_freq);
+ m_log_data.timestamp_func = timestamp_func;
+ }
+
+ ret_code_t err_code = nrf_memobj_pool_init(&log_mempool);
+ if (err_code != NRF_SUCCESS)
+ {
+ return err_code;
+ }
+
+ uint32_t modules_cnt = NRF_LOG_CONST_SECTION_VARS_COUNT;
+ uint32_t i;
+ if (NRF_LOG_FILTERS_ENABLED)
+ {
+ uint32_t j;
+ //sort modules by name
+ for (i = 0; i < modules_cnt; i++)
+ {
+ uint32_t idx = 0;
+
+ for (j = 0; j < modules_cnt; j++)
+ {
+ if (i != j)
+ {
+ char const * p_name0 = NRF_LOG_CONST_SECTION_VARS_GET(i)->p_module_name;
+ char const * p_name1 = NRF_LOG_CONST_SECTION_VARS_GET(j)->p_module_name;
+ if (strncmp(p_name0, p_name1, 20) > 0)
+ {
+ idx++;
+ }
+ }
+
+ }
+ nrf_log_module_dynamic_data_t * p_module_ddata =
+ (nrf_log_module_dynamic_data_t *)NRF_LOG_DYNAMIC_SECTION_VARS_GET(i);
+ p_module_ddata->filter = 0;
+ p_module_ddata->module_id = i;
+ p_module_ddata->order_idx = idx;
+ }
+ }
+ else
+ {
+ for(i = 0; i < modules_cnt; i++)
+ {
+ nrf_log_module_reduced_dynamic_data_t * p_module_ddata =
+ (nrf_log_module_reduced_dynamic_data_t *)NRF_LOG_DYNAMIC_SECTION_VARS_GET(i);
+ p_module_ddata->module_id = i;
+ }
+ }
+
+ return NRF_SUCCESS;
+}
+
+uint32_t nrf_log_module_cnt_get(void)
+{
+ return NRF_LOG_CONST_SECTION_VARS_COUNT;
+}
+
+static ret_code_t module_idx_get(uint32_t * p_idx, bool ordered_idx)
+{
+ if (ordered_idx)
+ {
+ uint32_t module_cnt = nrf_log_module_cnt_get();
+ uint32_t i;
+ for (i = 0; i < module_cnt; i++)
+ {
+ nrf_log_module_dynamic_data_t * p_module_data =
+ (nrf_log_module_dynamic_data_t *)NRF_LOG_DYNAMIC_SECTION_VARS_GET(i);
+ if (p_module_data->order_idx == *p_idx)
+ {
+ *p_idx = i;
+ return NRF_SUCCESS;
+ }
+ }
+ return NRF_ERROR_NOT_FOUND;
+ }
+ else
+ {
+ return NRF_SUCCESS;
+ }
+}
+const char * nrf_log_module_name_get(uint32_t module_id, bool ordered_idx)
+{
+ if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS)
+ {
+ nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id);
+ return p_module_data->p_module_name;
+ }
+ else
+ {
+ return NULL;
+ }
+}
+
+uint8_t nrf_log_color_id_get(uint32_t module_id, nrf_log_severity_t severity)
+{
+ nrf_log_module_const_data_t * p_module_data = NRF_LOG_CONST_SECTION_VARS_GET(module_id);
+ uint8_t color_id;
+ switch (severity)
+ {
+ case NRF_LOG_SEVERITY_ERROR:
+ color_id = NRF_LOG_ERROR_COLOR;
+ break;
+ case NRF_LOG_SEVERITY_WARNING:
+ color_id = NRF_LOG_WARNING_COLOR;
+ break;
+ case NRF_LOG_SEVERITY_INFO:
+ color_id = p_module_data->info_color_id;
+ break;
+ case NRF_LOG_SEVERITY_DEBUG:
+ color_id = p_module_data->debug_color_id;
+ break;
+ default:
+ color_id = 0;
+ break;
+ }
+ return color_id;
+}
+
+static uint32_t higher_lvl_get(uint32_t lvls)
+{
+ uint32_t top_lvl = 0;
+ uint32_t tmp_lvl;
+ uint32_t i;
+
+ //Find highest level enabled by backends
+ for (i = 0; i < (32/NRF_LOG_LEVEL_BITS); i+=NRF_LOG_LEVEL_BITS)
+ {
+ tmp_lvl = BF_GET(lvls,NRF_LOG_LEVEL_BITS, i);
+ if (tmp_lvl > top_lvl)
+ {
+ top_lvl = tmp_lvl;
+ }
+ }
+ return top_lvl;
+}
+
+void nrf_log_module_filter_set(uint32_t backend_id, uint32_t module_id, nrf_log_severity_t severity)
+{
+ if (NRF_LOG_FILTERS_ENABLED)
+ {
+ nrf_log_module_dynamic_data_t * p_module_filter =
+ (nrf_log_module_dynamic_data_t *)NRF_LOG_DYNAMIC_SECTION_VARS_GET(module_id);
+ p_module_filter->filter_lvls &= ~(NRF_LOG_LEVEL_MASK << (NRF_LOG_LEVEL_BITS * backend_id));
+ p_module_filter->filter_lvls |= (severity & NRF_LOG_LEVEL_MASK) << (NRF_LOG_LEVEL_BITS * backend_id);
+ p_module_filter->filter = higher_lvl_get(p_module_filter->filter_lvls);
+ }
+}
+
+static nrf_log_severity_t nrf_log_module_init_filter_get(uint32_t module_id)
+{
+ nrf_log_module_const_data_t * p_module_data =
+ NRF_LOG_CONST_SECTION_VARS_GET(module_id);
+ return NRF_LOG_FILTERS_ENABLED ? p_module_data->initial_lvl : p_module_data->compiled_lvl;
+}
+
+nrf_log_severity_t nrf_log_module_filter_get(uint32_t backend_id,
+ uint32_t module_id,
+ bool ordered_idx,
+ bool dynamic)
+{
+ nrf_log_severity_t severity = NRF_LOG_SEVERITY_NONE;
+ if (NRF_LOG_FILTERS_ENABLED && dynamic)
+ {
+ if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS)
+ {
+ nrf_log_module_dynamic_data_t * p_module_filter =
+ (nrf_log_module_dynamic_data_t *)NRF_LOG_DYNAMIC_SECTION_VARS_GET(module_id);
+ severity = (nrf_log_severity_t)((p_module_filter->filter_lvls >> (NRF_LOG_LEVEL_BITS * backend_id)) &
+ NRF_LOG_LEVEL_MASK);
+ }
+ }
+ else if (!dynamic)
+ {
+ if (module_idx_get(&module_id, ordered_idx) == NRF_SUCCESS)
+ {
+ nrf_log_module_const_data_t * p_module_data =
+ NRF_LOG_CONST_SECTION_VARS_GET(module_id);
+ severity = (nrf_log_severity_t)p_module_data->compiled_lvl;
+ }
+ }
+ return severity;
+}
+/**
+ * Function examines current header and omits pushed strings and packets which are in progress.
+ */
+static bool invalid_packets_pushed_str_omit(nrf_log_header_t const * p_header, uint32_t * p_rd_idx)
+{
+ bool ret = false;
+ if ((p_header->base.generic.type == HEADER_TYPE_PUSHED) || (p_header->base.generic.in_progress == 1))
+ {
+ if (p_header->base.generic.in_progress == 1)
+ {
+ switch (p_header->base.generic.type)
+ {
+ case HEADER_TYPE_STD:
+ *p_rd_idx += (HEADER_SIZE + p_header->base.std.nargs);
+ break;
+ case HEADER_TYPE_HEXDUMP:
+ *p_rd_idx += (HEADER_SIZE + p_header->base.hexdump.len);
+ break;
+ default:
+ ASSERT(0);
+ break;
+ }
+ }
+ else
+ {
+ *p_rd_idx +=
+ (PUSHED_HEADER_SIZE + p_header->base.pushed.len + p_header->base.pushed.offset);
+ }
+ ret = true;
+ }
+ return ret;
+}
+/**
+ * @brief Skips the oldest, not pushed logs to make space for new logs.
+ * @details This function moves forward read index to prepare space for new logs.
+ */
+
+static uint32_t log_skip(void)
+{
+ uint16_t dropped = 0;
+
+ (void)nrf_atomic_flag_set(&m_log_data.log_skipped);
+ (void)nrf_atomic_flag_set(&m_log_data.log_skipping);
+
+ uint32_t rd_idx = m_log_data.rd_idx;
+ uint32_t mask = m_log_data.mask;
+ nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask];
+ nrf_log_header_t header;
+
+ // Skip any string that is pushed to the circular buffer.
+ do {
+ if (invalid_packets_pushed_str_omit(p_header, &rd_idx))
+ {
+ //something was omitted. Point to new header and try again.
+ p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask];
+ }
+ else
+ {
+ break;
+ }
+ } while (true);
+
+ uint32_t i;
+ for (i = 0; i < HEADER_SIZE; i++)
+ {
+ ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask];
+ }
+
+ switch (header.base.generic.type)
+ {
+ case HEADER_TYPE_HEXDUMP:
+ dropped = header.dropped;
+ rd_idx += CEIL_DIV(header.base.hexdump.len, sizeof(uint32_t));
+ break;
+ case HEADER_TYPE_STD:
+ dropped = header.dropped;
+ rd_idx += header.base.std.nargs;
+ break;
+ default:
+ ASSERT(false);
+ break;
+ }
+
+ uint32_t log_skipping_tmp = nrf_atomic_flag_clear_fetch(&m_log_data.log_skipping);
+ //update read index only if log_skip was not interrupted by another log skip
+ if (log_skipping_tmp)
+ {
+ m_log_data.rd_idx = rd_idx;
+ }
+
+ return (uint32_t)dropped;
+}
+
+/**
+ * @brief Function for getting number of dropped logs. Dropped counter is reset after reading.
+ *
+ * @return Number of dropped logs saturated to 16 bits.
+ */
+static inline uint32_t dropped_sat16_get(void)
+{
+ uint32_t dropped = nrf_atomic_u32_fetch_store(&m_log_data.log_dropped_cnt, 0);
+ return __USAT(dropped, 16); //Saturate to 16 bits
+}
+
+
+static inline void std_header_set(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t nargs,
+ uint32_t wr_idx,
+ uint32_t mask)
+{
+
+
+ //Prepare header - in reverse order to ensure that packet type is validated (set to STD as last action)
+ uint32_t module_id = severity_mid >> NRF_LOG_MODULE_ID_POS;
+ uint32_t dropped = dropped_sat16_get();
+ ASSERT(module_id < nrf_log_module_cnt_get());
+ m_log_data.buffer[(wr_idx + 1) & mask] = module_id | (dropped << 16);
+
+ if (NRF_LOG_USES_TIMESTAMP)
+ {
+ m_log_data.buffer[(wr_idx + 2) & mask] = m_log_data.timestamp_func();
+ }
+
+ nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[wr_idx & mask];
+ p_header->base.std.severity = severity_mid & NRF_LOG_LEVEL_MASK;
+ p_header->base.std.nargs = nargs;
+ p_header->base.std.addr = ((uint32_t)(p_str) & STD_ADDR_MASK);
+ p_header->base.std.type = HEADER_TYPE_STD;
+ p_header->base.std.in_progress = 0;
+}
+
+/**
+ * @brief Allocates chunk in a buffer for one entry and injects overflow if
+ * there is no room for requested entry.
+ *
+ * @param content_len 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 content_len, uint32_t * p_wr_idx, bool std)
+{
+ uint32_t req_len = content_len + 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);
+ while (req_len > available_words)
+ {
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_log_data.log_dropped_cnt, 1));
+ if (NRF_LOG_ALLOW_OVERFLOW)
+ {
+ uint32_t dropped_in_skip = log_skip();
+ UNUSED_RETURN_VALUE(nrf_atomic_u32_add(&m_log_data.log_dropped_cnt, dropped_in_skip));
+ available_words = (m_log_data.mask + 1) - (m_log_data.wr_idx - m_log_data.rd_idx);
+ }
+ else
+ {
+ ret = false;
+ break;
+ }
+ }
+
+ if (ret)
+ {
+ nrf_log_main_header_t invalid_header;
+ invalid_header.raw = 0;
+
+ if (std)
+ {
+ invalid_header.std.type = HEADER_TYPE_STD;
+ invalid_header.std.in_progress = 1;
+ invalid_header.std.nargs = content_len;
+ }
+ else
+ {
+ invalid_header.hexdump.type = HEADER_TYPE_HEXDUMP;
+ invalid_header.hexdump.in_progress = 1;
+ invalid_header.hexdump.len = content_len;
+ }
+
+ nrf_log_main_header_t * p_header = (nrf_log_main_header_t *)&m_log_data.buffer[m_log_data.wr_idx & m_log_data.mask];
+
+ p_header->raw = invalid_header.raw;
+
+ m_log_data.wr_idx += req_len;
+ }
+
+ 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)
+{
+ //allocation algorithm relies on that assumption
+ STATIC_ASSERT(PUSHED_HEADER_SIZE == 1);
+ uint32_t * p_buf = NULL;
+
+ len32 += PUSHED_HEADER_SIZE; // 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.rd_idx);
+ uint32_t tail_words = (m_log_data.mask + 1) - (m_log_data.wr_idx & m_log_data.mask);
+
+ //available space is continuous
+ uint32_t curr_pos_available = (available_words <= tail_words) ? available_words : tail_words;
+ uint32_t start_pos_available = (available_words <= tail_words) ? 0 : (available_words - tail_words);
+
+ if ((len32 <= curr_pos_available) ||
+ ((len32 - PUSHED_HEADER_SIZE) <= start_pos_available))
+ {
+ // buffer will fit in the tail or in the begining
+ // non zero offset is set if string is put at the beginning of the buffer
+ *p_offset = (len32 <= curr_pos_available) ? 0 : (tail_words - PUSHED_HEADER_SIZE);
+ uint32_t str_start_idx =
+ (m_log_data.wr_idx + PUSHED_HEADER_SIZE + *p_offset) & m_log_data.mask;
+ p_buf = &m_log_data.buffer[str_start_idx];
+ // index is incremented by payload and offset
+ m_log_data.wr_idx += (len32 + *p_offset);
+ }
+
+ CRITICAL_REGION_EXIT();
+
+ return p_buf;
+}
+
+
+uint32_t nrf_log_push(char * const p_str)
+{
+ if ((m_log_data.autoflush) || (p_str == NULL))
+ {
+ return (uint32_t)p_str;
+ }
+
+ uint32_t mask = m_log_data.mask;
+ uint32_t slen = strlen(p_str) + 1;
+ uint32_t buflen = CEIL_DIV(slen, sizeof(uint32_t));
+ uint32_t offset = 0;
+ uint32_t wr_idx;
+ char * p_dst_str = (char *)cont_buf_prealloc(buflen, &offset, &wr_idx);
+ if (p_dst_str)
+ {
+ nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[wr_idx & mask];
+ PUSHED_HEADER_FILL(p_header, offset, buflen);
+ memcpy(p_dst_str, p_str, slen);
+ }
+ return (uint32_t)p_dst_str;
+}
+
+static inline void std_n(uint32_t severity_mid, char const * const p_str, uint32_t const * args, uint32_t nargs)
+{
+ uint32_t mask = m_log_data.mask;
+ uint32_t wr_idx;
+
+ if (buf_prealloc(nargs, &wr_idx, true))
+ {
+ // Proceed only if buffer was successfully preallocated.
+
+ uint32_t data_idx = wr_idx + HEADER_SIZE;
+ uint32_t i;
+ for (i = 0; i < nargs; i++)
+ {
+ m_log_data.buffer[data_idx++ & mask] =args[i];
+ }
+ std_header_set(severity_mid, p_str, nargs, wr_idx, mask);
+ }
+ if (m_log_data.autoflush)
+ {
+ NRF_LOG_FLUSH();
+ }
+
+}
+
+void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str)
+{
+ std_n(severity_mid, p_str, NULL, 0);
+}
+
+
+void nrf_log_frontend_std_1(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0)
+{
+ uint32_t args[] = {val0};
+ std_n(severity_mid, p_str, args, ARRAY_SIZE(args));
+}
+
+
+void nrf_log_frontend_std_2(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0,
+ uint32_t val1)
+{
+ uint32_t args[] = {val0, val1};
+ std_n(severity_mid, p_str, args, ARRAY_SIZE(args));
+}
+
+
+void nrf_log_frontend_std_3(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0,
+ uint32_t val1,
+ uint32_t val2)
+{
+ uint32_t args[] = {val0, val1, val2};
+ std_n(severity_mid, p_str, args, ARRAY_SIZE(args));
+}
+
+
+void nrf_log_frontend_std_4(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0,
+ uint32_t val1,
+ uint32_t val2,
+ uint32_t val3)
+{
+ uint32_t args[] = {val0, val1, val2, val3};
+ std_n(severity_mid, p_str, args, ARRAY_SIZE(args));
+}
+
+
+void nrf_log_frontend_std_5(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0,
+ uint32_t val1,
+ uint32_t val2,
+ uint32_t val3,
+ uint32_t val4)
+{
+ uint32_t args[] = {val0, val1, val2, val3, val4};
+ std_n(severity_mid, p_str, args, ARRAY_SIZE(args));
+}
+
+
+void nrf_log_frontend_std_6(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0,
+ uint32_t val1,
+ uint32_t val2,
+ uint32_t val3,
+ uint32_t val4,
+ uint32_t val5)
+{
+ uint32_t args[] = {val0, val1, val2, val3, val4, val5};
+ std_n(severity_mid, p_str, args, ARRAY_SIZE(args));
+}
+
+
+void nrf_log_frontend_hexdump(uint32_t severity_mid,
+ const void * const p_data,
+ uint16_t length)
+{
+ uint32_t mask = m_log_data.mask;
+
+ uint32_t wr_idx;
+ if (buf_prealloc(CEIL_DIV(length, sizeof(uint32_t)), &wr_idx, false))
+ {
+ uint32_t header_wr_idx = wr_idx;
+ wr_idx += HEADER_SIZE;
+
+ 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);
+ memcpy(&m_log_data.buffer[0], &((uint8_t *)p_data)[space0], length - space0);
+ }
+
+ //Prepare header - in reverse order to ensure that packet type is validated (set to HEXDUMP as last action)
+ if (NRF_LOG_USES_TIMESTAMP)
+ {
+ m_log_data.buffer[(header_wr_idx + 2) & mask] = m_log_data.timestamp_func();
+ }
+
+ uint32_t module_id = severity_mid >> NRF_LOG_MODULE_ID_POS;
+ uint32_t dropped = dropped_sat16_get();
+ m_log_data.buffer[(header_wr_idx + 1) & mask] = module_id | (dropped << 16);
+ //Header prepare
+ nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[header_wr_idx & mask];
+ p_header->base.hexdump.severity = severity_mid & NRF_LOG_LEVEL_MASK;
+ p_header->base.hexdump.offset = 0;
+ p_header->base.hexdump.len = length;
+ p_header->base.hexdump.type = HEADER_TYPE_HEXDUMP;
+ p_header->base.hexdump.in_progress = 0;
+
+
+
+ }
+
+ if (m_log_data.autoflush)
+ {
+ NRF_LOG_FLUSH();
+ }
+}
+
+
+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;
+ }
+ m_log_data.log_skipped = 0;
+ //It has to be ensured that reading rd_idx occurs after skipped flag is cleared.
+ __DSB();
+ uint32_t rd_idx = m_log_data.rd_idx;
+ uint32_t mask = m_log_data.mask;
+ nrf_log_header_t * p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask];
+ nrf_log_header_t header;
+ nrf_memobj_t * p_msg_buf = NULL;
+ uint32_t memobj_offset = 0;
+ uint32_t severity = 0;
+
+ // Skip any string that is pushed to the circular buffer.
+ do {
+ if (invalid_packets_pushed_str_omit(p_header, &rd_idx))
+ {
+ //Check if end of data is not reached.
+ if (rd_idx >= m_log_data.wr_idx)
+ {
+ m_log_data.rd_idx = m_log_data.wr_idx;
+ return false;
+ }
+ //something was omitted. Point to new header and try again.
+ p_header = (nrf_log_header_t *)&m_log_data.buffer[rd_idx & mask];
+ }
+ else
+ {
+ break;
+ }
+ } while (true);
+
+ uint32_t i;
+ for (i = 0; i < HEADER_SIZE; i++)
+ {
+ ((uint32_t*)&header)[i] = m_log_data.buffer[rd_idx++ & mask];
+ }
+
+ if (header.base.generic.type == HEADER_TYPE_HEXDUMP)
+ {
+ uint32_t orig_data_len = header.base.hexdump.len;
+ uint32_t data_len = MIN(header.base.hexdump.len, NRF_LOG_MAX_HEXDUMP); //limit the data
+ header.base.hexdump.len = data_len;
+ uint32_t msg_buf_size8 = sizeof(uint32_t)*HEADER_SIZE + data_len;
+ severity = header.base.hexdump.severity;
+ p_msg_buf = nrf_memobj_alloc(&log_mempool, msg_buf_size8);
+
+ if (p_msg_buf)
+ {
+ nrf_memobj_get(p_msg_buf);
+ nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset);
+ memobj_offset += HEADER_SIZE*sizeof(uint32_t);
+
+ uint32_t space0 = sizeof(uint32_t) * (mask + 1 - (rd_idx & mask));
+ if (data_len > 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 : data_len;
+ uint8_t * ptr1 = space0 ?
+ (uint8_t *)&m_log_data.buffer[0] : NULL;
+ uint8_t len1 = space0 ? data_len - space0 : 0;
+
+ nrf_memobj_write(p_msg_buf, ptr0, len0, memobj_offset);
+ memobj_offset += len0;
+ if (ptr1)
+ {
+ nrf_memobj_write(p_msg_buf, ptr1, len1, memobj_offset);
+ }
+ }
+ else
+ {
+ uint8_t * p_data = (uint8_t *)&m_log_data.buffer[rd_idx & mask];
+ nrf_memobj_write(p_msg_buf, p_data, data_len, memobj_offset);
+ }
+ rd_idx += CEIL_DIV(orig_data_len, 4);
+ }
+ }
+ else if (header.base.generic.type == HEADER_TYPE_STD) // standard entry
+ {
+ header.base.std.nargs = MIN(header.base.std.nargs, NRF_LOG_MAX_NUM_OF_ARGS);
+ uint32_t msg_buf_size32 = HEADER_SIZE + header.base.std.nargs;
+ severity = header.base.std.severity;
+
+ p_msg_buf = nrf_memobj_alloc(&log_mempool, msg_buf_size32*sizeof(uint32_t));
+
+ if (p_msg_buf)
+ {
+ nrf_memobj_get(p_msg_buf);
+ nrf_memobj_write(p_msg_buf, &header, HEADER_SIZE*sizeof(uint32_t), memobj_offset);
+ memobj_offset += HEADER_SIZE*sizeof(uint32_t);
+
+ for (i = 0; i < header.base.std.nargs; i++)
+ {
+ nrf_memobj_write(p_msg_buf, &m_log_data.buffer[rd_idx++ & mask],
+ sizeof(uint32_t), memobj_offset);
+ memobj_offset += sizeof(uint32_t);
+ }
+ }
+ }
+ else
+ {
+ //Do nothing. In case of log overflow buffer can contain corrupted data.
+ }
+
+ if (p_msg_buf)
+ {
+ nrf_log_backend_t * p_backend = m_log_data.p_backend_head;
+ if (NRF_LOG_ALLOW_OVERFLOW && m_log_data.log_skipped)
+ {
+ // Check if any log was skipped during log processing. Do not forward log if skipping
+ // occured because data may be invalid.
+ nrf_memobj_put(p_msg_buf);
+ }
+ else
+ {
+ while (p_backend)
+ {
+ bool entry_accepted = false;
+ if (nrf_log_backend_is_enabled(p_backend) == true)
+ {
+ if (NRF_LOG_FILTERS_ENABLED)
+ {
+ uint8_t backend_id = nrf_log_backend_id_get(p_backend);
+ nrf_log_module_dynamic_data_t * p_module_filter =
+ (nrf_log_module_dynamic_data_t *)NRF_LOG_DYNAMIC_SECTION_VARS_GET(header.module_id);
+ uint32_t filter_lvls = p_module_filter->filter_lvls;
+ uint32_t backend_lvl = (filter_lvls >> (backend_id*NRF_LOG_LEVEL_BITS))
+ & NRF_LOG_LEVEL_MASK;
+ //Degrade INFO_RAW level to INFO.
+ severity = (severity == NRF_LOG_SEVERITY_INFO_RAW) ? NRF_LOG_SEVERITY_INFO : severity;
+ if (backend_lvl >= severity)
+ {
+ entry_accepted = true;
+ }
+ }
+ else
+ {
+ (void)severity;
+ entry_accepted = true;
+ }
+ }
+ if (entry_accepted)
+ {
+ nrf_log_backend_put(p_backend, p_msg_buf);
+ }
+ p_backend = p_backend->p_next;
+ }
+
+ nrf_memobj_put(p_msg_buf);
+
+ if (NRF_LOG_ALLOW_OVERFLOW)
+ {
+ // Read index can be moved forward only if dequeueing process was not interrupt by
+ // skipping procedure. If NRF_LOG_ALLOW_OVERFLOW is set then in case of buffer gets full
+ // and new logger entry occurs, oldest entry is removed. In that case read index is
+ // changed and updating it here would corrupt the internal circular buffer.
+ CRITICAL_REGION_ENTER();
+ if (m_log_data.log_skipped == 0)
+ {
+ m_log_data.rd_idx = rd_idx;
+ }
+ CRITICAL_REGION_EXIT();
+ }
+ else
+ {
+ m_log_data.rd_idx = rd_idx;
+ }
+ }
+ }
+ else
+ {
+ //Could not allocate memobj - backends are not freeing them on time.
+ nrf_log_backend_t * p_backend = m_log_data.p_backend_head;
+ //Flush all backends
+ while (p_backend)
+ {
+ nrf_log_backend_flush(p_backend);
+ p_backend = p_backend->p_next;
+ }
+ NRF_LOG_WARNING("Backends flushed");
+ }
+
+ return buffer_is_empty() ? false : true;
+}
+
+static int32_t backend_id_assign(void)
+{
+ int32_t candidate_id;
+ nrf_log_backend_t * p_backend;
+ bool id_available;
+ for (candidate_id = 0; candidate_id < NRF_LOG_MAX_BACKENDS; candidate_id++)
+ {
+ p_backend = m_log_data.p_backend_head;
+ id_available = true;
+ while (p_backend)
+ {
+ if (nrf_log_backend_id_get(p_backend) == candidate_id)
+ {
+ id_available = false;
+ break;
+ }
+ p_backend = p_backend->p_next;
+ }
+ if (id_available)
+ {
+ return candidate_id;
+ }
+ }
+ return -1;
+}
+
+int32_t nrf_log_backend_add(nrf_log_backend_t * p_backend, nrf_log_severity_t severity)
+{
+ int32_t id = backend_id_assign();
+ if (id == -1)
+ {
+ return id;
+ }
+
+ nrf_log_backend_id_set(p_backend, id);
+ //add to list
+ if (m_log_data.p_backend_head == NULL)
+ {
+ m_log_data.p_backend_head = p_backend;
+ p_backend->p_next = NULL;
+ }
+ else
+ {
+ p_backend->p_next = m_log_data.p_backend_head->p_next;
+ m_log_data.p_backend_head->p_next = p_backend;
+ }
+
+ if (NRF_LOG_FILTERS_ENABLED)
+ {
+ uint32_t i;
+ for (i = 0; i < nrf_log_module_cnt_get(); i++)
+ {
+ nrf_log_severity_t buildin_lvl = nrf_log_module_init_filter_get(i);
+ nrf_log_severity_t actual_severity = MIN(buildin_lvl, severity);
+ nrf_log_module_filter_set(nrf_log_backend_id_get(p_backend), i, actual_severity);
+ }
+ }
+
+ return id;
+}
+
+void nrf_log_backend_remove(nrf_log_backend_t * p_backend)
+{
+ nrf_log_backend_t * p_curr = m_log_data.p_backend_head;
+ nrf_log_backend_t * p_prev = NULL;
+ while (p_curr != p_backend)
+ {
+ p_prev = p_curr;
+ p_curr = p_curr->p_next;
+ }
+
+ if (p_prev)
+ {
+ p_prev->p_next = p_backend->p_next;
+ }
+ else
+ {
+ m_log_data.p_backend_head = NULL;
+ }
+}
+
+void nrf_log_panic(void)
+{
+ nrf_log_backend_t * p_backend = m_log_data.p_backend_head;
+ m_log_data.autoflush = true;
+ while (p_backend)
+ {
+ nrf_log_backend_enable(p_backend);
+ nrf_log_backend_panic_set(p_backend);
+ p_backend = p_backend->p_next;
+ }
+}
+
+#if NRF_LOG_CLI_CMDS
+#include "nrf_cli.h"
+
+static const char * m_severity_lvls[] = {
+ "none",
+ "error",
+ "warning",
+ "info",
+ "debug",
+};
+
+static const char * m_severity_lvls_sorted[] = {
+ "debug",
+ "error",
+ "info",
+ "none",
+ "warning",
+};
+
+static void log_status(nrf_cli_t const * p_cli, size_t argc, char **argv)
+{
+ uint32_t modules_cnt = nrf_log_module_cnt_get();
+ uint32_t backend_id = p_cli->p_log_backend->backend.id;
+ uint32_t i;
+
+ if (!nrf_log_backend_is_enabled(&p_cli->p_log_backend->backend))
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Logs are halted!\r\n");
+ }
+ nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-40s | current | built-in \r\n", "module_name");
+ nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "----------------------------------------------------------\r\n");
+ for (i = 0; i < modules_cnt; i++)
+ {
+ nrf_log_severity_t module_dynamic_lvl = nrf_log_module_filter_get(backend_id, i, true, true);
+ nrf_log_severity_t module_compiled_lvl = nrf_log_module_filter_get(backend_id, i, true, false);
+ nrf_log_severity_t actual_compiled_lvl = MIN(module_compiled_lvl, (nrf_log_severity_t)NRF_LOG_DEFAULT_LEVEL);
+ nrf_cli_fprintf(p_cli, NRF_CLI_NORMAL, "%-40s | %-7s | %s%s\r\n",
+ nrf_log_module_name_get(i, true),
+ m_severity_lvls[module_dynamic_lvl],
+ m_severity_lvls[actual_compiled_lvl],
+ actual_compiled_lvl < module_compiled_lvl ? "*" : "");
+ }
+}
+
+static bool module_id_get(const char * p_name, uint32_t * p_id)
+{
+ uint32_t modules_cnt = nrf_log_module_cnt_get();
+ const char * p_tmp_name;
+ uint32_t j;
+ for (j = 0; j < modules_cnt; j++)
+ {
+ p_tmp_name = nrf_log_module_name_get(j, false);
+ if (strncmp(p_tmp_name, p_name, 32) == 0)
+ {
+ *p_id = j;
+ break;
+ }
+ }
+ return (j != modules_cnt);
+}
+
+static bool module_id_filter_set(uint32_t backend_id,
+ uint32_t module_id,
+ nrf_log_severity_t lvl)
+{
+ nrf_log_severity_t buildin_lvl = nrf_log_module_filter_get(backend_id, module_id, false, false);
+ if (lvl > buildin_lvl)
+ {
+ return false;
+ }
+ else
+ {
+ nrf_log_module_filter_set(backend_id, module_id, lvl);
+ return true;
+ }
+}
+
+static void log_ctrl(nrf_cli_t const * p_cli, size_t argc, char **argv)
+{
+ uint32_t backend_id = p_cli->p_log_backend->backend.id;
+ nrf_log_severity_t lvl;
+ uint32_t first_m_name_idx;
+ uint32_t i;
+ bool all_modules = false;
+
+ if (argc > 0)
+ {
+ if (strncmp(argv[0], "enable", 7) == 0)
+ {
+ if (argc == 1)
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Bad parameter count.\r\n");
+ return;
+ }
+
+ if (argc == 2)
+ {
+ all_modules = true;
+ }
+
+ for (i = 0; i < ARRAY_SIZE(m_severity_lvls); i++)
+ {
+ if (strncmp(argv[1], m_severity_lvls[i], 10) == 0)
+ {
+ break;
+ }
+ }
+
+ if (i == ARRAY_SIZE(m_severity_lvls))
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown severity level: %s\r\n", argv[1]);
+ return;
+ }
+
+ lvl = (nrf_log_severity_t)i;
+ first_m_name_idx = 2;
+
+ }
+ else if (strncmp(argv[0], "disable", 8) == 0)
+ {
+ if (argc == 1)
+ {
+ all_modules = true;
+ }
+ lvl = NRF_LOG_SEVERITY_NONE;
+ first_m_name_idx = 1;
+ }
+ else
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown option: %s\r\n", argv[0]);
+ return;
+ }
+
+ if (all_modules)
+ {
+ for (i = 0; i < nrf_log_module_cnt_get(); i++)
+ {
+ if (module_id_filter_set(backend_id, i, lvl) == false)
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Level unavailable for module: %s\r\n", nrf_log_module_name_get(i, false));
+ }
+ }
+ }
+ else
+ {
+ for (i = first_m_name_idx; i < argc; i++)
+ {
+ uint32_t module_id = 0;
+ if (module_id_get(argv[i], &module_id) == false)
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Unknown module:%s\r\n", argv[i]);
+ }
+
+ if (module_id_filter_set(backend_id, module_id, lvl) == false)
+ {
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "Level unavailable for module: %s\r\n", nrf_log_module_name_get(module_id, false));
+ }
+ }
+ }
+ }
+}
+static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static);
+
+NRF_CLI_CREATE_DYNAMIC_CMD(m_module_name, module_name_get);
+
+static void module_name_get(size_t idx, nrf_cli_static_entry_t * p_static)
+{
+ p_static->handler = NULL;
+ p_static->p_help = NULL;
+ p_static->p_subcmd = &m_module_name;
+ p_static->p_syntax = nrf_log_module_name_get(idx, true);
+}
+
+static void severity_lvl_get(size_t idx, nrf_cli_static_entry_t * p_static)
+{
+ p_static->handler = NULL;
+ p_static->p_help = NULL;
+ p_static->p_subcmd = &m_module_name;
+ p_static->p_syntax = (idx < ARRAY_SIZE(m_severity_lvls_sorted)) ?
+ m_severity_lvls_sorted[idx] : NULL;
+}
+
+NRF_CLI_CREATE_DYNAMIC_CMD(m_severity_lvl, severity_lvl_get);
+
+static void log_halt(nrf_cli_t const * p_cli, size_t argc, char **argv)
+{
+ nrf_log_backend_disable(&p_cli->p_log_backend->backend);
+}
+
+static void log_go(nrf_cli_t const * p_cli, size_t argc, char **argv)
+{
+ nrf_log_backend_enable(&p_cli->p_log_backend->backend);
+}
+
+NRF_CLI_CREATE_STATIC_SUBCMD_SET(m_sub_log_stat)
+{
+ NRF_CLI_CMD(disable, &m_module_name,
+ "'log disable <module_0> .. <module_n>' disables logs in specified "
+ "modules (all if no modules specified).",
+ log_ctrl),
+ NRF_CLI_CMD(enable, &m_severity_lvl,
+ "'log enable <level> <module_0> ... <module_n>' enables logs up to given level in "
+ "specified modules (all if no modules specified).",
+ log_ctrl),
+ NRF_CLI_CMD(go, NULL, "Resume logging", log_go),
+ NRF_CLI_CMD(halt, NULL, "Halt logging", log_halt),
+ NRF_CLI_CMD(status, NULL, "Logger status", log_status),
+ NRF_CLI_SUBCMD_SET_END
+};
+
+static void log_cmd(nrf_cli_t const * p_cli, size_t argc, char **argv)
+{
+ if ((argc == 1) || nrf_cli_help_requested(p_cli))
+ {
+ nrf_cli_help_print(p_cli, NULL, 0);
+ return;
+ }
+
+ nrf_cli_fprintf(p_cli, NRF_CLI_ERROR, "%s:%s%s\r\n", argv[0], " unknown parameter: ", argv[1]);
+}
+
+NRF_CLI_CMD_REGISTER(log, &m_sub_log_stat, "Commands for controlling logger", log_cmd);
+
+#endif //NRF_LOG_CLI_CMDS
+
+#endif // NRF_MODULE_ENABLED(NRF_LOG)
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_internal.h b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_internal.h
new file mode 100644
index 0000000..7c5246f
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_internal.h
@@ -0,0 +1,529 @@
+/**
+ * Copyright (c) 2016 - 2018, 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>
+#include "nrf_log_instance.h"
+#include "nrf_log_types.h"
+
+#ifndef NRF_LOG_ERROR_COLOR
+ #define NRF_LOG_ERROR_COLOR NRF_LOG_COLOR_DEFAULT
+#endif
+
+#ifndef NRF_LOG_WARNING_COLOR
+ #define NRF_LOG_WARNING_COLOR NRF_LOG_COLOR_DEFAULT
+#endif
+
+#ifndef NRF_LOG_INFO_COLOR
+ #define NRF_LOG_INFO_COLOR NRF_LOG_COLOR_DEFAULT
+#endif
+
+#ifndef NRF_LOG_DEBUG_COLOR
+ #define NRF_LOG_DEBUG_COLOR NRF_LOG_COLOR_DEFAULT
+#endif
+
+
+#ifndef NRF_LOG_COLOR_DEFAULT
+#define NRF_LOG_COLOR_DEFAULT 0
+#endif
+
+#ifndef NRF_LOG_DEFAULT_LEVEL
+#define NRF_LOG_DEFAULT_LEVEL 0
+#endif
+
+#ifndef NRF_LOG_USES_COLORS
+#define NRF_LOG_USES_COLORS 0
+#endif
+
+#ifndef NRF_LOG_USES_TIMESTAMP
+#define NRF_LOG_USES_TIMESTAMP 0
+#endif
+
+#ifndef NRF_LOG_FILTERS_ENABLED
+#define NRF_LOG_FILTERS_ENABLED 0
+#endif
+
+#ifndef NRF_LOG_MODULE_NAME
+ #define NRF_LOG_MODULE_NAME app
+#endif
+
+#define NRF_LOG_LEVEL_BITS 3
+#define NRF_LOG_LEVEL_MASK ((1UL << NRF_LOG_LEVEL_BITS) - 1)
+#define NRF_LOG_MODULE_ID_BITS 16
+#define NRF_LOG_MODULE_ID_POS 16
+
+
+#define NRF_LOG_MAX_NUM_OF_ARGS 6
+
+
+#if NRF_LOG_FILTERS_ENABLED && NRF_LOG_ENABLED
+ #define NRF_LOG_FILTER NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).filter
+ #define NRF_LOG_INST_FILTER(p_inst) (p_inst)->filter
+#else
+ #undef NRF_LOG_FILTER
+ #define NRF_LOG_FILTER NRF_LOG_SEVERITY_DEBUG
+ #define NRF_LOG_INST_FILTER(p_inst) NRF_LOG_SEVERITY_DEBUG
+#endif
+
+#if NRF_LOG_ENABLED
+#define NRF_LOG_MODULE_ID NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME).module_id
+#define NRF_LOG_INST_ID(p_inst) (p_inst)->module_id
+#else
+#define NRF_LOG_MODULE_ID 0
+#define NRF_LOG_INST_ID(p_inst) 0
+#endif
+
+
+#define LOG_INTERNAL_X(N, ...) CONCAT_2(LOG_INTERNAL_, N) (__VA_ARGS__)
+#define LOG_INTERNAL(type, ...) LOG_INTERNAL_X(NUM_VA_ARGS_LESS_1( \
+ __VA_ARGS__), type, __VA_ARGS__)
+#if NRF_LOG_ENABLED
+#define NRF_LOG_INTERNAL_LOG_PUSH(_str) nrf_log_push(_str)
+#define LOG_INTERNAL_0(type, str) \
+ nrf_log_frontend_std_0(type, str)
+#define LOG_INTERNAL_1(type, str, arg0) \
+ /*lint -save -e571*/nrf_log_frontend_std_1(type, str, (uint32_t)(arg0))/*lint -restore*/
+#define LOG_INTERNAL_2(type, str, arg0, arg1) \
+ /*lint -save -e571*/nrf_log_frontend_std_2(type, str, (uint32_t)(arg0), \
+ (uint32_t)(arg1))/*lint -restore*/
+#define LOG_INTERNAL_3(type, str, arg0, arg1, arg2) \
+ /*lint -save -e571*/nrf_log_frontend_std_3(type, str, (uint32_t)(arg0), \
+ (uint32_t)(arg1), (uint32_t)(arg2))/*lint -restore*/
+#define LOG_INTERNAL_4(type, str, arg0, arg1, arg2, arg3) \
+ /*lint -save -e571*/nrf_log_frontend_std_4(type, str, (uint32_t)(arg0), \
+ (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3))/*lint -restore*/
+#define LOG_INTERNAL_5(type, str, arg0, arg1, arg2, arg3, arg4) \
+ /*lint -save -e571*/nrf_log_frontend_std_5(type, str, (uint32_t)(arg0), \
+ (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4))/*lint -restore*/
+#define LOG_INTERNAL_6(type, str, arg0, arg1, arg2, arg3, arg4, arg5) \
+ /*lint -save -e571*/nrf_log_frontend_std_6(type, str, (uint32_t)(arg0), \
+ (uint32_t)(arg1), (uint32_t)(arg2), (uint32_t)(arg3), (uint32_t)(arg4), (uint32_t)(arg5))/*lint -restore*/
+
+
+#else //NRF_LOG_ENABLED
+#define NRF_LOG_INTERNAL_LOG_PUSH(_str) (void)(_str)
+#define LOG_INTERNAL_0(_type, _str) \
+ (void)(_type); (void)(_str)
+#define LOG_INTERNAL_1(_type, _str, _arg0) \
+ (void)(_type); (void)(_str); (void)(_arg0)
+#define LOG_INTERNAL_2(_type, _str, _arg0, _arg1) \
+ (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1)
+#define LOG_INTERNAL_3(_type, _str, _arg0, _arg1, _arg2) \
+ (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2)
+#define LOG_INTERNAL_4(_type, _str, _arg0, _arg1, _arg2, _arg3) \
+ (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3)
+#define LOG_INTERNAL_5(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4) \
+ (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4)
+#define LOG_INTERNAL_6(_type, _str, _arg0, _arg1, _arg2, _arg3, _arg4, _arg5) \
+ (void)(_type); (void)(_str); (void)(_arg0); (void)(_arg1); (void)(_arg2); (void)(_arg3); (void)(_arg4); (void)(_arg5)
+#endif //NRF_LOG_ENABLED
+
+#define LOG_SEVERITY_MOD_ID(severity) ((severity) | NRF_LOG_MODULE_ID << NRF_LOG_MODULE_ID_POS)
+#define LOG_SEVERITY_INST_ID(severity,p_inst) ((severity) | NRF_LOG_INST_ID(p_inst) << NRF_LOG_MODULE_ID_POS)
+
+#if NRF_LOG_ENABLED
+#define LOG_HEXDUMP(_severity, _p_data, _length) \
+ nrf_log_frontend_hexdump((_severity), (_p_data), (_length))
+#else
+#define LOG_HEXDUMP(_severity, _p_data, _length) \
+ (void)(_severity); (void)(_p_data); (void)_length
+#endif
+
+#define NRF_LOG_INTERNAL_INST(level, level_id, p_inst, ...) \
+ if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
+ (level <= NRF_LOG_DEFAULT_LEVEL)) \
+ { \
+ if (NRF_LOG_INST_FILTER(p_inst) >= level) \
+ { \
+ LOG_INTERNAL(LOG_SEVERITY_INST_ID(level_id, p_inst), __VA_ARGS__); \
+ } \
+ }
+
+#define NRF_LOG_INTERNAL_MODULE(level, level_id, ...) \
+ if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
+ (level <= NRF_LOG_DEFAULT_LEVEL)) \
+ { \
+ if (NRF_LOG_FILTER >= level) \
+ { \
+ LOG_INTERNAL(LOG_SEVERITY_MOD_ID(level_id), __VA_ARGS__); \
+ } \
+ }
+
+#define NRF_LOG_INTERNAL_HEXDUMP_INST(level, level_id, p_inst, p_data, len) \
+ if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
+ (level <= NRF_LOG_DEFAULT_LEVEL)) \
+ { \
+ if (NRF_LOG_INST_FILTER(p_inst) >= level) \
+ { \
+ LOG_HEXDUMP(LOG_SEVERITY_INST_ID(level_id, p_inst), \
+ (p_data), (len)); \
+ } \
+ }
+
+#define NRF_LOG_INTERNAL_HEXDUMP_MODULE(level, level_id, p_data, len) \
+ if (NRF_LOG_ENABLED && (NRF_LOG_LEVEL >= level) && \
+ (level <= NRF_LOG_DEFAULT_LEVEL)) \
+ { \
+ if (NRF_LOG_FILTER >= level) \
+ { \
+ LOG_HEXDUMP(LOG_SEVERITY_MOD_ID(level_id), \
+ (p_data), (len)); \
+ } \
+ }
+
+#define NRF_LOG_INTERNAL_INST_ERROR(p_inst, ...) \
+ NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, __VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_ERROR(...) \
+ NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR,__VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_INST_ERROR(p_inst, p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_inst, p_data, len)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_ERROR(p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_ERROR, NRF_LOG_SEVERITY_ERROR, p_data, len)
+
+#define NRF_LOG_INTERNAL_INST_WARNING(p_inst, ...) \
+ NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, __VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_WARNING(...) \
+ NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING,__VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_INST_WARNING(p_inst, p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_inst, p_data, len)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_WARNING(p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_(NRF_LOG_SEVERITY_WARNING, NRF_LOG_SEVERITY_WARNING, p_data, len)
+
+#define NRF_LOG_INTERNAL_INST_INFO(p_inst, ...) \
+ NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, __VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_INFO(...) \
+ NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, __VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_INST_INFO(p_inst, p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_inst, p_data, len)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_INFO(p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO, p_data, len)
+
+#define NRF_LOG_INTERNAL_RAW_INFO(...) \
+ NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, __VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_RAW_HEXDUMP_INFO(p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_INFO, NRF_LOG_SEVERITY_INFO_RAW, p_data, len)
+
+#define NRF_LOG_INTERNAL_INST_DEBUG(p_inst, ...) \
+ NRF_LOG_INTERNAL_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, __VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_DEBUG(...) \
+ NRF_LOG_INTERNAL_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, __VA_ARGS__)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_INST_DEBUG(p_inst, p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_INST(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_inst, p_data, len)
+
+#define NRF_LOG_INTERNAL_HEXDUMP_DEBUG(p_data, len) \
+ NRF_LOG_INTERNAL_HEXDUMP_MODULE(NRF_LOG_SEVERITY_DEBUG, NRF_LOG_SEVERITY_DEBUG, p_data, len)
+
+
+#if NRF_LOG_ENABLED
+
+#ifdef UNIT_TEST
+#define COMPILED_LOG_LEVEL 4
+#else
+#define COMPILED_LOG_LEVEL NRF_LOG_LEVEL
+#endif
+
+
+#define NRF_LOG_INTERNAL_MODULE_REGISTER() \
+ NRF_LOG_INTERNAL_ITEM_REGISTER(NRF_LOG_MODULE_NAME, \
+ STRINGIFY(NRF_LOG_MODULE_NAME), \
+ NRF_LOG_INFO_COLOR, \
+ NRF_LOG_DEBUG_COLOR, \
+ NRF_LOG_INITIAL_LEVEL, \
+ COMPILED_LOG_LEVEL)
+
+#else
+#define NRF_LOG_INTERNAL_MODULE_REGISTER() /*lint -save -e19*/ /*lint -restore*/
+#endif
+
+extern NRF_LOG_DYNAMIC_STRUCT_NAME NRF_LOG_ITEM_DATA_DYNAMIC(NRF_LOG_MODULE_NAME);
+
+/**
+ * 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 |
+ * |------------------------------|
+ * | Module_ID (optional) |
+ * |------------------------------|
+ * | 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|
+ * |------------------------------|
+ * | Module_ID (optional) |
+ * |------------------------------|
+ * | 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 STD_ADDR_MASK ((uint32_t)(1U << 22) - 1U)
+#define HEADER_TYPE_STD 1U
+#define HEADER_TYPE_HEXDUMP 2U
+#define HEADER_TYPE_PUSHED 0U
+#define HEADER_TYPE_INVALID 3U
+
+typedef struct
+{
+ uint32_t type : 2;
+ uint32_t in_progress: 1;
+ uint32_t data : 29;
+} nrf_log_generic_header_t;
+
+typedef struct
+{
+ uint32_t type : 2;
+ uint32_t in_progress: 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 in_progress: 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_main_header_t;
+
+typedef struct
+{
+ nrf_log_main_header_t base;
+ uint16_t module_id;
+ uint16_t dropped;
+ uint32_t timestamp;
+} nrf_log_header_t;
+
+#define HEADER_SIZE (sizeof(nrf_log_header_t)/sizeof(uint32_t) - \
+ (NRF_LOG_USES_TIMESTAMP ? 0 : 1))
+
+#define PUSHED_HEADER_SIZE (sizeof(nrf_log_pushed_header_t)/sizeof(uint32_t))
+
+//Implementation assumes that pushed header has one word.
+STATIC_ASSERT(PUSHED_HEADER_SIZE == 1);
+/**
+ * @brief A function for logging raw string.
+ *
+ * @param severity_mid Severity.
+ * @param p_str A pointer to a string.
+ */
+void nrf_log_frontend_std_0(uint32_t severity_mid, char const * const p_str);
+
+/**
+ * @brief A function for logging a formatted string with one argument.
+ *
+ * @param severity_mid Severity.
+ * @param p_str A pointer to a formatted string.
+ * @param val0 An argument.
+ */
+void nrf_log_frontend_std_1(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0);
+
+/**
+ * @brief A function for logging a formatted string with 2 arguments.
+ *
+ * @param severity_mid Severity.
+ * @param p_str A pointer to a formatted string.
+ * @param val0, val1 Arguments for formatting string.
+ */
+void nrf_log_frontend_std_2(uint32_t severity_mid,
+ char const * const p_str,
+ uint32_t val0,
+ uint32_t val1);
+
+/**
+ * @brief A function for logging a formatted string with 3 arguments.
+ *
+ * @param severity_mid Severity.
+ * @param p_str A pointer to a formatted string.
+ * @param val0, val1, val2 Arguments for formatting string.
+ */
+void nrf_log_frontend_std_3(uint32_t severity_mid,
+ 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_mid 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(uint32_t severity_mid,
+ 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_mid 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(uint32_t severity_mid,
+ 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_mid 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(uint32_t severity_mid,
+ 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_mid 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(uint32_t severity_mid,
+ 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__
diff --git a/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_str_formatter.c b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_str_formatter.c
new file mode 100644
index 0000000..fa548f3
--- /dev/null
+++ b/thirdparty/nRF5_SDK_15.0.0_a53641a/components/libraries/experimental_log/src/nrf_log_str_formatter.c
@@ -0,0 +1,256 @@
+/**
+ * Copyright (c) 2016 - 2018, 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 <ctype.h>
+
+#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"
+
+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", 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