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

[Bugreport] Unecessary high RAM usage if NRF_LOG_BACKEND_SERIAL_USES_RTT is set

Platform: nRF52-DK using SDK12.1.0 and S132

Summary: Using nrf_log module from SDK along with RTT by setting NRF_LOG_BACKEND_SERIAL_USES_RTT flag causes nrf_log_serial.c to allocate excessive amount of memory for log buffer despite the fact that this memory is not used.

Way to reproduce: Use any example from the SDK, set it to log over RTT using large log buffer (NRF_LOG_BACKEND_SERIAL_USES_RTT=1 and for example NRF_LOG_BACKEND_MAX_STRING_LENGTH=4096) and try to NRF_LOG_DEBUG over 1024 bytes in blocking mode.

Expected behavior: All information is logged properly. RAM usage of nrf_log related modules corresponds to user settings.

Actual behavior: Only 1024 bytes are logged before truncation happens, memory usage is NRF_LOG_BACKEND_MAX_STRING_LENGTH+1024

Cause: nrf_log_serial.callocates m_rtt_buffer which is NRF_LOG_BACKEND_MAX_STRING_LENGTH bytes wide but this buffer isn't used by Segger_RTT which is underlying logger backend. Despite of programmer's intent to call SEGGER_RTT_ConfigUpBuffer and set log buffer pointer to this buffer Segger init code ignores it. It's due to buffer id number being equal to 0.

Here's the relevant code snippet from SEGGER_RTT.c

if (BufferIndex < (unsigned)_SEGGER_RTT.MaxNumUpBuffers) {
    SEGGER_RTT_LOCK(SavedState);
    if (BufferIndex > 0u) {
      _SEGGER_RTT.aUp[BufferIndex].sName        = sName;
      _SEGGER_RTT.aUp[BufferIndex].pBuffer      = pBuffer;
      _SEGGER_RTT.aUp[BufferIndex].SizeOfBuffer = BufferSize;
      _SEGGER_RTT.aUp[BufferIndex].RdOff        = 0u;
      _SEGGER_RTT.aUp[BufferIndex].WrOff        = 0u;
    }
    _SEGGER_RTT.aUp[BufferIndex].Flags          = Flags;
    SEGGER_RTT_UNLOCK(SavedState);
    r =  0;
  }

