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

Unable to use Memory Manager Diagnostics even on the latest SDK (SDK 17.0.2)

Hello,

I am using SDK 17.0.2 and want to use Memory Manager Diagnostics .

I have added to my project's sdk_config.h the following :

#ifndef MEM_MANAGER_ENABLE_DIAGNOSTICS
#define MEM_MANAGER_ENABLE_DIAGNOSTICS 1
#endif

Once I tried to build my project with this define I got : 

..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:504:42: error: 'BLOC_CAT_COUNT' undeclared here (not in a function); did you mean 'BLOCK_CAT_COUNT'?
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:516:1: error: expected ',' or ';' before 'static'
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:620:19: error: 'm_min_size' undeclared (first use in this function); did you mean 'p_min_size'?
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:620:19: note: each undeclared identifier is reported only once for each function it appears in
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:687:5: error: expected ';' before 'm_module_initialized'
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:757:5: error: expected ';' before '}' token
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:911:23: error: 'm_min_size' undeclared (first use in this function); did you mean 'p_min_size'?
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:923:23: error: 'm_max_count' undeclared (first use in this function); did you mean 'm_cur_count'?
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:970:13: error: 'm_min_size' undeclared (first use in this function); did you mean 'p_min_size'?
..\nRF5_SDK\nRF5_SDK_17.0.2_d674dde\components\libraries\mem_manager\mem_manager.c:972:37: error: 'm_max_count' undeclared (first use in this function); did you mean 'm_cur_count'?
Build failed

Any chance you have an updated file that works?

