This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

NRF_LOG_INFO: Only the last log statement is printed out

I inherited a Nordic project that is running on the 52832 board with the 15.3 version of the SDK.  The project uses CLI, TWI, and logging.  The developer has to jump through hoops to get all 3 functioning at the same time.  I am now expanding the project.  The issue.  NRF_LOG_INFO works fine if I provide a constant string (e.q. NRF_LOG_INFO("Hello world");)

However, the minute I create a generic logging utility which uses non-stack memory (using data segment memory - statically declared array), only the last logged data is printed several times. 

so something like

XXX_LOG_PRINTF(LOG_INFO, "sensor initialization start.");
.... some more code here.....
XXX_LOG_PRINTF(LOG_INFO, "sensor initialization complete.");
My logging utility can take variable length arguments, etc.  So the "constant strings" you see in the calls above gets copied to a statically declared string which gets passed to the Nordic logging utility.
I only see the last line printed twice.  I have turned off deferred, so I am at a loss.

I have read the chapter on logging and think I understand the buffering concept on the front and back end.   I have tried messing with the sdk_config.h to no avail.   Here are what I think are relevant:

All my CLI commands and output work great.

#define NRF_LOG_DEFERRED 0
#define NRF_LOG_CLI_CMDS 1
#define NRF_LOG_FILTERS_ENABLED 0
The ways I have tried to log the info:
NRF_LOG_INFO("%s\n", NRF_LOG_PUSH((char *)pLogMsg));
or
NRF_LOG_RAW_INFO
I am running on Ubuntu linux, using minicom (which works great for constant strings and cli).  Segger, RTT or any other IDE is not an option.  This must be done via UART<
Please let me know if you need additional info to assist in this.
Thanks,
Jim
  • I just tested the unmodified CLI example from the SDK, and it seems to work there as well, only adding two lines to the main() function:

        NRF_LOG_RAW_INFO("Command Line Interface example started.\n");
        NRF_LOG_RAW_INFO("Please press the Tab key to see all available commands.\n");
        test_log("helloWorld");
        test_log("goodbyeWorld");

    with the same test_log() function as before. It works both with NRF_LOG_DEFERRED set to 0 and 1. 

    Can you please test with the unmodified CLI example and these addons?

    Can you show me how you print your logging in your case when it only prints the last logged message? Is it possible to share the project so that I can reproduce it?

    Best regards,

    Edvin

  • Do you see the difference in my design and your perturbation of it? Why did you stray from my example?  You are not copying the string into a local buffer.  Please follow my example.  I am not sure if I am having trouble communicating the issue, but it seems that you always adjust the example to simplify it.  That is the problem, you are simplifying the situation.  Can you see in my example where I copy over the string?  In actuality, there is a lot more formatting going on in my logging routine which requires this.  Please follow my example above without modification.  Otherwise, resolving this issue will take weeks.  There is talk moving away from Nordic so this may be a moot point.

  • >>Can you show me how you print your logging in your case when it only prints the last logged message? >>Is it possible to share the project so that I can reproduce it?

        I did if you followed the example above but you chose to modify it....Please you the code below as shown.....

    static char message[256];
    
    void logMsg(const char *pMessage)
    {
        int cnt = 0;
    
        memset(message, 0, 256);
        cnt = snprintf(message, 255, pMessage); 
        message[cnt-1] = '\0';
        NRF_LOG_RAW_INFO("%s\n", message);
    
        return;
    }

  • you are passing two different pointers in your example.  whereas my example is using the same pointer.  If deferred is set to 0, this should not be a problem.  Even if deferred is on, and my understanding of your logging is correct, this should also not be a problem as long as I don't exceed any queue or buffer size.  I am guessing your logging mechanism is not properly copying the incoming data.

  • I created an example where you can see the difference in your method and mine.  I've also included the output.  You can see my original logger just duplicates the string, where yours will work.  However, passing const strings is not the purpose of my logging.

    /**
     * Copyright (c) 2016 - 2019, 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 <stdio.h>
    #include <stdbool.h>
    #include <stddef.h>
    
    #include "nrf.h"
    #include "nrf_drv_clock.h"
    #include "nrf_gpio.h"
    #include "nrf_delay.h"
    
    #include "app_timer.h"
    #include "fds.h"
    #include "app_error.h"
    #include "app_util.h"
    
    #include "nrf_cli.h"
    #include "nrf_cli_rtt.h"
    #include "nrf_cli_types.h"
    
    #include "boards.h"
    
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "nrf_log_backend_flash.h"
    #include "nrf_fstorage_nvmc.h"
    
    #include "nrf_mpu_lib.h"
    #include "nrf_stack_guard.h"
    
    #if defined(APP_USBD_ENABLED) && APP_USBD_ENABLED
    #define CLI_OVER_USB_CDC_ACM 1
    #else
    #define CLI_OVER_USB_CDC_ACM 0
    #endif
    
    #if CLI_OVER_USB_CDC_ACM
    #include "nrf_cli_cdc_acm.h"
    #include "nrf_drv_usbd.h"
    #include "app_usbd_core.h"
    #include "app_usbd.h"
    #include "app_usbd_string_desc.h"
    #include "app_usbd_cdc_acm.h"
    #endif //CLI_OVER_USB_CDC_ACM
    
    #if defined(TX_PIN_NUMBER) && defined(RX_PIN_NUMBER)
    #define CLI_OVER_UART 1
    #else
    #define CLI_OVER_UART 0
    #endif
    
    #if CLI_OVER_UART
    #include "nrf_cli_uart.h"
    #endif
    
    /* If enabled then CYCCNT (high resolution) timestamp is used for the logger. */
    #define USE_CYCCNT_TIMESTAMP_FOR_LOG 0
    
    /**@file
     * @defgroup CLI_example main.c
     *
     * @{
     *
     */
    
    #if NRF_LOG_BACKEND_FLASHLOG_ENABLED
    NRF_LOG_BACKEND_FLASHLOG_DEF(m_flash_log_backend);
    #endif
    
    #if NRF_LOG_BACKEND_CRASHLOG_ENABLED
    NRF_LOG_BACKEND_CRASHLOG_DEF(m_crash_log_backend);
    #endif
    
    /* Counter timer. */
    APP_TIMER_DEF(m_timer_0);
    
    /* Declared in demo_cli.c */
    extern uint32_t m_counter;
    extern bool m_counter_active;
    
    #if CLI_OVER_USB_CDC_ACM
    
    /**
     * @brief Enable power USB detection
     *
     * Configure if example supports USB port connection
     */
    #ifndef USBD_POWER_DETECTION
    #define USBD_POWER_DETECTION true
    #endif
    
    
    static void usbd_user_ev_handler(app_usbd_event_type_t event)
    {
        switch (event)
        {
            case APP_USBD_EVT_STOPPED:
                app_usbd_disable();
                break;
            case APP_USBD_EVT_POWER_DETECTED:
                if (!nrf_drv_usbd_is_enabled())
                {
                    app_usbd_enable();
                }
                break;
            case APP_USBD_EVT_POWER_REMOVED:
                app_usbd_stop();
                break;
            case APP_USBD_EVT_POWER_READY:
                app_usbd_start();
                break;
            default:
                break;
        }
    }
    
    #endif //CLI_OVER_USB_CDC_ACM
    
    /**
     * @brief Command line interface instance
     * */
    #define CLI_EXAMPLE_LOG_QUEUE_SIZE  (10)
    
    #if CLI_OVER_USB_CDC_ACM
    NRF_CLI_CDC_ACM_DEF(m_cli_cdc_acm_transport);
    NRF_CLI_DEF(m_cli_cdc_acm,
                "usb_cli:~$ ",
                &m_cli_cdc_acm_transport.transport,
                '\r',
                CLI_EXAMPLE_LOG_QUEUE_SIZE);
    #endif //CLI_OVER_USB_CDC_ACM
    
    #if CLI_OVER_UART
    NRF_CLI_UART_DEF(m_cli_uart_transport, 0, 64, 16);
    NRF_CLI_DEF(m_cli_uart,
                "uart_cli:~$ ",
                &m_cli_uart_transport.transport,
                '\r',
                CLI_EXAMPLE_LOG_QUEUE_SIZE);
    #endif
    
    NRF_CLI_RTT_DEF(m_cli_rtt_transport);
    NRF_CLI_DEF(m_cli_rtt,
                "rtt_cli:~$ ",
                &m_cli_rtt_transport.transport,
                '\n',
                CLI_EXAMPLE_LOG_QUEUE_SIZE);
    
    static void timer_handle(void * p_context)
    {
        UNUSED_PARAMETER(p_context);
    
        if (m_counter_active)
        {
            m_counter++;
            NRF_LOG_RAW_INFO("counter = %d\n", m_counter);
        }
    }
    
    static void cli_start(void)
    {
        ret_code_t ret;
    
    #if CLI_OVER_USB_CDC_ACM
        ret = nrf_cli_start(&m_cli_cdc_acm);
        APP_ERROR_CHECK(ret);
    #endif
    
    #if CLI_OVER_UART
        ret = nrf_cli_start(&m_cli_uart);
        APP_ERROR_CHECK(ret);
    #endif
    
        ret = nrf_cli_start(&m_cli_rtt);
        APP_ERROR_CHECK(ret);
    }
    
    static void cli_init(void)
    {
        ret_code_t ret;
    
    #if CLI_OVER_USB_CDC_ACM
        ret = nrf_cli_init(&m_cli_cdc_acm, NULL, true, true, NRF_LOG_SEVERITY_INFO);
        APP_ERROR_CHECK(ret);
    #endif
    
    #if CLI_OVER_UART
        nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
        uart_config.pseltxd = TX_PIN_NUMBER;
        uart_config.pselrxd = RX_PIN_NUMBER;
        uart_config.hwfc    = NRF_UART_HWFC_DISABLED;
        ret = nrf_cli_init(&m_cli_uart, &uart_config, true, true, NRF_LOG_SEVERITY_INFO);
        APP_ERROR_CHECK(ret);
    #endif
    
        ret = nrf_cli_init(&m_cli_rtt, NULL, true, true, NRF_LOG_SEVERITY_INFO);
        APP_ERROR_CHECK(ret);
    }
    
    
    static void usbd_init(void)
    {
    #if CLI_OVER_USB_CDC_ACM
        ret_code_t ret;
        static const app_usbd_config_t usbd_config = {
            .ev_handler = app_usbd_event_execute,
            .ev_state_proc = usbd_user_ev_handler
        };
        ret = app_usbd_init(&usbd_config);
        APP_ERROR_CHECK(ret);
    
        app_usbd_class_inst_t const * class_cdc_acm =
                app_usbd_cdc_acm_class_inst_get(&nrf_cli_cdc_acm);
        ret = app_usbd_class_append(class_cdc_acm);
        APP_ERROR_CHECK(ret);
    
        if (USBD_POWER_DETECTION)
        {
            ret = app_usbd_power_events_enable();
            APP_ERROR_CHECK(ret);
        }
        else
        {
            NRF_LOG_INFO("No USB power detection enabled\nStarting USB now");
    
            app_usbd_enable();
            app_usbd_start();
        }
    
        /* Give some time for the host to enumerate and connect to the USB CDC port */
        nrf_delay_ms(1000);
    #endif
    }
    
    
    static void cli_process(void)
    {
    #if CLI_OVER_USB_CDC_ACM
        nrf_cli_process(&m_cli_cdc_acm);
    #endif
    
    #if CLI_OVER_UART
        nrf_cli_process(&m_cli_uart);
    #endif
    
        nrf_cli_process(&m_cli_rtt);
    }
    
    
    static void flashlog_init(void)
    {
        ret_code_t ret;
        int32_t backend_id;
    
        ret = nrf_log_backend_flash_init(&nrf_fstorage_nvmc);
        APP_ERROR_CHECK(ret);
    #if NRF_LOG_BACKEND_FLASHLOG_ENABLED
        backend_id = nrf_log_backend_add(&m_flash_log_backend, NRF_LOG_SEVERITY_WARNING);
        APP_ERROR_CHECK_BOOL(backend_id >= 0);
    
        nrf_log_backend_enable(&m_flash_log_backend);
    #endif
    
    #if NRF_LOG_BACKEND_CRASHLOG_ENABLED
        backend_id = nrf_log_backend_add(&m_crash_log_backend, NRF_LOG_SEVERITY_INFO);
        APP_ERROR_CHECK_BOOL(backend_id >= 0);
    
        nrf_log_backend_enable(&m_crash_log_backend);
    #endif
    }
    
    static inline void stack_guard_init(void)
    {
        APP_ERROR_CHECK(nrf_mpu_lib_init());
        APP_ERROR_CHECK(nrf_stack_guard_init());
    }
    
    uint32_t cyccnt_get(void)
    {
        return DWT->CYCCNT;
    }
    
    static char message[256];
    
    void logMsg(const char *pMessage)
    {
        int cnt = 0;
    
        memset(message, 0, 256);
        cnt = snprintf(message, 255, pMessage); 
        message[cnt-1] = '\0';
        NRF_LOG_INFO("%s\n", NRF_LOG_PUSH(message));
    
        return;
    }
    
    void logMsg2(const char *pMessage)
    {
        
        NRF_LOG_RAW_INFO("%s\n", pMessage);
    
        return;
    }
    int main(void)
    {
        ret_code_t ret;
        char buff[1024];
    
        if (USE_CYCCNT_TIMESTAMP_FOR_LOG)
        {
            CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
            DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
            DWT->CYCCNT = 0;
            APP_ERROR_CHECK(NRF_LOG_INIT(cyccnt_get, 64000000));
        }
        else
        {
            APP_ERROR_CHECK(NRF_LOG_INIT(app_timer_cnt_get));
        }
    
        ret = nrf_drv_clock_init();
        APP_ERROR_CHECK(ret);
        nrf_drv_clock_lfclk_request(NULL);
    
        ret = app_timer_init();
        APP_ERROR_CHECK(ret);
    
        ret = app_timer_create(&m_timer_0, APP_TIMER_MODE_REPEATED, timer_handle);
        APP_ERROR_CHECK(ret);
    
        ret = app_timer_start(m_timer_0, APP_TIMER_TICKS(1000), NULL);
        APP_ERROR_CHECK(ret);
    
        cli_init();
    
        usbd_init();
    
        ret = fds_init();
        APP_ERROR_CHECK(ret);
    
    
        UNUSED_RETURN_VALUE(nrf_log_config_load());
    
        cli_start();
    
        flashlog_init();
    
        stack_guard_init();
    
        snprintf(buff, 1023, "NRF_LOG_DEFERRED=%d\n",NRF_LOG_DEFERRED);
        logMsg(buff);
        logMsg("Please press the Tab key to see all available commands.\n");
    
        logMsg2("Test Print #1 - data seg pointer\n");
        logMsg2("Test Print #2 - data seg pointer\n");
    
        while (true)
        {
            UNUSED_RETURN_VALUE(NRF_LOG_PROCESS());
    #if CLI_OVER_USB_CDC_ACM && APP_USBD_CONFIG_EVENT_QUEUE_ENABLE
            while (app_usbd_event_queue_process())
            {
                /* Nothing to do */
            }
    #endif
            cli_process();
        }
    }
    
    /** @} */
    
    [00:00:00.000,000] <info> stack_guard: Stack Guard (128 bytes): 0x2000E000-0x2000E07F (total stack size: 8192 bytes, usable stack area: 8064 bytes)
    [00:00:00.000,122] <info> app: Please press the Tab key to see all available commands.
    
    [00:00:00.000,244] <info> app: Please press the Tab key to see all available commands.
    
    Test Print #1 - data seg pointer
    
    Test Print #2 - data seg pointer
    
    uart_cli:~$ 
    

Related