MCUXpresso_MIMXRT1052xxxxB/components/mem_manager/fsl_component_mem_manager.h

494 lines
19 KiB
C

/*
* Copyright 2018, 2020, 2023 NXP
* All rights reserved.
*
*
* SPDX-License-Identifier: BSD-3-Clause
*/
#ifndef __MEM_MANAGER_H__
#define __MEM_MANAGER_H__
#ifndef SDK_COMPONENT_DEPENDENCY_FSL_COMMON
#define SDK_COMPONENT_DEPENDENCY_FSL_COMMON (1U)
#endif
#if (defined(SDK_COMPONENT_DEPENDENCY_FSL_COMMON) && (SDK_COMPONENT_DEPENDENCY_FSL_COMMON > 0U))
#include "fsl_common.h"
#else
#endif
/*!
* @addtogroup MemManager
* @{
*/
/*****************************************************************************
******************************************************************************
* Public macros
******************************************************************************
*****************************************************************************/
/*!
* @brief Provide Minimal heap size for application to execute correctly.
*
* The application can define a minimal heap size for proper code exection at run time,
* This will issue a link error if the minimal heap size requirement is not fullfilled (not enough space in RAM)
* By Default, Minimal heap size is set to 4 bytes (unlikely enough to have application work correctly)
*/
#if !defined(MinimalHeapSize_c)
#define MinimalHeapSize_c (uint32_t)4
#endif
/*!
* @brief Configures the memory manager light enable.
*/
#ifndef gMemManagerLight
#define gMemManagerLight (1)
#endif
/*!
* @brief Configures the memory manager trace debug enable.
*/
#ifndef MEM_MANAGER_ENABLE_TRACE
#define MEM_MANAGER_ENABLE_TRACE (0)
#endif
/*
* @brief Configures the memory manager remove memory buffer.
*/
#ifndef MEM_MANAGER_BUFFER_REMOVE
#define MEM_MANAGER_BUFFER_REMOVE (0)
#endif
/*!
* @brief Configures the memory manager pre configure.
*/
#ifndef MEM_MANAGER_PRE_CONFIGURE
#define MEM_MANAGER_PRE_CONFIGURE (1)
#endif
#if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
#ifndef MEM_POOL_SIZE
#define MEM_POOL_SIZE (32U)
#endif
#ifndef MEM_BLOCK_SIZE
#define MEM_BLOCK_SIZE (12U)
#endif
#else
#ifndef MEM_POOL_SIZE
#define MEM_POOL_SIZE (20U)
#endif
#ifndef MEM_BLOCK_SIZE
#define MEM_BLOCK_SIZE (4U)
#endif
#endif
#define MAX_POOL_ID 3U
/* Debug Macros - stub if not defined */
#ifndef MEM_DBG_LOG
#define MEM_DBG_LOG(...)
#endif
/* Default memory allocator */
#ifndef MEM_BufferAlloc
#define MEM_BufferAlloc(numBytes) MEM_BufferAllocWithId(numBytes, 0)
#endif
#if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U))
/*
* Defines pools by block size and number of blocks. Must be aligned to 4 bytes.
* Defines block as (blockSize ,numberOfBlocks, id), id must be keep here,
* even id is 0, will be _block_set_(64, 8, 0) _eol_
* and _block_set_(64, 8) _eol_\ could not supported
*/
#ifndef PoolsDetails_c
#define PoolsDetails_c _block_set_(64, 8, 0) _eol_ _block_set_(128, 2, 1) _eol_ _block_set_(256, 6, 1) _eol_
#endif /* PoolsDetails_c */
#define MEM_BLOCK_DATA_BUFFER_NONAME_DEFINE(blockSize, numberOfBlocks, id) \
uint32_t g_poolBuffer##blockSize##_##numberOfBlocks##_##id[(MEM_POOL_SIZE + (numberOfBlocks)*MEM_BLOCK_SIZE + \
((numberOfBlocks) * (blockSize)) + 3U) >> \
2U];
#define MEM_BLOCK_BUFFER_NONAME_DEFINE(blockSize, numberOfBlocks, id) \
MEM_BLOCK_DATA_BUFFER_NONAME_DEFINE(blockSize, numberOfBlocks, id) \
const static mem_config_t g_poolHeadBuffer##blockSize##_##numberOfBlocks##_##id = { \
(blockSize), (numberOfBlocks), (id), (0), (uint8_t *)&g_poolBuffer##blockSize##_##numberOfBlocks##_##id[0]}
#define MEM_BLOCK_NONAME_BUFFER(blockSize, numberOfBlocks, id) \
(uint8_t *)&g_poolHeadBuffer##blockSize##_##numberOfBlocks##_##id
#endif /* MEM_MANAGER_PRE_CONFIGURE */
/*!
* @brief Defines the memory buffer
*
* This macro is used to define the shell memory buffer for memory manager.
* And then uses the macro MEM_BLOCK_BUFFER to get the memory buffer pointer.
* The macro should not be used in any function.
*
* This is a example,
* @code
* MEM_BLOCK_BUFFER_DEFINE(app64, 5, 64,0);
* MEM_BLOCK_BUFFER_DEFINE(app128, 6, 128,0);
* MEM_BLOCK_BUFFER_DEFINE(app256, 7, 256,0);
* @endcode
*
* @param name The name string of the memory buffer.
* @param numberOfBlocks The number Of Blocks.
* @param blockSize The memory block size.
* @param id The id Of memory buffer.
*/
#define MEM_BLOCK_DATA_BUFFER_DEFINE(name, numberOfBlocks, blockSize, id) \
uint32_t \
g_poolBuffer##name[(MEM_POOL_SIZE + numberOfBlocks * MEM_BLOCK_SIZE + numberOfBlocks * blockSize + 3U) >> 2U];
#define MEM_BLOCK_BUFFER_DEFINE(name, numberOfBlocks, blockSize, id) \
MEM_BLOCK_DATA_BUFFER_DEFINE(name, numberOfBlocks, blockSize, id) \
mem_config_t g_poolHeadBuffer##name = {(blockSize), (numberOfBlocks), (id), (0), (uint8_t *)&g_poolBuffer##name[0]}
/*! \
* @brief Gets the memory buffer pointer \
* \
* This macro is used to get the memory buffer pointer. The macro should \
* not be used before the macro MEM_BLOCK_BUFFER_DEFINE is used. \
* \
* @param name The memory name string of the buffer. \
*/
#define MEM_BLOCK_BUFFER(name) (uint8_t *)&g_poolHeadBuffer##name
/*****************************************************************************
******************************************************************************
* Public type definitions
******************************************************************************
*****************************************************************************/
/**@brief Memory status. */
#if (defined(SDK_COMPONENT_DEPENDENCY_FSL_COMMON) && (SDK_COMPONENT_DEPENDENCY_FSL_COMMON > 0U))
typedef enum _mem_status
{
kStatus_MemSuccess = kStatus_Success, /* No error occurred */
kStatus_MemInitError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 1), /* Memory initialization error */
kStatus_MemAllocError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 2), /* Memory allocation error */
kStatus_MemFreeError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 3), /* Memory free error */
kStatus_MemUnknownError = MAKE_STATUS(kStatusGroup_MEM_MANAGER, 4), /* something bad has happened... */
} mem_status_t;
#else
typedef enum _mem_status
{
kStatus_MemSuccess = 0, /* No error occurred */
kStatus_MemInitError = 1, /* Memory initialization error */
kStatus_MemAllocError = 2, /* Memory allocation error */
kStatus_MemFreeError = 3, /* Memory free error */
kStatus_MemUnknownError = 4, /* something bad has happened... */
} mem_status_t;
#endif
/**@brief Memory user config. */
typedef struct _mem_config
{
uint16_t blockSize; /*< The memory block size. */
uint16_t numberOfBlocks; /*< The number Of Blocks. */
uint16_t poolId; /*< The pool id Of Blocks. */
uint16_t reserved; /*< reserved. */
uint8_t *pbuffer; /*< buffer. */
} mem_config_t;
#if defined(gFSCI_MemAllocTest_Enabled_d) && (gFSCI_MemAllocTest_Enabled_d)
/**@brief Memory status. */
typedef enum mem_alloc_test_status
{
kStatus_AllocSuccess = kStatus_Success, /* Allow buffer to be allocated */
kStatus_AllocBlock = kStatus_Busy, /* Block buffer to be allocated */
} mem_alloc_test_status_t;
#endif
#ifdef MEM_STATISTICS
#define MML_INTERNAL_STRUCT_SZ (2 * sizeof(uint32_t) + 48)
#else
#define MML_INTERNAL_STRUCT_SZ (2 * sizeof(uint32_t))
#endif
#define AREA_FLAGS_POOL_NOT_SHARED (1u << 0)
#define AREA_FLAGS_VALID_MASK (AREA_FLAGS_POOL_NOT_SHARED)
#define AREA_FLAGS_RFFU ~(AREA_FLAGS_VALID_MASK)
/**@brief Memory user config. */
typedef struct _mem_area_cfg_s memAreaCfg_t;
struct _mem_area_cfg_s
{
memAreaCfg_t *next; /*< Next registered RAM area descriptor. */
void *start_address; /*< Start address of RAM area. */
void *end_address; /*< Size of registered RAM area. */
uint16_t flags; /*< BIT(0) AREA_FLAGS_POOL_NOT_SHARED means not member of default pool, other bits RFFU */
uint16_t reserved; /*< 16 bit padding */
uint32_t low_watermark; /*< lowest level of number of free bytes */
uint8_t internal_ctx[MML_INTERNAL_STRUCT_SZ]; /* Placeholder for internal allocator data */
};
/*****************************************************************************
******************************************************************************
* Public memory declarations
******************************************************************************
*****************************************************************************/
/*****************************************************************************
******************************************************************************
* Public prototypes
******************************************************************************
*****************************************************************************/
#if defined(__cplusplus)
extern "C" {
#endif /* _cplusplus */
#if (defined(MEM_MANAGER_PRE_CONFIGURE) && (MEM_MANAGER_PRE_CONFIGURE > 0U))
/*!
* @brief Initialises the Memory Manager.
*
*/
mem_status_t MEM_Init(void);
#endif
#if !defined(gMemManagerLight) || (gMemManagerLight == 0)
/*!
* @brief Add memory buffer to memory manager buffer list.
*
* @note This API should be called when need add memory buffer to memory manager buffer list. First use
* MEM_BLOCK_BUFFER_DEFINE to
* define memory buffer, then call MEM_AddBuffer function with MEM_BLOCK_BUFFER Macro as the input parameter.
* @code
* MEM_BLOCK_BUFFER_DEFINE(app64, 5, 64,0);
* MEM_BLOCK_BUFFER_DEFINE(app128, 6, 128,0);
* MEM_BLOCK_BUFFER_DEFINE(app256, 7, 256,0);
*
* MEM_AddBuffer(MEM_BLOCK_BUFFER(app64));
* MEM_AddBuffer(MEM_BLOCK_BUFFER(app128));
* MEM_AddBuffer(MEM_BLOCK_BUFFER(app256));
* @endcode
*
* @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter.
*
* @retval kStatus_MemSuccess Memory manager add buffer succeed.
* @retval kStatus_MemUnknownError Memory manager add buffer error occurred.
*/
mem_status_t MEM_AddBuffer(const uint8_t *buffer);
#endif /* gMemManagerLight */
#if !defined(gMemManagerLight) || (gMemManagerLight == 0)
#if (defined(MEM_MANAGER_BUFFER_REMOVE) && (MEM_MANAGER_BUFFER_REMOVE > 0U))
/*!
* @brief Remove memory buffer from memory manager buffer list.
*
* @note This API should be called when need remove memory buffer from memory manager buffer list. Use MEM_BLOCK_BUFFER
* Macro as the input parameter.
*
* @param buffer Pointer the memory pool buffer, use MEM_BLOCK_BUFFER Macro as the input parameter.
*
* @retval kStatus_MemSuccess Memory manager remove buffer succeed.
* @retval kStatus_MemUnknownError Memory manager remove buffer error occurred.
*/
mem_status_t MEM_RemoveBuffer(uint8_t *buffer);
#endif /* MEM_MANAGER_BUFFER_REMOVE */
#endif /* gMemManagerLight */
/*!
* @brief Allocate a block from the memory pools. The function uses the
* numBytes argument to look up a pool with adequate block sizes.
*
* @param numBytes The number of bytes will be allocated.
* @param poolId The ID of the pool where to search for a free buffer.
* @retval Memory buffer address when allocate success, NULL when allocate fail.
*/
void *MEM_BufferAllocWithId(uint32_t numBytes, uint8_t poolId);
/*!
* @brief Memory buffer free .
*
* @param buffer The memory buffer address will be free.
* @retval kStatus_MemSuccess Memory free succeed.
* @retval kStatus_MemFreeError Memory free error occurred.
*/
mem_status_t MEM_BufferFree(void *buffer);
/*!
* @brief Returns the size of a given buffer.
*
* @param buffer The memory buffer address will be get size.
* @retval The size of a given buffer.
*/
uint16_t MEM_BufferGetSize(void *buffer);
/*!
* @brief Frees all allocated blocks by selected source and in selected pool.
*
* @param poolId Selected pool Id (4 LSBs of poolId parameter) and selected
* source Id (4 MSBs of poolId parameter).
* @retval kStatus_MemSuccess Memory free succeed.
* @retval kStatus_MemFreeError Memory free error occurred.
*/
mem_status_t MEM_BufferFreeAllWithId(uint8_t poolId);
/*!
* @brief Memory buffer realloc.
*
* @param buffer The memory buffer address will be reallocated.
* @param new_size The number of bytes will be reallocated
* @retval kStatus_MemSuccess Memory free succeed.
* @retval kStatus_MemFreeError Memory free error occurred.
*/
void *MEM_BufferRealloc(void *buffer, uint32_t new_size);
/*!
* @brief Get the address after the last allocated block if MemManagerLight is used.
*
* @retval UpperLimit Return the address after the last allocated block if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_GetHeapUpperLimit(void);
#if defined(gMemManagerLight) && (gMemManagerLight > 0)
/*!
* @brief Get the address after the last allocated block in area defined by id.
*
* @param[in] id 0 means memHeap, other values depend on number of registered areas
*
* @retval UpperLimit Return the address after the last allocated block if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_GetHeapUpperLimitByAreaId(uint8_t id);
#endif
/*!
* @brief Get the free space low watermark.
*
* @retval FreeHeapSize Return the heap space low water mark free if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_GetFreeHeapSizeLowWaterMark(void);
/*!
* @brief Get the free space low watermark.
*
* @param area_id Selected area Id
*
* @retval Return the heap space low water mark free if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_GetFreeHeapSizeLowWaterMarkByAreaId(uint8_t area_id);
/*!
* @brief Reset the free space low watermark.
*
* @retval FreeHeapSize Return the heap space low water mark free at the time it was reset
* if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_ResetFreeHeapSizeLowWaterMark(void);
/*!
* @brief Reset the free space low watermark.
*
* @param area_id Selected area Id
*
* @retval FreeHeapSize Return the heap space low water mark free at the time it was reset
* if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_ResetFreeHeapSizeLowWaterMarkByAreaId(uint8_t area_id);
/*!
* @brief Get the free space in the heap for a area id.
*
* @param area_id area_id whose available size is requested (0 means generic pool)
*
* @retval FreeHeapSize Return the free space in the heap if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_GetFreeHeapSizeByAreaId(uint8_t area_id);
/*!
* @brief Get the free space in the heap.
*
* @retval FreeHeapSize Return the free space in the heap if MemManagerLight is used.
* @retval 0 Return 0 in case of the legacy MemManager.
*/
uint32_t MEM_GetFreeHeapSize(void);
#if defined(gMemManagerLight) && (gMemManagerLight > 0)
/*!
* @brief Selective RAM bank reinit after low power, based on a requested address range
* Useful for ECC RAM banks
* Defined as weak and empty in fsl_component_mem_manager_light.c to be overloaded by user
*
* @param[in] startAddress Start address of the requested range
* @param[in] endAddress End address of the requested range
*/
void MEM_ReinitRamBank(uint32_t startAddress, uint32_t endAddress);
#endif /* gMemManagerLight */
#if !defined(gMemManagerLight) || (gMemManagerLight == 0)
#if (defined(MEM_MANAGER_ENABLE_TRACE) && (MEM_MANAGER_ENABLE_TRACE > 0U))
/*!
* @brief Function to print statistics related to memory blocks managed by memory manager. Like bellow:
* allocationFailures: 241 freeFailures:0
* POOL: ID 0 status:
* numBlocks allocatedBlocks allocatedBlocksPeak poolFragmentWaste poolFragmentWastePeak poolFragmentMinWaste
* poolTotalFragmentWaste
* 5 5 5 59 63 59 305
* Currently pool meory block allocate status:
* Block 0 Allocated bytes: 1
* Block 1 Allocated bytes: 2
* Block 2 Allocated bytes: 3
* Block 3 Allocated bytes: 4
* Block 4 Allocated bytes: 5
*
* @details This API prints information with respects to each pool and block, including Allocated size,
* total block count, number of blocks in use at the time of printing, The API is intended to
* help developers tune the block sizes to make optimal use of memory for the application.
*
* @note This API should be disable by configure MEM_MANAGER_ENABLE_TRACE to 0
*
*/
void MEM_Trace(void);
#endif /* MEM_MANAGER_ENABLE_TRACE */
#endif /* gMemManagerLight */
#if defined(gMemManagerLight) && (gMemManagerLight == 1)
void *MEM_CallocAlt(size_t len, size_t val);
#endif /*gMemManagerLight == 1*/
#if defined(gMemManagerLight) && (gMemManagerLight > 0)
/*!
* @brief Function to register additional areas to allocate memory from.
*
* @param[in] area_desc memAreaCfg_t structure defining start address and end address of area.
* This atructure may not be in rodata becasue the next field and internal private
* context are reserved in this structure. If NULL defines the default memHeap area.
* @param[out] area_id pointer to return id of area. Required if allocation from specific pool
* is required.
* @param[in] flags BIT(0) means that allocations can be performed in pool only explicitly and
* it is not a member of the default pool (id 0). Invalid for initial registration call.
* @return kStatus_MemSuccess if success, kStatus_MemInitError otherwise.
*
*/
mem_status_t MEM_RegisterExtendedArea(memAreaCfg_t *area_desc, uint8_t *area_id, uint16_t flags);
/*!
* @brief Function to unregister an extended area
*
* @param[in] area_id must be different from 0 (main heap).
*
* @return kStatus_MemSuccess if success,
* kStatus_MemFreeError if area_id is 0 or area not found or still has buffers in use.
*
*/
mem_status_t MEM_UnRegisterExtendedArea(uint8_t area_id);
#endif
#if defined(__cplusplus)
}
#endif
/*! @}*/
#endif /* #ifndef __MEM_MANAGER_H__ */