Note the if (BufferIndex > 0u) condition which is not met and Segger RTT still logs into it's internal buffer which by default has size of 1024 bytes (defined in SEGGER_RTT_Conf.h). This causes premature log truncation despite the user's intent of increasing log buffer size by setting NRF_LOG_BACKEND_MAX_STRING_LENGTH to a larger value.

  • In order to resolve this following patch is proposed:

    diff --git a/components/libraries/log/src/nrf_log_backend_serial.c b/components/libraries/log/src/nrf_log_backend_serial.c
    index 4aa73b7..5c70edc 100644
    --- a/components/libraries/log/src/nrf_log_backend_serial.c
    +++ b/components/libraries/log/src/nrf_log_backend_serial.c
    @@ -27,10 +27,6 @@
     #include "nrf_drv_uart.h"
     #endif
     
    -#if NRF_LOG_BACKEND_SERIAL_USES_RTT
    -static char m_rtt_buffer[NRF_LOG_BACKEND_MAX_STRING_LENGTH];
    -#endif
    -
     #if NRF_LOG_BACKEND_SERIAL_USES_UART
     static char m_uart_buffer[NRF_LOG_BACKEND_MAX_STRING_LENGTH];
     static nrf_drv_uart_t m_uart = NRF_DRV_UART_INSTANCE(NRF_LOG_BACKEND_UART_INSTANCE);
    @@ -74,7 +70,6 @@ static void uart_event_handler(nrf_drv_uart_event_t * p_event, void * p_context)
     
     ret_code_t nrf_log_backend_init(bool blocking)
     {
    -    uint32_t              ret_code;
     
         if (m_initialized && (blocking == m_blocking_mode))
         {
    @@ -82,19 +77,12 @@ ret_code_t nrf_log_backend_init(bool blocking)
         }
     
     #if NRF_LOG_BACKEND_SERIAL_USES_RTT
    -    ret_code = SEGGER_RTT_ConfigUpBuffer(
    -        0,
    -        "Normal",
    -        m_rtt_buffer,
    -        NRF_LOG_BACKEND_MAX_STRING_LENGTH,
    -        SEGGER_RTT_MODE_NO_BLOCK_TRIM);
    -    if ( ret_code != 0)
    -    {
    -        return NRF_ERROR_INVALID_STATE;
    -    }
    +		SEGGER_RTT_Init();
     #endif //NRF_LOG_BACKEND_SERIAL_USES_RTT
     
     #if (NRF_LOG_BACKEND_SERIAL_USES_UART)
    +		uint32_t              ret_code;
    +		
         nrf_drv_uart_config_t uart_config = NRF_DRV_UART_DEFAULT_CONFIG;
         uart_config.hwfc     =
                 (nrf_uart_hwfc_t)NRF_LOG_BACKEND_SERIAL_UART_FLOW_CONTROL;
    diff --git a/external/segger_rtt/SEGGER_RTT_Conf.h b/external/segger_rtt/SEGGER_RTT_Conf.h
    index c47f54c..ebd6a49 100644
    --- a/external/segger_rtt/SEGGER_RTT_Conf.h
    +++ b/external/segger_rtt/SEGGER_RTT_Conf.h
    @@ -20,6 +20,7 @@ Purpose : Implementation of SEGGER real-time transfer (RTT) which
     #define SEGGER_RTT_CONF_H
     
     #include "compiler_abstraction.h"
    +#include "sdk_config.h"
     
     #ifdef __ICCARM__
       #include <intrinsics.h>
    @@ -32,10 +33,15 @@ Purpose : Implementation of SEGGER real-time transfer (RTT) which
     **********************************************************************
     */
     
    -#define SEGGER_RTT_MAX_NUM_UP_BUFFERS             (2)     // Max. number of up-buffers (T->H) available on this target    (Default: 2)
    -#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS           (2)     // Max. number of down-buffers (H->T) available on this target  (Default: 2)
    +#define SEGGER_RTT_MAX_NUM_UP_BUFFERS             (1)     // Max. number of up-buffers (T->H) available on this target    (Default: 2)
    +#define SEGGER_RTT_MAX_NUM_DOWN_BUFFERS           (1)     // Max. number of down-buffers (H->T) available on this target  (Default: 2)
     
    +#ifdef NRF_LOG_BACKEND_MAX_STRING_LENGTH
    +#define BUFFER_SIZE_UP                            (NRF_LOG_BACKEND_MAX_STRING_LENGTH)  // Size of the buffer for terminal output of target, up to host (Default: 1k)
    +#else
     #define BUFFER_SIZE_UP                            (1024)  // Size of the buffer for terminal output of target, up to host (Default: 1k)
    +#endif
    +
     #define BUFFER_SIZE_DOWN                          (16)    // Size of the buffer for terminal input to target from host (Usually keyboard input) (Default: 16)
     
     #define SEGGER_RTT_PRINTF_BUFFER_SIZE             (64u)    // Size of buffer for RTT printf to bulk-send chars via RTT     (Default: 64)
    

    It replaces SEGGER_RTT_ConfigUpBuffer() with SEGGER_RTT_Init() which in this case has the same effect and removes all references to m_rtt_buffer. This solves excessive memory allocation problem.

    In order to allow log buffer size configuration the modification of SEGGER_RTT_Conf.h is introduced which uses NRF_LOG_BACKEND_MAX_STRING_LENGTH as default buffer size. Additionally number of up and down buffers is reconfigured to 1 of each (was 2) because that's maximum number usable with Keil + RTT viewer in live debug session. It allows to further reduce amount of used memory.

  • FormerMember
    0 FormerMember

    Thanks for reporting the bug and a proposed fix. The bug is reported internally and will be fixed.

Related