Parents
  • Hi,

    There seems to be a typo on line 504 in mem_manager.c. This line:

    static const uint32_t m_min_size_default[BLOC_CAT_COUNT] =

    Should be changed to:

    static const uint32_t m_min_size_default[BLOCK_CAT_COUNT] =

    I will report this internally.

    Best regards,
    Jørgen

  • Ok, sorry. I though the rest of the errors was caused by the first one, but I see some of them are separate errors (missing m_max_count and semicolon after NRF_MEM_MANAGER_DIAGNOSE/NRF_MEM_MANAGER_DIAGNOSE_RESET). I have attached a version of the file that compiles in the application, but I did not do any further testing: 

    /**
     * Copyright (c) 2014 - 2020, Nordic Semiconductor ASA
     *
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without modification,
     * are permitted provided that the following conditions are met:
     *
     * 1. Redistributions of source code must retain the above copyright notice, this
     *    list of conditions and the following disclaimer.
     *
     * 2. Redistributions in binary form, except as embedded into a Nordic
     *    Semiconductor ASA integrated circuit in a product or a software update for
     *    such product, must reproduce the above copyright notice, this list of
     *    conditions and the following disclaimer in the documentation and/or other
     *    materials provided with the distribution.
     *
     * 3. Neither the name of Nordic Semiconductor ASA nor the names of its
     *    contributors may be used to endorse or promote products derived from this
     *    software without specific prior written permission.
     *
     * 4. This software, with or without modification, must only be used with a
     *    Nordic Semiconductor ASA integrated circuit.
     *
     * 5. Any software provided in binary form under this license must not be reverse
     *    engineered, decompiled, modified and/or disassembled.
     *
     * THIS SOFTWARE IS PROVIDED BY NORDIC SEMICONDUCTOR ASA "AS IS" AND ANY EXPRESS
     * OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
     * OF MERCHANTABILITY, NONINFRINGEMENT, AND FITNESS FOR A PARTICULAR PURPOSE ARE
     * DISCLAIMED. IN NO EVENT SHALL NORDIC SEMICONDUCTOR ASA OR CONTRIBUTORS BE
     * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
     * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
     * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
     * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
     * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
     * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     */
    #include "sdk_common.h"
    #if NRF_MODULE_ENABLED(MEM_MANAGER)
    #include <stdio.h>
    #include "mem_manager.h"
    #include "nrf_assert.h"
    
    #define NRF_LOG_MODULE_NAME mem_mngr
    
    #if MEM_MANAGER_CONFIG_LOG_ENABLED
    #define NRF_LOG_LEVEL       MEM_MANAGER_CONFIG_LOG_LEVEL
    #define NRF_LOG_INFO_COLOR  MEM_MANAGER_CONFIG_INFO_COLOR
    #define NRF_LOG_DEBUG_COLOR MEM_MANAGER_CONFIG_DEBUG_COLOR
    #else //MEM_MANAGER_CONFIG_LOG_ENABLED
    #define NRF_LOG_LEVEL       0
    #endif //MEM_MANAGER_CONFIG_LOG_ENABLED
    #include "nrf_log.h"
    NRF_LOG_MODULE_REGISTER();
    
    /**
     * @defgroup memory_manager_mutex_lock_unlock Module's Mutex Lock/Unlock Macros.
     *
     * @details Macros used to lock and unlock modules. Currently the SDK does not use mutexes but
     *          framework is provided in case need arises to use an alternative architecture.
     * @{
     */
    #define MM_MUTEX_LOCK()   SDK_MUTEX_LOCK(m_mm_mutex)                                                /**< Lock module using mutex. */
    #define MM_MUTEX_UNLOCK() SDK_MUTEX_UNLOCK(m_mm_mutex)                                              /**< Unlock module using mutex. */
    /** @} */
    
    #undef NULL_PARAM_CHECK
    #undef NULL_PARAM_CHECK_VOID
    #undef VERIFY_MODULE_INITIALIZED
    #undef VERIFY_MODULE_INITIALIZED_VOID
    #undef VERIFY_REQUESTED_SIZE
    #undef VERIFY_REQUESTED_SIZE_VOID
    
    #if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0)
    
    /**
     * @brief Macro for verifying NULL parameters.
     *        Returning with an appropriate error code on failure.
     *
     * @param[in] PARAM Parameter checked for NULL.
     *
     * @retval (NRF_ERROR_NULL | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) when @ref PARAM is NULL.
     */
    #define NULL_PARAM_CHECK(PARAM)                            \
        if ((PARAM) == NULL)                                   \
        {                                                      \
            return (NRF_ERROR_NULL | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \
        }
    
    /**
     * @brief Macro for verifying NULL parameters are not passed to API and returning on failure.
     *
     * @param[in] PARAM Parameter checked for NULL.
     */
    #define NULL_PARAM_CHECK_VOID(PARAM)                       \
        if ((PARAM) == NULL)                                   \
        {                                                      \
            return;                                            \
        }
    
    
    /**
     * @brief Macro for verifying module's initialization status.
     *        Returning with an appropriate error code on failure.
     *
     * @retval (NRF_ERROR_INVALID_STATE | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) module is uninitialized.
     */
    #define VERIFY_MODULE_INITIALIZED()                                     \
        do                                                                  \
        {                                                                   \
            if (!m_module_initialized)                                      \
            {                                                               \
                return (NRF_ERROR_INVALID_STATE | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \
            }                                                               \
        } while (0)
    
    /**
     * @brief Macro for verifying module's initialization status and returning on failure.
     */
    #define VERIFY_MODULE_INITIALIZED_VOID()                                \
        do                                                                  \
        {                                                                   \
            if (!m_module_initialized)                                      \
            {                                                               \
                return;                                                     \
            }                                                               \
        } while (0)
    
    
    /**
     * @brief Macro for verifying requested size of memory does not exceed maximum block
     *       size supported by the module. Returning with appropriate error code on failure.
     *
     * @param[in] SIZE Requested size to be allocated.
     *
     * @retval (NRF_ERROR_INVALID_PARAM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE) if requested size is greater
     *         than the largest block size managed by the module.
     */
    #define VERIFY_REQUESTED_SIZE(SIZE)                                     \
        do                                                                  \
        {                                                                   \
            if (((SIZE) == 0) ||((SIZE) >  MAX_MEM_SIZE))                   \
            {                                                               \
                return (NRF_ERROR_INVALID_PARAM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE); \
            }                                                               \
        } while (0)
    
    
    /**
     * @brief Macro for verifying requested size of memory does not exceed maximum block
     *       size supported by the module. Returns on failure.
     *
     * @param[in] SIZE Requested size to be allocated.
     */
    #define VERIFY_REQUESTED_SIZE_VOID(SIZE)                                \
        do                                                                  \
        {                                                                   \
            if (((SIZE) == 0) ||((SIZE) >  MAX_MEM_SIZE))                   \
            {                                                               \
                return;                                                     \
            }                                                               \
        } while (0)
    
    
    /**@} */
    #else  //MEM_MANAGER_DISABLE_API_PARAM_CHECK
    
    #define NULL_PARAM_CHECK(PARAM)
    #define VERIFY_MODULE_INITIALIZED()
    #define VERIFY_REQUESTED_SIZE(SIZE)
    
    #endif //MEM_MANAGER_DISABLE_API_PARAM_CHECK
    
    
    /**@brief Setting defaults in case XXSmall block not used by application. */
    #ifndef MEMORY_MANAGER_XXSMALL_BLOCK_COUNT
        #define MEMORY_MANAGER_XXSMALL_BLOCK_COUNT 0
        #define MEMORY_MANAGER_XXSMALL_BLOCK_SIZE  0
        #define XXSMALL_BLOCK_START                0
        #define XXSMALL_BLOCK_END                  0
        #define XXSMALL_MEMORY_START               0
    #endif // MEMORY_MANAGER_XXSMALL_BLOCK_SIZE
    
    
    /**@brief Setting defaults in case XSmall block not used by application. */
    #ifndef MEMORY_MANAGER_XSMALL_BLOCK_COUNT
       #define MEMORY_MANAGER_XSMALL_BLOCK_COUNT   0
       #define MEMORY_MANAGER_XSMALL_BLOCK_SIZE    0
       #define XSMALL_BLOCK_START                  0
       #define XSMALL_BLOCK_END                    0
       #define XSMALL_MEMORY_START                 0
    #endif // MEMORY_MANAGER_XSMALL_BLOCK_SIZE
    
    
    /**@brief Setting defaults in case Small block not used by application. */
    #ifndef MEMORY_MANAGER_SMALL_BLOCK_COUNT
       #define MEMORY_MANAGER_SMALL_BLOCK_COUNT    0
       #define MEMORY_MANAGER_SMALL_BLOCK_SIZE     0
       #define SMALL_BLOCK_START                   0
       #define SMALL_BLOCK_END                     0
       #define SMALL_MEMORY_START                  0
    #endif // MEMORY_MANAGER_SMALL_BLOCK_COUNT
    
    
    /**@brief Setting defaults in case Medium block not used by application. */
    #ifndef MEMORY_MANAGER_MEDIUM_BLOCK_COUNT
       #define MEMORY_MANAGER_MEDIUM_BLOCK_COUNT   0
       #define MEMORY_MANAGER_MEDIUM_BLOCK_SIZE    0
       #define MEDIUM_BLOCK_START                  0
       #define MEDIUM_BLOCK_END                    0
       #define MEDIUM_MEMORY_START                 0
    #endif // MEMORY_MANAGER_MEDIUM_BLOCK_COUNT
    
    
    /**@brief Setting defaults in case Large block not used by application. */
    #ifndef MEMORY_MANAGER_LARGE_BLOCK_COUNT
       #define MEMORY_MANAGER_LARGE_BLOCK_COUNT    0
       #define MEMORY_MANAGER_LARGE_BLOCK_SIZE     0
       #define LARGE_BLOCK_START                   0
       #define LARGE_BLOCK_END                     0
       #define LARGE_MEMORY_START                  0
    #endif // MEMORY_MANAGER_LARGE_BLOCK_COUNT
    
    
    /**@brief Setting defaults in case XLarge block not used by application. */
    #ifndef MEMORY_MANAGER_XLARGE_BLOCK_COUNT
       #define MEMORY_MANAGER_XLARGE_BLOCK_COUNT   0
       #define MEMORY_MANAGER_XLARGE_BLOCK_SIZE    0
       #define XLARGE_BLOCK_START                  0
       #define XLARGE_BLOCK_END                    0
       #define XLARGE_MEMORY_START                 0
    #endif // MEMORY_MANAGER_XLARGE_BLOCK_COUNT
    
    
    /**@brief Setting defaults in case XXLarge block not used by application. */
    #ifndef MEMORY_MANAGER_XXLARGE_BLOCK_COUNT
       #define MEMORY_MANAGER_XXLARGE_BLOCK_COUNT  0
       #define MEMORY_MANAGER_XXLARGE_BLOCK_SIZE   0
       #define XXLARGE_BLOCK_START                 0
       #define XXLARGE_BLOCK_END                   0
       #define XXLARGE_MEMORY_START                0
    #endif // MEMORY_MANAGER_XXLARGE_BLOCK_COUNT
    
    
    /**@brief  Based on which blocks are defined, MAX_MEM_SIZE is determined.
     *
     * @note   Also, in case none of these are defined, a compile time error is indicated.
     */
    #if (MEMORY_MANAGER_XXLARGE_BLOCK_COUNT != 0)
        #define MAX_MEM_SIZE MEMORY_MANAGER_XXLARGE_BLOCK_SIZE
    #elif (MEMORY_MANAGER_XLARGE_BLOCK_COUNT != 0)
        #define MAX_MEM_SIZE MEMORY_MANAGER_XLARGE_BLOCK_SIZE
    #elif (MEMORY_MANAGER_LARGE_BLOCK_COUNT != 0)
        #define MAX_MEM_SIZE MEMORY_MANAGER_LARGE_BLOCK_SIZE
    #elif (MEMORY_MANAGER_MEDIUM_BLOCK_COUNT != 0)
        #define MAX_MEM_SIZE MEMORY_MANAGER_MEDIUM_BLOCK_SIZE
    #elif (MEMORY_MANAGER_SMALL_BLOCK_COUNT != 0)
        #define MAX_MEM_SIZE MEMORY_MANAGER_SMALL_BLOCK_SIZE
    #elif (MEMORY_MANAGER_XSMALL_BLOCK_COUNT != 0)
        #define MAX_MEM_SIZE MEMORY_MANAGER_XSMALL_BLOCK_SIZE
    #elif (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT != 0)
        #define MAX_MEM_SIZE MEMORY_MANAGER_XXSMALL_BLOCK_SIZE
    #else
        #err "One of MEMORY_MANAGER_SMALL_BLOCK_COUNT, MEMORY_MANAGER_MEDIUM_BLOCK_COUNT or \
             or MEMORY_MANAGER_LARGE_BLOCK_COUNT should be defined."
    #endif
    
    /**@brief XXSmall block start index in case XXSmall Block is defined. */
    #ifndef XXSMALL_BLOCK_START
    #define XXSMALL_BLOCK_START   0
    #endif // XXSMALL_BLOCK_START
    
    
    /**@brief XSmall block start index in case XSmall Block is defined. */
    #ifndef XSMALL_BLOCK_START
    #define XSMALL_BLOCK_START    (XXSMALL_BLOCK_START + MEMORY_MANAGER_XXSMALL_BLOCK_COUNT)
    #endif // XSMALL_BLOCK_START
    
    
    /**@brief Small block start index in case Small Block is defined. */
    #ifndef SMALL_BLOCK_START
    #define SMALL_BLOCK_START     (XSMALL_BLOCK_START  + MEMORY_MANAGER_XSMALL_BLOCK_COUNT)
    #endif // SMALL_BLOCK_START
    
    
    /**@brief Medium block start index in case Medium Block is defined. */
    #ifndef MEDIUM_BLOCK_START
    #define MEDIUM_BLOCK_START    (SMALL_BLOCK_START   + MEMORY_MANAGER_SMALL_BLOCK_COUNT)
    #endif // MEDIUM_BLOCK_START
    
    
    /**@brief Large block start index in case Large Block is defined. */
    #ifndef LARGE_BLOCK_START
    #define LARGE_BLOCK_START     (MEDIUM_BLOCK_START  + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT)
    #endif // LARGE_BLOCK_START
    
    
    /**@brief XLarge block start index in case XLarge Block is defined. */
    #ifndef XLARGE_BLOCK_START
    #define XLARGE_BLOCK_START    (LARGE_BLOCK_START   + MEMORY_MANAGER_LARGE_BLOCK_COUNT)
    #endif // XLARGE_BLOCK_START
    
    /**@brief XXLarge block start index in case XXLarge Block is defined. */
    #ifndef XXLARGE_BLOCK_START
    #define XXLARGE_BLOCK_START   (XLARGE_BLOCK_START  + MEMORY_MANAGER_XLARGE_BLOCK_COUNT)
    #endif //XXLARGE_BLOCK_START
    
    
    /**@brief XXSmall block end index in case XXSmall Block is defined. */
    #ifndef XXSMALL_BLOCK_END
    #define XXSMALL_BLOCK_END   (XXSMALL_BLOCK_START   + MEMORY_MANAGER_XXSMALL_BLOCK_COUNT)
    #endif // XXSMALL_BLOCK_END
    
    /**@brief XSmall block end index in case XSmall Block is defined. */
    #ifndef XSMALL_BLOCK_END
    #define XSMALL_BLOCK_END    (XSMALL_BLOCK_START    + MEMORY_MANAGER_XSMALL_BLOCK_COUNT)
    #endif // XSMALL_BLOCK_END
    
    
    /**@brief Small block end index in case Small Block is defined. */
    #ifndef SMALL_BLOCK_END
    #define SMALL_BLOCK_END     (SMALL_BLOCK_START     + MEMORY_MANAGER_SMALL_BLOCK_COUNT)
    #endif // SMALL_BLOCK_END
    
    
    /**@brief Medium block end index in case Medium Block is defined. */
    #ifndef MEDIUM_BLOCK_END
    #define MEDIUM_BLOCK_END    (MEDIUM_BLOCK_START    + MEMORY_MANAGER_MEDIUM_BLOCK_COUNT)
    #endif // MEDIUM_BLOCK_END
    
    
    /**@brief Large block end index in case Large Block is defined. */
    #ifndef LARGE_BLOCK_END
    #define LARGE_BLOCK_END     (LARGE_BLOCK_START    + MEMORY_MANAGER_LARGE_BLOCK_COUNT)
    #endif // LARGE_BLOCK_END
    
    
    /**@brief XLarge block end index in case XLarge Block is defined. */
    #ifndef XLARGE_BLOCK_END
    #define XLARGE_BLOCK_END    (XLARGE_BLOCK_START   + MEMORY_MANAGER_XLARGE_BLOCK_COUNT)
    #endif // XLARGE_BLOCK_END
    
    
    /**@brief XXLarge block end index in case XXLarge Block is defined. */
    #ifndef XXLARGE_BLOCK_END
    #define XXLARGE_BLOCK_END   (XXLARGE_BLOCK_START  + MEMORY_MANAGER_XXLARGE_BLOCK_COUNT)
    #endif //XXLARGE_BLOCK_END
    
    
    #define XXSMALL_MEMORY_SIZE (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT * MEMORY_MANAGER_XXSMALL_BLOCK_SIZE)
    #define XSMALL_MEMORY_SIZE  (MEMORY_MANAGER_XSMALL_BLOCK_COUNT  * MEMORY_MANAGER_XSMALL_BLOCK_SIZE)
    #define SMALL_MEMORY_SIZE   (MEMORY_MANAGER_SMALL_BLOCK_COUNT   * MEMORY_MANAGER_SMALL_BLOCK_SIZE)
    #define MEDIUM_MEMORY_SIZE  (MEMORY_MANAGER_MEDIUM_BLOCK_COUNT  * MEMORY_MANAGER_MEDIUM_BLOCK_SIZE)
    #define LARGE_MEMORY_SIZE   (MEMORY_MANAGER_LARGE_BLOCK_COUNT   * MEMORY_MANAGER_LARGE_BLOCK_SIZE)
    #define XLARGE_MEMORY_SIZE  (MEMORY_MANAGER_XLARGE_BLOCK_COUNT  * MEMORY_MANAGER_XLARGE_BLOCK_SIZE)
    #define XXLARGE_MEMORY_SIZE (MEMORY_MANAGER_XXLARGE_BLOCK_COUNT * MEMORY_MANAGER_XXLARGE_BLOCK_SIZE)
    
    
    /**@brief XXSmall memory start index in case XXSmall Block is defined. */
    #ifndef XXSMALL_MEMORY_START
    #define XXSMALL_MEMORY_START  0
    #endif // XXSMALL_MEMORY_START
    
    
    /**@brief XSmall memory start index in case XSmall Block is defined. */
    #ifndef XSMALL_MEMORY_START
    #define XSMALL_MEMORY_START  (XXSMALL_MEMORY_START + XXSMALL_MEMORY_SIZE)
    #endif // XSMALL_MEMORY_START
    
    
    /**@brief Small memory start index in case Small Block is defined. */
    #ifndef SMALL_MEMORY_START
    #define SMALL_MEMORY_START  (XSMALL_MEMORY_START + XSMALL_MEMORY_SIZE)
    #endif // SMALL_MEMORY_START
    
    
    /**@brief Medium memory start index in case Medium Block is defined. */
    #ifndef MEDIUM_MEMORY_START
    #define MEDIUM_MEMORY_START  (SMALL_MEMORY_START + SMALL_MEMORY_SIZE)
    #endif // MEDIUM_MEMORY_START
    
    
    /**@brief Large memory start index in case Large Block is defined. */
    #ifndef LARGE_MEMORY_START
    #define LARGE_MEMORY_START  (MEDIUM_MEMORY_START + MEDIUM_MEMORY_SIZE)
    #endif // LARGE_MEMORY_START
    
    
    /**@brief XLarge memory start index in case XLarge Block is defined. */
    #ifndef XLARGE_MEMORY_START
    #define XLARGE_MEMORY_START  (LARGE_MEMORY_START + LARGE_MEMORY_SIZE)
    #endif // XLARGE_MEMORY_START
    
    
    /**@brief XXLarge memory start index in case XXLarge Block is defined. */
    #ifndef XXLARGE_MEMORY_START
    #define XXLARGE_MEMORY_START  (XLARGE_MEMORY_START + XLARGE_MEMORY_SIZE)
    #endif // XLARGE_MEMORY_START
    
    
    /**@brief Total count of block managed by the module. */
    #define TOTAL_BLOCK_COUNT (MEMORY_MANAGER_XXSMALL_BLOCK_COUNT +                                     \
                               MEMORY_MANAGER_XSMALL_BLOCK_COUNT  +                                     \
                               MEMORY_MANAGER_SMALL_BLOCK_COUNT   +                                     \
                               MEMORY_MANAGER_MEDIUM_BLOCK_COUNT  +                                     \
                               MEMORY_MANAGER_LARGE_BLOCK_COUNT   +                                     \
                               MEMORY_MANAGER_XLARGE_BLOCK_COUNT  +                                     \
                               MEMORY_MANAGER_XXLARGE_BLOCK_COUNT)
    
    
    /**@brief Total memory managed by the module. */
    #define TOTAL_MEMORY_SIZE (XXSMALL_MEMORY_SIZE +                                                    \
                               XSMALL_MEMORY_SIZE  +                                                    \
                               SMALL_MEMORY_SIZE   +                                                    \
                               MEDIUM_MEMORY_SIZE  +                                                    \
                               LARGE_MEMORY_SIZE   +                                                    \
                               XLARGE_MEMORY_SIZE  +                                                    \
                               XXLARGE_MEMORY_SIZE)
    
    
    #define BLOCK_CAT_COUNT                7                                                            /**< Block category count is 7 (xxsmall, xsmall, small, medium, large, xlarge, xxlarge). Having one of the block count to zero has no impact on this count. */
    #define BLOCK_CAT_XXS                  0                                                            /**< Extra Extra Small category identifier. */
    #define BLOCK_CAT_XS                   1                                                            /**< Extra Small category identifier. */
    #define BLOCK_CAT_SMALL                2                                                            /**< Small category identifier. */
    #define BLOCK_CAT_MEDIUM               3                                                            /**< Medium category identifier. */
    #define BLOCK_CAT_LARGE                4                                                            /**< Large category identifier. */
    #define BLOCK_CAT_XL                   5                                                            /**< Extra Large category identifier. */
    #define BLOCK_CAT_XXL                  6                                                            /**< Extra Extra Large category identifier. */
    
    #define BITMAP_SIZE                    32                                                           /**< Bitmap size for each word used to contain block information. */
    #define BLOCK_BITMAP_ARRAY_SIZE        CEIL_DIV(TOTAL_BLOCK_COUNT, BITMAP_SIZE)                     /**< Determines number of blocks needed for book keeping availability status of all blocks. */
    
    
    /**@brief Lookup table for maximum memory size per block category. */
    static const uint32_t m_block_size[BLOCK_CAT_COUNT] =
    {
        MEMORY_MANAGER_XXSMALL_BLOCK_SIZE,
        MEMORY_MANAGER_XSMALL_BLOCK_SIZE,
        MEMORY_MANAGER_SMALL_BLOCK_SIZE,
        MEMORY_MANAGER_MEDIUM_BLOCK_SIZE,
        MEMORY_MANAGER_LARGE_BLOCK_SIZE,
        MEMORY_MANAGER_XLARGE_BLOCK_SIZE,
        MEMORY_MANAGER_XXLARGE_BLOCK_SIZE
    };
    
    /**@brief Lookup table for block start index for each block category. */
    static const uint32_t m_block_start[BLOCK_CAT_COUNT] =
    {
        XXSMALL_BLOCK_START,
        XSMALL_BLOCK_START,
        SMALL_BLOCK_START,
        MEDIUM_BLOCK_START,
        LARGE_BLOCK_START,
        XLARGE_BLOCK_START,
        XXLARGE_BLOCK_START
    };
    
    /**@brief Lookup table for last block index for each block category. */
    static const uint32_t m_block_end[BLOCK_CAT_COUNT] =
    {
        XXSMALL_BLOCK_END,
        XSMALL_BLOCK_END,
        SMALL_BLOCK_END,
        MEDIUM_BLOCK_END,
        LARGE_BLOCK_END,
        XLARGE_BLOCK_END,
        XXLARGE_BLOCK_END
    };
    
    /**@brief Lookup table for memory start range for each block category. */
    static const uint32_t m_block_mem_start[BLOCK_CAT_COUNT] =
    {
        XXSMALL_MEMORY_START,
        XSMALL_MEMORY_START,
        SMALL_MEMORY_START,
        MEDIUM_MEMORY_START,
        LARGE_MEMORY_START,
        XLARGE_MEMORY_START,
        XXLARGE_MEMORY_START
    };
    
    static uint8_t  m_memory[TOTAL_MEMORY_SIZE];                                                        /**< Memory managed by the module. */
    static uint32_t m_mem_pool[BLOCK_BITMAP_ARRAY_SIZE];                                                /**< Bitmap used for book-keeping availability of all blocks managed by the module.  */
    
    #if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1)
    
    uint8_t* mem_begin = &m_memory[0];
    uint8_t* mem_end = &m_memory[TOTAL_MEMORY_SIZE];
    
    /**@brief Lookup table for descriptive strings for each block category. */
    static const char * m_block_desc_str[BLOCK_CAT_COUNT] =
    {
        "XXSmall",
        "XSmall",
        "Small",
        "Medium",
        "Large",
        "XLarge",
        "XXLarge"
    };
    
    static const uint32_t m_min_size_default[BLOCK_CAT_COUNT] =
    {
        MEMORY_MANAGER_XXSMALL_BLOCK_SIZE,
        MEMORY_MANAGER_XSMALL_BLOCK_SIZE,
        MEMORY_MANAGER_SMALL_BLOCK_SIZE,
        MEMORY_MANAGER_MEDIUM_BLOCK_SIZE,
        MEMORY_MANAGER_LARGE_BLOCK_SIZE,
        MEMORY_MANAGER_XLARGE_BLOCK_SIZE,
        MEMORY_MANAGER_XXLARGE_BLOCK_SIZE
    };
    
    /**@brief Table for book keeping smallest size allocated in each block range. */
    static uint32_t m_min_size[BLOCK_CAT_COUNT];
    
    /**@brief Table for book keeping largest size allocated in each block range. */
    static uint32_t m_max_size[BLOCK_CAT_COUNT];
    
    /**@brief Table for keeping the peak count in each block range. */
    static uint32_t m_peak_count[BLOCK_CAT_COUNT];
    
    /**@brief Table for keeping the max count in each block range. */
    static uint32_t m_max_count[BLOCK_CAT_COUNT];
    
    /**@brief Table for keeping the current count in each block range. */
    static uint32_t m_cur_count[BLOCK_CAT_COUNT];
    
    /**@brief Global pointing to minimum size holder for block type being allocated. */
    static uint32_t * p_min_size;
    
    /**@brief Global pointing to maximum size holder for block type being allocated. */
    static uint32_t * p_max_size;
    
    /**@brief Lookup table for count of block available in each block category. */
    static uint32_t m_block_count[BLOCK_CAT_COUNT] =
    {
        MEMORY_MANAGER_XXSMALL_BLOCK_COUNT,
        MEMORY_MANAGER_XSMALL_BLOCK_COUNT,
        MEMORY_MANAGER_SMALL_BLOCK_COUNT,
        MEMORY_MANAGER_MEDIUM_BLOCK_COUNT,
        MEMORY_MANAGER_LARGE_BLOCK_COUNT,
        MEMORY_MANAGER_XLARGE_BLOCK_COUNT,
        MEMORY_MANAGER_XXLARGE_BLOCK_COUNT
    };
    
    #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
    
    SDK_MUTEX_DEFINE(m_mm_mutex)                                                                        /**< Mutex variable. Currently unused, this declaration does not occupy any space in RAM. */
    #if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0)
    static bool     m_module_initialized = false;                                                       /**< State indicating if module is initialized or not. */
    #endif // MEM_MANAGER_DISABLE_API_PARAM_CHECK
    
    
    /**@brief Function to get X and Y coordinates.
     *
     * @details Function to get X and Y co-ordinates for the block identified by index.
     *          Here, X determines relevant word for the block. Y determines the actual bit in the word.
     *
     * @param[in]  index Identifies the block.
     * @param[out] p_x   Points to the word that contains the bit representing the block.
     * @param[out] p_y   Contains the bitnumber in the the word 'X' relevant to the block.
     */
    static __INLINE void get_block_coordinates(uint32_t block_index, uint32_t * p_x, uint32_t * p_y)
    {
        // Determine position of the block in the bitmap.
        // X determines relevant word for the block. Y determines the actual bit in the word.
        const uint32_t x = block_index / BITMAP_SIZE;
        const uint32_t y = (block_index - x * BITMAP_SIZE);
    
        (*p_x) = x;
        (*p_y) = y;
    }
    
    
    /**@brief Function to get the category of the block of size 'size' or block number 'block_index'.*/
    static __INLINE uint32_t get_block_cat(uint32_t size, uint32_t block_index)
    {
        for (uint32_t block_cat = 0; block_cat < BLOCK_CAT_COUNT; block_cat++)
        {
            if (((size != 0) && (size <= m_block_size[block_cat]) &&
                (m_block_end[block_cat] != m_block_start[block_cat])) ||
                (block_index < m_block_end[block_cat]))
            {
                return block_cat;
            }
        }
    
        return 0;
    }
    
    /**@brief Initializes the block by setting it to be free. */
    static void block_init (uint32_t block_index)
    {
        uint32_t x;
        uint32_t y;
    
        // Determine position of the block in the bitmap.
        // X determines relevant word for the block. Y determines the actual bit in the word.
        get_block_coordinates(block_index, &x, &y);
    
    #if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1)
        // Update current use statistics: lower current count in block
        if (!IS_SET(m_mem_pool[x], y))
        {
            uint32_t block_cat = get_block_cat(0, block_index);
            m_cur_count[block_cat]--;
        }
    #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
    
        // Set bit related to the block to indicate that the block is free.
        SET_BIT(m_mem_pool[x], y);
    }
    
    
    /**@brief Function to get the size of the block number 'block_index'. */
    static __INLINE uint32_t get_block_size(uint32_t block_index)
    {
        const uint32_t block_cat = get_block_cat(0, block_index);
    
    #if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1)
        p_min_size = &m_min_size[block_cat];
        p_max_size = &m_max_size[block_cat];
    #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
    
        return m_block_size[block_cat];
    }
    
    
    /**@brief Function to free the block identified by block number 'block_index'. */
    static bool is_block_free(uint32_t block_index)
    {
        uint32_t x;
        uint32_t y;
    
        // Determine position of the block in the bitmap.
        // X determines relevant word for the block. Y determines the actual bit in the word.
        get_block_coordinates(block_index, &x, &y);
    
        return IS_SET(m_mem_pool[x], y);
    }
    
    
    /**@brief Function to allocate the block identified by block number 'block_index'. */
    static void block_allocate(uint32_t block_index)
    {
        uint32_t x;
        uint32_t y;
    
        // Determine position of the block in the bitmap.
        // X determines relevant word for the block. Y determines the actual bit in the word.
        get_block_coordinates(block_index, &x, &y);
    
        CLR_BIT(m_mem_pool[x], y);
    
    #if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1)
        // Update statistics: Add to current count in block.
        uint32_t block_cat = get_block_cat(0, block_index);
        m_cur_count[block_cat]++;
    
        // Report if the peak usage goes up in current block
        if (m_cur_count[block_cat] > m_peak_count[block_cat])
        {
            NRF_LOG_INFO("%d: %d -> %d", block_cat, m_peak_count[block_cat], m_cur_count[block_cat]);
            m_peak_count[block_cat] = m_cur_count[block_cat];
        }
    #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
    }
    
    
    uint32_t nrf_mem_init(void)
    {
        NRF_LOG_DEBUG(">> %s.", (uint32_t)__func__);
    
        SDK_MUTEX_INIT(m_mm_mutex);
    
        MM_MUTEX_LOCK();
    
        uint32_t block_index = 0;
    
        for (block_index = 0; block_index < TOTAL_BLOCK_COUNT; block_index++)
        {
            block_init(block_index);
        }
    
        NRF_MEM_MANAGER_DIAGNOSE_RESET;
    
    #if (MEM_MANAGER_DISABLE_API_PARAM_CHECK == 0)
        m_module_initialized = true;
    #endif // MEM_MANAGER_DISABLE_API_PARAM_CHECK
    
        NRF_MEM_MANAGER_DIAGNOSE;
    
        MM_MUTEX_UNLOCK();
    
        NRF_LOG_DEBUG("<< %s.", (uint32_t)__func__);
    
        return NRF_SUCCESS;
    }
    
    
    uint32_t nrf_mem_reserve(uint8_t ** pp_buffer, uint32_t * p_size)
    {
        VERIFY_MODULE_INITIALIZED();
        NULL_PARAM_CHECK(pp_buffer);
        NULL_PARAM_CHECK(p_size);
    
        const uint32_t requested_size = (*p_size);
    
        VERIFY_REQUESTED_SIZE(requested_size);
    
        NRF_LOG_DEBUG(">> %s, size 0x%04lX.", (uint32_t)__func__, requested_size);
    
        MM_MUTEX_LOCK();
    
        const uint32_t block_cat    = get_block_cat(requested_size, TOTAL_BLOCK_COUNT);
        uint32_t       block_index  = m_block_start[block_cat];
        uint32_t       memory_index = m_block_mem_start[block_cat];
        uint32_t       err_code     = (NRF_ERROR_NO_MEM | NRF_ERROR_MEMORY_MANAGER_ERR_BASE);
    
        NRF_LOG_DEBUG("Start index for the pool = 0x%08lX, total block count 0x%08X",
               block_index,
               TOTAL_BLOCK_COUNT);
    
        for (; block_index < TOTAL_BLOCK_COUNT; block_index++)
        {
            uint32_t block_size = get_block_size(block_index);
    
            if (is_block_free(block_index) == true)
            {
                NRF_LOG_DEBUG("Reserving block 0x%08lX", block_index);
    
                // Search succeeded, found free block.
                err_code     = NRF_SUCCESS;
    
                // Allocate block.
                block_allocate(block_index);
    
                (*pp_buffer) = &m_memory[memory_index];
                (*p_size)    = block_size;
    
            #if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1)
                (*p_min_size) = MIN((*p_min_size), requested_size);
                (*p_max_size) = MAX((*p_max_size), requested_size);
            #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
    
                break;
            }
            memory_index += block_size;
        }
        if (err_code != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Memory reservation failed: err_code %d, memory %p, size %d!",
                    err_code,
                    (uint32_t)(*pp_buffer),
                    (*p_size));
    
            NRF_MEM_MANAGER_DIAGNOSE;
        }
    
        MM_MUTEX_UNLOCK();
    
        NRF_LOG_DEBUG("<< %s %p, result 0x%08lX.", (uint32_t)__func__,
                     (uint32_t)(*pp_buffer), err_code);
    
        return err_code;
    }
    
    
    void * nrf_malloc(uint32_t size)
    {
        uint8_t * buffer = NULL;
        uint32_t allocated_size = size;
    
        uint32_t retval = nrf_mem_reserve(&buffer, &allocated_size);
    
        if (retval != NRF_SUCCESS)
        {
            NRF_LOG_ERROR("Failed to malloc side: %d", size);
            buffer = NULL;
        }
    
        return buffer;
    }
    
    
    void * nrf_calloc(uint32_t count, uint32_t size)
    {
        uint8_t * buffer = NULL;
        uint32_t allocated_size = (size * count);
    
        NRF_LOG_DEBUG("[%s]: Requested size %d, count %d", (uint32_t)__func__, allocated_size, count);
    
        uint32_t retval = nrf_mem_reserve(&buffer, &allocated_size);
        if (retval == NRF_SUCCESS)
        {
            NRF_LOG_DEBUG("[%s]: buffer %p, total size %d", (uint32_t)__func__, (uint32_t)buffer, allocated_size);
            memset(buffer,0, allocated_size);
        }
        else
        {
            NRF_LOG_ERROR("[%s]: Failed to allocate memory %d", (uint32_t)__func__, allocated_size);
            buffer = NULL;
        }
    
        return buffer;
    }
    
    
    void nrf_free(void * p_mem)
    {
        VERIFY_MODULE_INITIALIZED_VOID();
        NULL_PARAM_CHECK_VOID(p_mem);
    
        NRF_LOG_DEBUG(">> %s %p.", (uint32_t)__func__, (uint32_t)p_mem);
    
        MM_MUTEX_LOCK();
    
        uint32_t index;
        uint32_t memory_index = 0;
    
        for (index = 0; index < TOTAL_BLOCK_COUNT; index++)
        {
            if (&m_memory[memory_index] == p_mem)
            {
                // Found a free block of memory, assign.
                NRF_LOG_DEBUG("<< Freeing block %d.", index);
                block_init(index);
                break;
            }
            memory_index += get_block_size(index);
        }
    
        MM_MUTEX_UNLOCK();
    
        NRF_LOG_DEBUG("<< %s.", (uint32_t)__func__);
        return;
    }
    
    
    void * nrf_realloc(void * p_mem, uint32_t size)
    {
        return p_mem;
    }
    
    
    #if defined(MEM_MANAGER_ENABLE_DIAGNOSTICS) && (MEM_MANAGER_ENABLE_DIAGNOSTICS == 1)
    
    /**@brief Function to format and print information with respect to each block.
     *
     * @details Internal function that formats and prints information related to the block category
     *          identified by 'block_cat'. This function also appends the number of bytes in use to
     *          p_mem_in_use based on current count of block in the category.
     *
     * @param[in]  block_cat    Identifies the category of block.
     * @param[out] p_mem_in_use Updates the memory in use based on count in use.
     */
    void print_block_info(uint32_t block_cat, uint32_t * p_mem_in_use)
    {
        #define PRINT_COLUMN_WIDTH      13
        #define PRINT_BUFFER_SIZE       100
        #define ASCII_VALUE_FOR_SPACE   32
    
        char           print_buffer[PRINT_BUFFER_SIZE];
        const uint32_t total_count   = (m_block_start[block_cat] + m_block_count[block_cat]);
        uint32_t       in_use        = 0;
        uint32_t       num_of_blocks = 0;
        uint32_t       index         = m_block_start[block_cat];
        uint32_t       column_number;
    
        // No statistic provided in case block category is not included.
        if (m_block_count[block_cat] != 0)
        {
            memset(print_buffer, ASCII_VALUE_FOR_SPACE, PRINT_BUFFER_SIZE);
    
            for (; index < total_count; index++)
            {
                if (is_block_free(index) == false)
                {
                    num_of_blocks++;
                    in_use += m_block_size[block_cat];
                }
            }
    
            column_number = 0;
            snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                     PRINT_COLUMN_WIDTH,
                     "| %s",
                     m_block_desc_str[block_cat]);
    
            column_number++;
            snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                     PRINT_COLUMN_WIDTH,
                     "| %d",
                     (int)m_block_size[block_cat]);
    
            column_number++;
            snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                     PRINT_COLUMN_WIDTH,
                     "| %d",
                     (int)m_block_count[block_cat]);
    
            column_number++;
            snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                     PRINT_COLUMN_WIDTH,
                     "| %d",
                     (int)num_of_blocks);
    
            column_number++;
            snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                     PRINT_COLUMN_WIDTH,
                     "| %d",
                     (int)m_min_size[block_cat]);
    
            column_number++;
            snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                     PRINT_COLUMN_WIDTH,
                     "| %d",
                     (int)m_max_size[block_cat]);
    
            column_number++;
            snprintf(&print_buffer[column_number * PRINT_COLUMN_WIDTH],
                     PRINT_COLUMN_WIDTH,
                     "| %d",
                     (int)m_max_count[block_cat]);
    
            column_number++;
            const uint32_t column_end = (column_number * PRINT_COLUMN_WIDTH);
    
            for (int j = 0; j < column_end; j ++)
            {
                if (print_buffer[j] == 0)
                {
                    print_buffer[j] = 0x20;
                }
            }
            snprintf(&print_buffer[column_end], 2, "|");
    
            NRF_LOG_INFO("%s", print_buffer);
    
            (*p_mem_in_use) += in_use;
        }
    }
    
    
    void nrf_mem_diagnose(void)
    {
        uint32_t in_use = 0;
    
        NRF_LOG_INFO("");
        NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+");
        NRF_LOG_INFO("| Block      | Size       | Total      | In Use     | Min Alloc  | Max Alloc  |");
        NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+");
    
        print_block_info(BLOCK_CAT_XXS, &in_use);
        print_block_info(BLOCK_CAT_XS, &in_use);
        print_block_info(BLOCK_CAT_SMALL, &in_use);
        print_block_info(BLOCK_CAT_MEDIUM, &in_use);
        print_block_info(BLOCK_CAT_LARGE, &in_use);
        print_block_info(BLOCK_CAT_XL, &in_use);
        print_block_info(BLOCK_CAT_XXL, &in_use);
    
        NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+");
        NRF_LOG_INFO("| Total      | %d      | %d        | %d",
                TOTAL_MEMORY_SIZE, TOTAL_BLOCK_COUNT,in_use);
        NRF_LOG_INFO("+------------+------------+------------+------------+------------+------------+");
    }
    
    
    void nrf_mem_diagnose_reset(void)
    {
        memcpy(&m_min_size, &m_min_size_default, sizeof(m_min_size));
        memset(&m_max_size, 0, sizeof(m_max_size));
        memset(&m_peak_count, 0, sizeof(m_max_count));
        memset(&m_cur_count, 0, sizeof(m_cur_count));
    }
    
    #endif // MEM_MANAGER_ENABLE_DIAGNOSTICS
    /** @} */
    #endif //NRF_MODULE_ENABLED(MEM_MANAGER)
    
    

    I will add the other errors to the internal report.

  • Hello Jørgen,

    I have used this updated version of mem_manager.c and also enabled the memory manager log :

    #define MEM_MANAGER_CONFIG_LOG_ENABLED 1

    I call  nrf_mem_diagnose_reset() , nrf_mem_diagnose() every two seconds.

    This is what I see in my log 

    00> <info> mem_mngr: +------------+------------+------------+------------+------------+------------+
    00>
    00> <info> mem_mngr: | Block | Size | Total | In Use | Min Alloc | Max Alloc |
    00>
    00> <info> mem_mngr: +------------+------------+------------+------------+------------+------------+
    00>
    00> <info> mem_mngr:
    00>
    00> <info> mem_mngr:
    00>
    00> <info> mem_mngr:
    00>
    00> <info> mem_mngr: +------------+------------+------------+------------+------------+------------+
    00>
    00> <info> mem_mngr: | Total | 98432 | 526 | 64
    00>
    00> <info> mem_mngr: +------------+------------+------------+------------+------------+------------+
    00>
    00> <info> mem_mngr: 2: 0 -> 1

     

    I have the feeling that it is not working as expected.

    Can you please clarify?

    Thanks in advance ,

    Rafalino 

  • Hello,

    Can someone explain what should we see when running  nrf_mem_diagnose() ?

    Thanks in advance ,

    Rafalno

  • It looks like print_block_info() will only print info if the block category is included:

    // No statistic provided in case block category is not included.
    if (m_block_count[block_cat] != 0)

    Have you set any of the MEMORY_MANAGER_{SIZE}_BLOCK_COUNT defines in your sdk_config.h file?

Reply Children
Related