Beware that this post is related to an SDK in maintenance mode
More Info: Consider nRF Connect SDK for new designs
This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

FreeRTOS power consumption and idle hook

Hi,

I'm developing a custom application starting from ble_hrm_freertos application. When NRF_LOG is enabled there is no way let the chip in low power consumption. I found the problem related to the following code in logger_thread function

#if NRF_LOG_ENABLED

/** **************************************************************************
 ** @brief    Logger task
 **
 ** This thread is responsible for processing log entries if logs are deferred.
 ** Thread flushes all log entries and suspends. It is resumed by idle task hook.
 **
 ** @param    arg   Task arguments (unused)
 ** *************************************************************************/

void TASK_Logger(void * arg)
{
    UNUSED_PARAMETER(arg);

    NRF_LOG_INFO("Logger task started");
    while (1)
    {
        NRF_LOG_FLUSH();
        vTaskSuspend(NULL);
    }
}

#endif
and the vApplicationIdleHook function
/** **************************************************************************
 ** @brief    Idle task hook
 **
 ** @note Idle hook must be enabled in FreeRTOS configuration (configUSE_IDLE_HOOK).
 ** *************************************************************************/

void TASK_Idle( void )
{
#if NRF_LOG_ENABLED

    vTaskResume(m_logger_task);

#endif
}

The following behavior is what happens:
  • When no other thread is scheduled the idle hook is called
  • The idle hook resumes the logger thread
  • After logger suspends, the idle hook is called again

This loop clearly prevents the device from going into low power. My question is the following: is there any other way to implement NRF_LOG flush without the side effect of increasing power consumption that much.

Best regards,

Andrea

Parents
  • Yes, you are right, and we have noticed it in this thread. The workaround is also given in my reply taken from the suggestion of other forum member.

    Please try the suggested changes to see if this can be something you can use?

  • Thanks, it works correcly and the power consumption is reduced when detached from RTT Viewer.

    I also added the hook in the nrf_log_frontend.c as mentioned in the previous post

    /**
     * @brief Log pending hook
     *
     */
    __WEAK void log_pending_hook( void )
    {
        // Nothing to do
    }
    
    /**
     * @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_buffer_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_buffer_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_buffer_mask];
    
            p_header->raw = invalid_header.raw;
    
            m_log_data.wr_idx += req_len;
        }
    
        CRITICAL_REGION_EXIT();
        log_pending_hook();
        return ret;
    }
    
    

    I will suggest your reply as the answer.

    Andrea

Reply
  • Thanks, it works correcly and the power consumption is reduced when detached from RTT Viewer.

    I also added the hook in the nrf_log_frontend.c as mentioned in the previous post

    /**
     * @brief Log pending hook
     *
     */
    __WEAK void log_pending_hook( void )
    {
        // Nothing to do
    }
    
    /**
     * @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_buffer_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_buffer_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_buffer_mask];
    
            p_header->raw = invalid_header.raw;
    
            m_log_data.wr_idx += req_len;
        }
    
        CRITICAL_REGION_EXIT();
        log_pending_hook();
        return ret;
    }
    
    

    I will suggest your reply as the answer.

    Andrea

Children
No Data
Related