Memory Manager#
Overview#
The Memory Manager is a platform-level software module that provides different ways to perform runtime allocations, either one shot or dynamic. The Memory Manager complements the toolchain linker by managing the RAM memory not allocated/partitioned by the linker. It offers different constructs that will help the different Silicon Labs SDK software modules and your application to build, as much as possible, an efficient and optimized RAM layout. The main Memory Manager constructs will be:
A dynamic allocation API
A memory pool API
A dynamic reservation API
The Memory Manager can be used in an RTOS context as it is thread-safe by protecting adequately its internal shared resources.
Initialization#
The initialization part includes the following configuration files:
sl_memory_manager_region_config.h
sl_memory_manager_config.h
These header files offer a few configurations for the Memory Manager. They use the CMSIS Configuration Wizard Annotations that can be rendered by Simplicity Studio to set graphically the configuration settings value.
sl_memory_manager_config.h allows users to configure the minimum block allocation size for the application. The default value is 32 bytes, it can be any 8-byte increment between 32 and 128 bytes inclusively, depending on the application's requirements. This configuration is bound to SL_MEMORY_MANAGER_BLOCK_ALLOCATION_MIN_SIZE. This configuration file also allows the user to enable or disable the memory manager statistics API. This is a feature that provides runtime information about memory usage, helping to optimize memory allocation strategies and detect potential memory leaks. By default the statistics API is enabled. It can be disabled by setting the appropriate configuration in sl_memory_manager_config.h. Disabling this API saves a significant amount of memory, which can be crucial for resource-constrained applications.
sl_memory_manager_region_config.h allows to configure the stack size for the application. SL_STACK_SIZE will be used by the linker to allocate a stack zone in the RAM. In a baremetal application, the stack size is bound to the value set by SL_STACK_SIZE. So you should carefully size the stack in that case. In an RTOS application, the stack size SL_STACK_SIZE will serve mainly for the code running in the main() context until the kernel is launched. Once the kernel is started, the different tasks' stacks, created upon tasks' creation, will allow to save the different contexts (that is task, function, ISR contexts). The main stack will be less active while the application's tasks are running.
Note
It is not possible to specify a minimum heap size via a configuration value in sl_memory_manager_region_config.h. The GCC and IAR linker files define a heap section in RAM that will be the last zone of the RAM partitioned by the toolchain linker. The size of this heap zone will be the remaining space of the RAM. If you need to perform some checks on the heap size, you should do it at runtime using the Memory Manager statistics API. You cannot do it during the toolchain preprocessor time.
The API function sl_memory_init() is used to initialize the Memory Manager module. This function must be called early during your initialization sequence. If either the SL System component (System Setup (sl_system) (deprecated)) or the SL Main component (System Setup (sl_main)) is used by your application, the sl_memory_init() call will be added automatically to your initialization sequence.
Functionalities#
The Memory Manager offers different functionalities such as:
Dynamically allocating and freeing blocks.
Creating and deleting memory pools. Allocating and freeing fixed-size blocks from a given pool.
Reserving and releasing blocks.
Getting statistics about the heap usage and the stack.
Retargeting the standard C library memory functions malloc()/free()/ calloc()/realloc() to the Memory Manager ones.
Overloading the C++ standard new/delete operators to the Memory Manager malloc()/free()
Dynamic Allocation#
The dynamic allocation API allows to dynamically allocate and free memory blocks of various sizes. The API supports the classic signatures of memory functions malloc()/free()/calloc()/realloc() while also offering variants of the same functions.
Operation | Standard-Like Function | Variant Function |
|---|---|---|
Allocating a block | ||
Freeing a block | ||
Allocating a block whose content is zero'ed | ||
Re-allocating a block |
The variants functions sl_memory_xxxx() differs from the standard-like functions with the following:
They return an error code of type sl_status_t. You may want to process any returned error code different from SL_STATUS_OK.
They allow to specify a block alignment requirement in bytes. The alignment can be any power-of-two values between 1 and 512 bytes inclusively. The default block alignment the Memory Manager will use is 8 bytes to maximize CPU accesses to allocated memory blocks.
They allow to specify a block type as long-term or short-term (further explained below). The Memory Manager allows to allocate a block from different ends of the heap to limit the fragmentation.
Allocating a block can be done by specifying your requested size with the simple sl_malloc(). If you have a special alignment requirement, the function sl_memory_alloc_advanced() is the one to use. The Memory Manager will use a first fit algorithm to find the block fitting the requested size. If the found block is too large, the allocator tries to split it to create a new free block from the unwanted portion of the found block. The block internal split operation helps to limit the internal fragmentation.
The dynamic allocation API allows to specify the block type as long-term (BLOCK_TYPE_LONG_TERM) or short-term (BLOCK_TYPE_SHORT_TERM) with the functions sl_memory_alloc() or sl_memory_alloc_advanced(). The long-term (LT) allocations are allocated from the heap start, while short-term (ST) ones are allocated from the heap end. LT/ST allocations relate to the expected lifetime of the block allocation. LT blocks are used for the full duration of the application or for something that is expected to last a long time. For instance, a control data structure enabling the proper functioning of a stack's layer, a driver, a part of the application layer. ST blocks are used for something that is expected to be freed quite quickly. For example, a received buffer that needs to be processed and once processed will be freed. Grouping your allocations as LT blocks and/or ST blocks can help to limit the heap fragmentation. Certain functions does not allow to indicate the block type. In that case, a default type is selected by the allocator.
Function | Block type |
|---|---|
Long-term by default | |
Long-term or short-term | |
Long-term or short-term | |
Long-term by default | |
Long-term or short-term | |
Long-term by default | |
Long-term by default |
Freeing a block is done by calling sl_free() or sl_memory_free(). sl_memory_free() returns an error code of type sl_status_t that you may want to test. Passing a NULL pointer to sl_free() or sl_memory_free() results in a neutral situation where the free() function will do nothing. If the same block is freed twice, the function sl_memory_free() will return an error. During the free operation, the function will try to merge adjacent blocks to the block that is being freed in order to limit the internal fragmentation. The adjacent blocks must, of course, not be in use to be merged.
If you want to get a block from the heap whose content has been initialized to zero to avoid any garbage values, the function sl_calloc() or sl_memory_calloc() can be called.
If you need to reallocate a block, the function sl_realloc() or sl_memory_realloc() should be called. Both versions allow to:
Extend the block with the requested size greater than the original size.
Reduce the block with the requested size smaller than the original size.
Extend a different block with the requested size greater than the original size.
The block can be moved elsewhere in the heap if it is impossible to extend it in its current memory space. A reduced block will always stay in the original block space as the allocator does not need to provide a different block. The content of the reallocated memory block is preserved up to the lesser of the new and old sizes, even if the block is moved to a new location. If the new size is larger, the value of the newly allocated portion is indeterminate. Some combinations of input parameters when calling sl_realloc() or sl_memory_realloc() will lead to the same behavior as sl_malloc(), sl_memory_alloc() or sl_free(), sl_memory_free() (cf. the sl_realloc() or sl_memory_realloc() function description for more details about those combinations).
The following code snippet shows a basic block allocation and deallocation using the standard-like functions:
uint8_t *ptr8;
ptr8 = (uint8_t *)sl_malloc(200);
memset(ptr8, 0xAA, 100);
sl_free(ptr8);
This other code snippet shows the same basic block allocation and deallocation using the variant functions:
uint8_t *ptr8;
sl_status_t status;
status = sl_memory_alloc(100, BLOCK_TYPE_LONG_TERM, (void **)&ptr8);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
memset(ptr8, 0xBB, 100);
status = sl_memory_free(ptr8);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
Memory Pool#
The memory pool API allows to:
Create a pool composed of N number of fixed-size blocks: sl_memory_create_pool().
Delete a pool: sl_memory_delete_pool().
Get a block from the pool: sl_memory_pool_alloc().
Free a pool's block: sl_memory_pool_free().
Memory pools are convenient if you want to ensure a sort of guaranteed quotas for some memory allocations situations. It is also more robust to unexpected allocations errors as opposed to the dynamic allocation API in which a block allocation can fail randomly if there is no free block to satisfy the requested size.
The memory pool API uses a pool handle. This handle is initialized when the pool is created with sl_memory_create_pool(). Then this handle is passed as an input parameter of the other functions. The handle can be allocated statically or dynamically. A static pool handle means the handle of type sl_memory_pool_t{} is a global variable for example. A dynamic pool handle means the handle is obtained from the heap itself by calling the function sl_memory_pool_handle_alloc().The dynamic pool handle will be freed with a call to sl_memory_pool_handle_free().
The following code snippet shows a typical memory pool API sequence using a static pool handle:
uint8_t *ptr8;
sl_status_t status;
sl_memory_pool_t pool1_handle = { 0 };
// Create a pool of 15 blocks whose size is 100 bytes for each block.
status = sl_memory_create_pool(100, 15, &pool1_handle);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
status = sl_memory_pool_alloc(&pool1_handle, (void **)&ptr8);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
memset(ptr8, 0xCC, 100);
status = sl_memory_pool_free(&pool1_handle, ptr8);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
status = sl_memory_delete_pool(&pool1_handle);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
This other code snippet presents the previous typical memory pool API sequence using a dynamic pool handle:
sl_status_t status;
sl_memory_pool_t *pool1_handle = NULL;
status = sl_memory_pool_handle_alloc(&pool1_handle);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
// Create a pool of 15 blocks of 100 bytes in size.
status = sl_memory_create_pool(100, 15, &pool1_handle);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
// Get blocks from the pool, use them and free them once done.
...
status = sl_memory_delete_pool(&pool1_handle);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
status = sl_memory_pool_handle_free(pool1_handle);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
Dynamic Reservation#
The dynamic reservation is a special construct allowing to reserve a block of a given size with sl_memory_reserve_block() and to release it with sl_memory_release_block(). The reserved block can then be used to any application purposes. The reserved block will be taken from the short-term section at the end of the heap. Please note that the dynamic reservation API is not meant to be used in the same way as the dynamic allocation API.
The dynamic reservation API uses a reservation handle. This handle is initialized when the block is reserved with sl_memory_reserve_block(). Then this handle is passed as an input parameter to the other functions. The handle can be allocated statically or dynamically. A static reservation handle means the handle of type sl_memory_reservation_t{} is a global variable for example. A dynamic reservation handle means the handle is obtained from the heap itself by calling the function sl_memory_reservation_handle_alloc(). The dynamic reservaiton handle will be freed with a call to sl_memory_reservation_handle_free().
The following code snippet shows a typical dynamic reservation API sequence using a static reservation handle:
uint8_t *ptr8;
sl_status_t status;
sl_memory_reservation_t reservation_handle1 = { 0 };
status = sl_memory_reserve_block(1024,
SL_MEMORY_BLOCK_ALIGN_8_BYTES,
reservation_handle1,
(void **)&ptr8);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
memset(ptr8, 0xDD, 1024);
status = sl_memory_release_block(&reservation_handle1);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
This other code snippet demonstrates the previous typical dynamic reservation API sequence using a dynamic reservation handle:
uint8_t *ptr8;
sl_status_t status;
sl_memory_reservation_t *reservation_handle1;
status = sl_memory_reservation_handle_alloc(&reservation_handle1);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
status = sl_memory_reserve_block(1024,
SL_MEMORY_BLOCK_ALIGN_8_BYTES,
reservation_handle1,
(void **)&ptr8);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
memset(ptr8, 0xEE, 1024);
status = sl_memory_release_block(&reservation_handle1);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
status = sl_memory_reservation_handle_free(reservation_handle1);
if (status != SL_STATUS_OK) {
// Process the error condition.
}
Statistics#
As your code is allocating and freeing blocks, you may want to know at a certain instant what the current state of the heap is. Some heap statistics queries at runtime can help to understand the current usage of the heap. By using the following statistics functions, you may be able to perform some asynchronous runtime heap checks:
Total heap size: sl_memory_get_total_heap_size().
Current free heap size: sl_memory_get_free_heap_size().
Current used heap size: sl_memory_get_used_heap_size().
Highest accumulated heap size usage: sl_memory_get_heap_high_watermark().
You can reset the high heap usage watermark with sl_memory_reset_heap_high_watermark().
Besides a few functions each dedicated to a specific statistic, the function sl_memory_get_heap_info() allows to get a general heap information structure of type sl_memory_heap_info_t{} with several heap statistics. Some of them overlap the statistics returned by the dedicated functions while the others complements statistics returned by the dedicated functions. Refer to the description of sl_memory_heap_info_t{} for more information of each field.
Retained heap statistics#
When bank retention control is present, the Memory Manager can report how much heap memory will be retained in sleep (EM2). Use sl_memory_heap_get_retention_info and the related getters (e.g. sl_memory_get_retained_size(), sl_memory_get_unretained_size()). Retained size and retained high watermark are tracked independently of heap statistics. Unretained size (see sl_memory_heap_get_unretained_size) requires heap statistics and equals free size + (heap used - retained size); it includes pool free blocks. Retention APIs require SL_MEMORY_MANAGER_STATISTICS_RETENTION_ENABLE and bank retention control (SL_CATALOG_BANK_RETENTION_CONTROL_*). When disabled, getters return (size_t)-1 (size/count) or 0 (absolute mask). Call sl_memory_retention_update_high_watermark() at sleep entry to update the retained high watermark.
If you want to know the start address and the total size of the program's stack and/or heap, simply call respectively the function sl_memory_get_stack_region() and/or sl_memory_get_heap_region().
C/C++ Toolchains Standard Memory Functions Retarget/Overload#
A program can perform dynamic memory allocations and deallocations using the standard memory functions whose implementation is provided by the C or C++ toolchain libraries.
C toolchain for the classic malloc()/free()/calloc()/realloc()
C++ toolchain for the new/delete operators
The Memory Manager supports the C standard memory functions retarget and the C++ new/delete overload.
When the memory_manager component is installed, the C standard memory functions are automatically retargeted to the Memory Manager ones:
GCC: coupled to the linker option "--wrap", the functions retargeted are
standard _malloc_r() -> sl_malloc()
standard _free_r() -> sl_free()
standard _calloc_r() -> sl_calloc()
standard _realloc_r() -> sl_realloc()
IAR: it has three separate heap memory handlers (the basic, the advanced, and the no-free heap handlers). IAR generally auto-selects one of the handlers.
Basic heap
standard __basic_malloc() -> sl_malloc()
standard __basic_free() -> sl_free()
standard __basic_calloc() -> sl_calloc()
standard __basic_realloc() -> sl_realloc()
Advanced heap
standard __iar_dl_malloc() -> sl_malloc()
standard __iar_dl_free() -> sl_free()
standard __iar_dl_calloc() -> sl_calloc()
standard __iar_dl_realloc() -> sl_realloc()
No Free heap
standard __no_free_malloc() -> sl_malloc()
standard __no_free_calloc() -> sl_calloc()
If you need the C++ new/delete global overload calling sl_memory_alloc() and sl_memory_free(), please install the additional component memory_manager_cpp. This global overload of new/delete operators will also apply to any C++ standard containers (for example vector, string, list).
Note
The Silicon Labs SDK generates a GCC or IAR linker script with Simplicity Studio. A typical toolchain linker script will define a section called "heap" or "HEAP". Usually, the C memory standard functions will assume a linker-defined "heap" section exists. If the memory_manager component is present, the toolchain linker script will define a new heap section named "memory_manager_heap" or "MEMORY_MANAGER_HEAP". Since the Memory Manager retargets the standard function malloc()/free()/calloc()/realloc() to the Memory Manager ones, there should not be any issues in your program. If an unlikely situation occurs where the toolchain standard memory functions retarget does not work, your application might end up calling a standard malloc() implementation from the toolchain instead of the Memory Manager one. In that case, a runtime error can occur and it is expected. You should then review the project settings to detect why the Memory Manager retarget did not work properly.
Hints#
Memory Allocations from ISR#
In general, ISR must be kept short. Allocating and freeing blocks from an ISR is possible but you should be careful. Nothing really prevents you from calling the dynamic allocation API functions such as sl_malloc() and sl_free(). But keep in mind a few things with the dynamic allocation API:
The dynamic allocation API functions protect their internal resources such as global lists managing the heap metadata by using critical sections. So when in your ISR, you will disable interrupts for a certain period of time, preventing other interrupts to be processed in time if your application has hard real-time constraints. This increases the overall interrupt latency of your system if this ISR executes very often to perform a dynamic memory operation
They can introduce non-deterministic behavior which is undesirable if your application requires crucial precise timing
A function such as sl_malloc() can fail if there is no block to satisfy your requested size allocation. Implementing the proper error handling in the ISR may increase the time spent in the ISR.
In the end, it really depends of your ISR processing context doing memory allocations/deallocations. If you really need to perform dynamic allocation from ISR, it may be better at least to use a memory pool. Getting and releasing a block from a pool is an operation more deterministic. And if you have properly sized your pool with a number of available blocks, you are less likely to encounter an allocation error.
Modules#
sl_memory_heap_retention_info_t
Enumerations#
Typedefs#
Functions#
Gets size and location of the stack.
Gets size and location of the heap.
Initializes the memory manager.
Reserves a memory block that will never need retention in EM2.
Allocates a memory block of at least requested size from the general-purpose heap.
Dynamically allocates a block of memory from the general-purpose heap.
Dynamically allocates a block of memory from the general-purpose heap.
Frees a previously allocated block.
Frees a dynamically allocated block of memory.
Dynamically allocates a memory block cleared to 0 from the general-purpose heap.
Dynamically allocates a memory block cleared to 0 from the general-purpose heap.
Resizes a previously allocated memory block in the general-purpose heap.
Resizes a previously allocated memory block from the general-purpose heap.
Dynamically reserves a block of memory from the general-purpose heap.
Frees a dynamically reserved block of memory.
Adds a retention request on a reserved block.
Removes a retention request on a reserved block.
Retrieves the size of a memory reservation.
Dynamically allocates a block reservation handle.
Frees a dynamically allocated block reservation handle.
Gets the size of the memory reservation handle structure.
Creates a memory pool in the general-purpose heap.
Creates a memory pool.
Deletes a memory pool.
Deletes a memory pool, but keeps the reservation.
Allocates a block from a memory pool.
Frees a block from a memory pool.
Dynamically allocates a memory pool handle.
Frees a dynamically allocated memory pool handle.
Gets the size of the memory pool handle structure.
Gets the total count of blocks in a memory pool.
Gets the count of free blocks in a memory pool.
Gets the count of used blocks in a memory pool.
Populates an sl_memory_heap_info_t{} structure with the current status of the general-purpose heap.
Retrieves the total size of the general-purpose heap.
Retrieves the current amount of free memory in the general-purpose heap.
Retrieves the current amount of memory used in the general-purpose heap.
Retrieves the general-purpose heap's high watermark.
Resets the general-purpose heap's high watermark to the current heap used.
Retrieves the amount of heap that would be retained in the general-purpose heap if entering EM2.
Retrieves the amount of heap that would not be retained in the general-purpose heap if entering EM2.
Retrieves the total size of RAM banks that would have retention enabled for the general-purpose heap if entering EM2.
Retrieves the number of RAM banks that would have retention enabled for the general-purpose heap if entering EM2.
Retrieves the absolute retained-banks mask for the general-purpose heap's memory type.
Updates the retained high watermark for the general-purpose heap from the current retained size.
Updates the retained high watermark for the specified heap from the current retained size.
Reserves a memory block that will never need retention in EM2 from a specific heap instance.
Allocates a memory block from a specific heap instance.
Allocates a memory block from a specific heap instance.
Frees a previously allocated block from a specific heap instance.
Allocates a memory block cleared to 0 from a specific heap instance.
Resizes a previously allocated memory block from a specific heap instance.
Dynamically reserves a block of memory from a specific heap instance.
Dynamically allocates a block reservation handle from a specific heap instance.
Creates a memory pool from a specific heap instance.
Creates a memory pool from a specific heap instance.
Dynamically allocates a memory pool handle from a specific heap instance.
Populates an sl_memory_heap_info_t{} structure with the current status of a specified heap instance.
Retrieves the total size of a specified heap instance.
Retrieves the current amount of free memory in a specified heap instance.
Retrieves the current amount of memory used in a specified heap instance.
Retrieves a specified heap instance's high watermark.
Resets a specified heap instance's high watermark to the current heap used.
Populates an sl_memory_heap_retention_info_t{} structure with retention statistics for a specified heap instance.
Retrieves the amount of heap that would be retained in the specified heap if entering EM2.
Retrieves the amount of heap that would not be retained in the specified heap if entering EM2.
Retrieves the total size of RAM banks that would have retention enabled for the specified heap if entering EM2.
Retrieves the number of RAM banks that would have retention enabled for the specified heap if entering EM2.
Retrieves the absolute retained-banks mask for the memory type of the given heap.
Macros#
Special value to indicate the default block alignment to the Memory Manager allocator.
Pre-defined values for block alignment managed by the Memory Manager allocator.
16 bytes alignment.
32 bytes alignment.
64 bytes alignment.
128 bytes alignment.
256 bytes alignment.
512 bytes alignment.
Heap attributes.
RAM only accessed by the CPU.
External RAM.
Enumeration Documentation#
sl_memory_block_type_t#
sl_memory_block_type_t
Block type.
| Enumerator | |
|---|---|
| BLOCK_TYPE_LONG_TERM | Long-term block type. |
| BLOCK_TYPE_SHORT_TERM | Short-term block type. |
Function Documentation#
sl_memory_get_stack_region#
sl_memory_region_t sl_memory_get_stack_region (void )
Gets size and location of the stack.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
description of the region reserved for the C stack.
sl_memory_get_heap_region#
sl_memory_region_t sl_memory_get_heap_region (void )
Gets size and location of the heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
description of the region reserved for the C heap.
sl_memory_init#
sl_status_t sl_memory_init (void )
Initializes the memory manager.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
This function should only be called once.
sl_memory_reserve_no_retention#
sl_status_t sl_memory_reserve_no_retention (size_t size, size_t align, void ** block)
Reserves a memory block that will never need retention in EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | size | Size of the block, in bytes. |
| size_t | [in] | align | Required alignment for the block, in bytes. |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
Required alignment of memory block (in bytes) MUST be a power of 2 and can range from 1 to 512 bytes. The define SL_MEMORY_BLOCK_ALIGN_DEFAULT can be specified to select the default alignment.
sl_malloc#
void * sl_malloc (size_t size)
Allocates a memory block of at least requested size from the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | size | Size of the block, in bytes. |
Simple version.
Returns
Pointer to allocated block if successful. Null pointer if allocation failed.
Note
Requesting a block of 0 byte will return a null pointer.
All allocated blocks using this function will be considered long-term allocations.
If building with asserts enabled (DEBUG_EFM or DEBUG_EFM_USER defined in the project), errno is used to store error codes. Possible errno codes are:
ENOMEM: If the allocation failed because the heap is full.
EINVAL: If the passed parameters are invalid (size is 0 or too large).
ENOTRECOVERABLE: If the API was unable to create an empty block.
sl_memory_alloc#
sl_status_t sl_memory_alloc (size_t size, uint8_t type, void ** block)
Dynamically allocates a block of memory from the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | size | Size of the block, in bytes. |
| uint8_t | [in] | type | Type of block (long-term or short-term). BLOCK_TYPE_LONG_TERM BLOCK_TYPE_SHORT_TERM Allocation fallback attributes. SL_MEMORY_HEAP_ALLOC_CPU_RAM SL_MEMORY_HEAP_ALLOC_EXTERNAL_RAM |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_alloc_advanced#
sl_status_t sl_memory_alloc_advanced (size_t size, size_t align, uint8_t type, void ** block)
Dynamically allocates a block of memory from the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | size | Size of the block, in bytes. |
| size_t | [in] | align | Required alignment for the block, in bytes. |
| uint8_t | [in] | type | Type of block (long-term or short term). BLOCK_TYPE_LONG_TERM BLOCK_TYPE_SHORT_TERM Allocation fallback attributes. SL_MEMORY_HEAP_ALLOC_CPU_RAM SL_MEMORY_HEAP_ALLOC_EXTERNAL_RAM |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Advanced version that allows to specify alignment.
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
Required alignment of memory block (in bytes) MUST be a power of 2 and can range from 1 to 512 bytes. The define SL_MEMORY_BLOCK_ALIGN_DEFAULT can be specified to select the default alignment.
sl_free#
void sl_free (void * ptr)
Frees a previously allocated block.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void * | [in] | ptr | Pointer to memory block to be freed. |
Simple version.
Note
Passing a null pointer does nothing.
If building with asserts enabled (DEBUG_EFM or DEBUG_EFM_USER defined in the project), errno is used to store error codes. Possible errno codes are:
EFAULT: If the there was no block at ptr.
EINVAL: If ptr is NULL.
sl_memory_free#
sl_status_t sl_memory_free (void * block)
Frees a dynamically allocated block of memory.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void * | [in] | block | Pointer to the block that must be freed. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_calloc#
void * sl_calloc (size_t item_count, size_t size)
Dynamically allocates a memory block cleared to 0 from the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | item_count | Number of elements to be allocated. |
| size_t | [in] | size | Size of each elements, in bytes. |
Simple version.
Returns
Pointer to allocated block if successful. Null pointer if allocation failed.
Note
All allocated blocks using this function will be considered long-term allocations.
If building with asserts enabled (DEBUG_EFM or DEBUG_EFM_USER defined in the project), errno is used to store error codes. Possible errno codes are:
ENOMEM: If the allocation failed because the heap is full.
EINVAL: If the passed parameters are invalid (size is 0 or too large).
ENOTRECOVERABLE: If the API was unable to create an empty block.
sl_memory_calloc#
sl_status_t sl_memory_calloc (size_t item_count, size_t size, uint8_t type, void ** block)
Dynamically allocates a memory block cleared to 0 from the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | item_count | Number of elements to be allocated. |
| size_t | [in] | size | Size of each elements, in bytes. |
| uint8_t | [in] | type | Type of block (long-term or short-term). BLOCK_TYPE_LONG_TERM BLOCK_TYPE_SHORT_TERM Allocation fallback attributes. SL_MEMORY_HEAP_ALLOC_CPU_RAM SL_MEMORY_HEAP_ALLOC_EXTERNAL_RAM |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_realloc#
void * sl_realloc (void * ptr, size_t size)
Resizes a previously allocated memory block in the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void * | [in] | ptr | Pointer to the allocation to resize. If NULL, behavior is same as sl_malloc(), sl_memory_alloc(). |
| size_t | [in] | size | New size of the block, in bytes. If 0, behavior is same as sl_free(), sl_memory_free(). |
Simple version.
Returns
Pointer to newly allocated block, if successful. Null pointer if re-allocation failed.
Note
All re-allocated blocks using this function will be considered long-term allocations.
'ptr' NULL and 'size' of 0 bytes is an incorrect parameters combination. No reallocation will be done by the function as it is an error condition.
If the new 'size' is the same as the old, the function changes nothing and returns the same provided address 'ptr'.
If building with asserts enabled (DEBUG_EFM or DEBUG_EFM_USER defined in the project), errno is used to store error codes. Possible errno codes are:
ENOMEM: If the allocation failed because the heap is full.
EINVAL: If the passed parameters are invalid (size is too large). If a size of 0 bytes is requested and the free operation failed.
ENOTRECOVERABLE: If the API was unable to create an empty block.
sl_memory_realloc#
sl_status_t sl_memory_realloc (void * ptr, size_t size, void ** block)
Resizes a previously allocated memory block from the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void * | [in] | ptr | Pointer to the allocation to resize. If NULL, behavior is same as sl_malloc(), sl_memory_alloc(). |
| size_t | [in] | size | New size of the block, in bytes. If 0, behavior is same as sl_free(), sl_memory_free(). |
| void ** | [out] | block | Pointer to variable that will receive the start address of the new allocated memory. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
All re-allocated blocks using this function will be considered long-term allocations.
'ptr' NULL and 'size' of 0 bytes is an incorrect parameters combination. No reallocation will be done by the function as it is an error condition.
If the new 'size' is the same as the old, the function changes nothing and returns the same provided address 'ptr'.
sl_memory_reserve_block#
sl_status_t sl_memory_reserve_block (size_t size, size_t align, sl_memory_reservation_t * handle, void ** block)
Dynamically reserves a block of memory from the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | size | Size of the block, in bytes. The minimum size is 32 bytes. If a size smaller than 32 bytes is requested, the function will truncate to 32 bytes. |
| size_t | [in] | align | Required alignment for the block, in bytes. |
| sl_memory_reservation_t * | [in] | handle | Handle to the reserved block. |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
Required alignment of memory block (in bytes) MUST be a power of 2 and can range from 1 to 512 bytes. The define SL_MEMORY_BLOCK_ALIGN_DEFAULT can be specified to select the default alignment.
sl_memory_release_block#
sl_status_t sl_memory_release_block (sl_memory_reservation_t * handle)
Frees a dynamically reserved block of memory.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_reservation_t * | [in] | handle | Handle to the reserved block. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_reservation_add_retention#
sl_status_t sl_memory_reservation_add_retention (const sl_memory_reservation_t * handle)
Adds a retention request on a reserved block.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_reservation_t * | [in] | handle | Pointer to const reservation handle for the reserved block. |
Registers that the reserved block's contents must be retained during deep sleep (EM2).
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
A reservation from sl_memory_reserve_block() is not retained during EM2 until this API is used.
You do not need to pair every call with sl_memory_reservation_remove_retention(); a reservation may stay retained for as long as needed.
Do not use this on a memory pool's reservation; the pool manages retention for that memory and this call corrupts the mechanism.
Calling this API twice on the same reservation without a corresponding call to sl_memory_reservation_remove_retention() will corrupt the retention mechanism.
sl_memory_reservation_remove_retention#
sl_status_t sl_memory_reservation_remove_retention (const sl_memory_reservation_t * handle)
Removes a retention request on a reserved block.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_reservation_t * | [in] | handle | Pointer to const reservation handle for the reserved block. |
Drops one prior retention request from sl_memory_reservation_add_retention(). When nothing else requires retention for that memory, it may no longer be retained during deep sleep (EM2).
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
A reservation from sl_memory_reserve_block() is not retained during EM2 until sl_memory_reservation_add_retention(); see that API.
Only call this once per sl_memory_reservation_add_retention() you intend to undo. Calling it when there was no matching add corrupts the retention mechanism.
Do not use this on a memory pool's reservation; the pool manages retention for that memory and this call corrupts the mechanism.
sl_memory_reservation_get_size#
sl_status_t sl_memory_reservation_get_size (const sl_memory_reservation_t * handle, size_t * size)
Retrieves the size of a memory reservation.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_reservation_t * | [in] | handle | Pointer to const reservation handle for the reserved block. |
| size_t * | [out] | size | Pointer to variable that will receive the size of the reservation, in bytes. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_reservation_handle_alloc#
sl_status_t sl_memory_reservation_handle_alloc (sl_memory_reservation_t ** handle)
Dynamically allocates a block reservation handle.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_reservation_t ** | [out] | handle | Pointer to a reservation handle. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_reservation_handle_free#
sl_status_t sl_memory_reservation_handle_free (sl_memory_reservation_t * handle)
Frees a dynamically allocated block reservation handle.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_reservation_t * | [in] | handle | Handle to the reserved block. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_reservation_handle_get_size#
uint32_t sl_memory_reservation_handle_get_size (void )
Gets the size of the memory reservation handle structure.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Memory reservation handle structure's size in bytes.
sl_memory_create_pool#
sl_status_t sl_memory_create_pool (size_t block_size, uint32_t block_count, sl_memory_pool_t * pool_handle)
Creates a memory pool in the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| size_t | [in] | block_size | Size of each block, in bytes. |
| uint32_t | [in] | block_count | Number of blocks in the pool. |
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Note
This function assumes the 'pool_handle' is provided by the caller:
either statically (e.g. as a global variable)
or dynamically by calling sl_memory_pool_handle_alloc().
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_create_pool_advanced#
sl_status_t sl_memory_create_pool_advanced (sl_memory_reservation_t * reservation_handle, size_t block_size, uint32_t block_count, size_t align, sl_memory_pool_t * pool_handle)
Creates a memory pool.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_reservation_t * | [in] | reservation_handle | Handle to the reservation block used for pool. If NULL, a memory reservation in the general-purpose heap will be done. |
| size_t | [in] | block_size | Size of each block, in bytes. |
| uint32_t | [in] | block_count | Number of blocks in the pool. |
| size_t | [in] | align | Alignment of each block, in bytes. |
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Advanced version that allows to specify reservation handle and block alignment.
Note
This function assumes the 'pool_handle' is provided by the caller:
either statically (e.g. as a global variable)
or dynamically by calling sl_memory_pool_handle_alloc().
If the reservation_handle is NULL, a reservation will be done in the general-purpose heap.
The custom reservation is only available on the power-aware version of the pool. On the lightweight version of the pool, the reservation_handle parameter must be NULL.
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_delete_pool#
sl_status_t sl_memory_delete_pool (sl_memory_pool_t * pool_handle)
Deletes a memory pool.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
All pool allocations need to be freed by calling sl_memory_pool_free() on each block before calling sl_memory_delete_pool().
The pool_handle provided is neither freed or invalidated. It can be reused in a new call to sl_memory_create_pool() or to sl_memory_create_pool_advanced() to create another pool.
sl_memory_delete_pool_no_unreserve#
sl_status_t sl_memory_delete_pool_no_unreserve (sl_memory_pool_t * pool_handle)
Deletes a memory pool, but keeps the reservation.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
This function is only available on the power-aware version of the pool.
All pool allocations need to be freed by calling sl_memory_pool_free() on each block before calling sl_memory_delete_pool().
A reference to the reservation must be kept before calling this function as the reservation will not be freed, thus creating a potential memory leak.
The pool_handle provided is neither freed or invalidated. It can be reused in a new call to sl_memory_create_pool() or to sl_memory_create_pool_advanced() to create another pool.
sl_memory_pool_alloc#
sl_status_t sl_memory_pool_alloc (sl_memory_pool_t * pool_handle, void ** block)
Allocates a block from a memory pool.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
| void ** | [out] | block | Pointer to a variable that will receive the address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_pool_free#
sl_status_t sl_memory_pool_free (sl_memory_pool_t * pool_handle, void * block)
Frees a block from a memory pool.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
| void * | [in] | block | Pointer to the block to free. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_pool_handle_alloc#
sl_status_t sl_memory_pool_handle_alloc (sl_memory_pool_t ** pool_handle)
Dynamically allocates a memory pool handle.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_pool_t ** | [out] | pool_handle | Handle to the memory pool. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_pool_handle_free#
sl_status_t sl_memory_pool_handle_free (sl_memory_pool_t * pool_handle)
Frees a dynamically allocated memory pool handle.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_pool_handle_get_size#
uint32_t sl_memory_pool_handle_get_size (void )
Gets the size of the memory pool handle structure.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Memory pool handle structure's size.
sl_memory_pool_get_total_block_count#
uint32_t sl_memory_pool_get_total_block_count (const sl_memory_pool_t * pool_handle)
Gets the total count of blocks in a memory pool.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Returns
Total number of blocks.
sl_memory_pool_get_free_block_count#
uint32_t sl_memory_pool_get_free_block_count (const sl_memory_pool_t * pool_handle)
Gets the count of free blocks in a memory pool.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Returns
Number of free blocks.
sl_memory_pool_get_used_block_count#
uint32_t sl_memory_pool_get_used_block_count (const sl_memory_pool_t * pool_handle)
Gets the count of used blocks in a memory pool.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Returns
Number of used blocks.
sl_memory_get_heap_info#
sl_status_t sl_memory_get_heap_info (sl_memory_heap_info_t * heap_info)
Populates an sl_memory_heap_info_t{} structure with the current status of the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_info_t * | [out] | heap_info | Pointer to structure that will receive further heap information data. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_get_total_heap_size#
size_t sl_memory_get_total_heap_size (void )
Retrieves the total size of the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Heap's size in bytes.
sl_memory_get_free_heap_size#
size_t sl_memory_get_free_heap_size (void )
Retrieves the current amount of free memory in the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Free heap size in bytes.
sl_memory_get_used_heap_size#
size_t sl_memory_get_used_heap_size (void )
Retrieves the current amount of memory used in the general-purpose heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Used heap size in bytes.
sl_memory_get_heap_high_watermark#
size_t sl_memory_get_heap_high_watermark (void )
Retrieves the general-purpose heap's high watermark.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Highest heap usage in bytes recorded.
sl_memory_reset_heap_high_watermark#
void sl_memory_reset_heap_high_watermark (void )
Resets the general-purpose heap's high watermark to the current heap used.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
sl_memory_get_retained_size#
size_t sl_memory_get_retained_size (void )
Retrieves the amount of heap that would be retained in the general-purpose heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Size in bytes of heap that will be retained in sleep. (size_t)-1 if statistics or retention control is disabled.
sl_memory_get_unretained_size#
size_t sl_memory_get_unretained_size (void )
Retrieves the amount of heap that would not be retained in the general-purpose heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Unretained = free size + explicitly unretained allocations + pool free blocks. Pool free blocks (blocks returned to the pool via sl_memory_pool_free() and not yet re-allocated) count as unretained size.
Returns
Size in bytes of heap that will not be retained in sleep (0 if disabled).
sl_memory_get_retained_banks_size#
size_t sl_memory_get_retained_banks_size (void )
Retrieves the total size of RAM banks that would have retention enabled for the general-purpose heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Size in bytes of retained banks. (size_t)-1 if statistics or retention control is disabled.
sl_memory_get_retained_bank_count#
size_t sl_memory_get_retained_bank_count (void )
Retrieves the number of RAM banks that would have retention enabled for the general-purpose heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Returns
Retained bank count. (size_t)-1 if statistics or retention control is disabled.
sl_memory_get_absolute_retained_banks_mask#
uint64_t sl_memory_get_absolute_retained_banks_mask (void )
Retrieves the absolute retained-banks mask for the general-purpose heap's memory type.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Equivalent to sl_memory_heap_get_absolute_retained_banks_mask() with the default heap. The mask covers all banks in that retention control (memory type), not only the banks used by the default heap.
Returns
Absolute bitmap: bit i = 1 means bank i would be retained in EM2; bit i = 0 means unretained. Valid range 1..UINT64_MAX (all bits set = all banks retained). Returns 0 if retention control or statistics are disabled (0 is not a valid mask because BSS/data always retain some banks).
sl_memory_retention_update_high_watermark#
void sl_memory_retention_update_high_watermark (void )
Updates the retained high watermark for the general-purpose heap from the current retained size.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| void | N/A |
Call this at the moment of going to sleep (e.g. EM2 entry), not on every retained size change. No-op when retention statistics are disabled.
sl_memory_heap_retention_update_high_watermark#
void sl_memory_heap_retention_update_high_watermark (const sl_memory_heap_t * heap)
Updates the retained high watermark for the specified heap from the current retained size.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Heap Handle. |
Call this at the moment of going to sleep (e.g. EM2 entry). No-op when retention statistics are disabled.
sl_memory_heap_reserve_no_retention#
sl_status_t sl_memory_heap_reserve_no_retention (sl_memory_heap_t * heap, size_t size, size_t align, void ** block)
Reserves a memory block that will never need retention in EM2 from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| size_t | [in] | size | Size of the block, in bytes. |
| size_t | [in] | align | Required alignment for the block, in bytes. |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
Required alignment of memory block (in bytes) MUST be a power of 2 and can range from 1 to 512 bytes. The define SL_MEMORY_BLOCK_ALIGN_DEFAULT can be specified to select the default alignment.
sl_memory_heap_alloc#
sl_status_t sl_memory_heap_alloc (sl_memory_heap_t * heap, size_t size, uint8_t type, void ** block)
Allocates a memory block from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| size_t | [in] | size | Size of the block, in bytes. |
| uint8_t | [in] | type | Type of block (long-term or short-term). BLOCK_TYPE_LONG_TERM BLOCK_TYPE_SHORT_TERM |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_alloc_advanced#
sl_status_t sl_memory_heap_alloc_advanced (sl_memory_heap_t * heap, size_t size, size_t align, uint8_t type, void ** block)
Allocates a memory block from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| size_t | [in] | size | Size of the block, in bytes. |
| size_t | [in] | align | Required alignment for the block, in bytes. |
| uint8_t | [in] | type | Type of block (long-term or short term). BLOCK_TYPE_LONG_TERM BLOCK_TYPE_SHORT_TERM |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Advanced version that allows to specify alignment.
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
Required alignment of memory block (in bytes) MUST be a power of 2 and can range from 1 to 512 bytes. The define SL_MEMORY_BLOCK_ALIGN_DEFAULT can be specified to select the default alignment.
sl_memory_heap_free#
sl_status_t sl_memory_heap_free (sl_memory_heap_t * heap, void * block)
Frees a previously allocated block from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. (Unused in this function.) |
| void * | [in] | block | Pointer to the block that must be freed. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_calloc#
sl_status_t sl_memory_heap_calloc (sl_memory_heap_t * heap, size_t item_count, size_t size, uint8_t type, void ** block)
Allocates a memory block cleared to 0 from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| size_t | [in] | item_count | Number of elements to be allocated. |
| size_t | [in] | size | Size of each element, in bytes. |
| uint8_t | [in] | type | Type of block (long-term or short-term). BLOCK_TYPE_LONG_TERM BLOCK_TYPE_SHORT_TERM |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_realloc#
sl_status_t sl_memory_heap_realloc (sl_memory_heap_t * heap, void * ptr, size_t size, void ** block)
Resizes a previously allocated memory block from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| void * | [in] | ptr | Pointer to the allocation to resize. If NULL, behavior is same as sl_memory_heap_alloc(). |
| size_t | [in] | size | New size of the block, in bytes. If 0, behavior is same as sl_memory_heap_free(). |
| void ** | [out] | block | Pointer to variable that will receive the start address of the new allocated memory. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
All re-allocated blocks using this function will be considered long-term allocations.
'ptr' NULL and 'size' of 0 bytes is an incorrect parameters combination. No reallocation will be done by the function as it is an error condition.
If the new 'size' is the same as the old, the function changes nothing and returns the same provided address 'ptr'.
sl_memory_heap_reserve_block#
sl_status_t sl_memory_heap_reserve_block (sl_memory_heap_t * heap, size_t size, size_t align, sl_memory_reservation_t * handle, void ** block)
Dynamically reserves a block of memory from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| size_t | [in] | size | Size of the block, in bytes. The minimum size is 32 bytes. If a size smaller than 32 bytes is requested, the function will truncate to 32 bytes. |
| size_t | [in] | align | Required alignment for the block, in bytes. |
| sl_memory_reservation_t * | [in] | handle | Handle to the reserved block. |
| void ** | [out] | block | Pointer to variable that will receive the start address of the allocated block. NULL in case of error condition. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
Note
Required alignment of memory block (in bytes) MUST be a power of 2 and can range from 1 to 512 bytes. The define SL_MEMORY_BLOCK_ALIGN_DEFAULT can be specified to select the default alignment.
sl_memory_heap_reservation_handle_alloc#
sl_status_t sl_memory_heap_reservation_handle_alloc (sl_memory_heap_t * heap, sl_memory_reservation_t ** handle)
Dynamically allocates a block reservation handle from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| sl_memory_reservation_t ** | [out] | handle | Pointer to a reservation handle. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_create_pool#
sl_status_t sl_memory_heap_create_pool (sl_memory_heap_t * heap, size_t block_size, uint32_t block_count, sl_memory_pool_t * pool_handle)
Creates a memory pool from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| size_t | [in] | block_size | Size of each block, in bytes. |
| uint32_t | [in] | block_count | Number of blocks in the pool. |
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Note
This function assumes the 'pool_handle' is provided by the caller:
either statically (e.g. as a global variable)
or dynamically by calling sl_memory_pool_handle_alloc().
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_create_pool_advanced#
sl_status_t sl_memory_heap_create_pool_advanced (sl_memory_heap_t * heap, size_t block_size, uint32_t block_count, size_t align, sl_memory_pool_t * pool_handle)
Creates a memory pool from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| size_t | [in] | block_size | Size of each block, in bytes. |
| uint32_t | [in] | block_count | Number of blocks in the pool. |
| size_t | [in] | align | Required alignment for each block, in bytes. |
| sl_memory_pool_t * | [in] | pool_handle | Handle to the memory pool. |
Advanced version that allows to specify block alignment
Note
This function assumes the 'pool_handle' is provided by the caller:
either statically (e.g. as a global variable)
or dynamically by calling sl_memory_pool_handle_alloc().
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_pool_handle_alloc#
sl_status_t sl_memory_heap_pool_handle_alloc (sl_memory_heap_t * heap, sl_memory_pool_t ** pool_handle)
Dynamically allocates a memory pool handle from a specific heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| sl_memory_pool_t ** | [out] | pool_handle | Pointer to the memory pool handle. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_get_info#
sl_status_t sl_memory_heap_get_info (const sl_memory_heap_t * heap, sl_memory_heap_info_t * heap_info)
Populates an sl_memory_heap_info_t{} structure with the current status of a specified heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| sl_memory_heap_info_t * | [out] | heap_info | Pointer to structure that will receive further heap information data. |
Returns
SL_STATUS_OK if successful. Error code otherwise.
sl_memory_heap_get_total_size#
size_t sl_memory_heap_get_total_size (const sl_memory_heap_t * heap)
Retrieves the total size of a specified heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Returns
Heap's size in bytes.
sl_memory_heap_get_free_size#
size_t sl_memory_heap_get_free_size (const sl_memory_heap_t * heap)
Retrieves the current amount of free memory in a specified heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Returns
Free heap size in bytes.
sl_memory_heap_get_used_size#
size_t sl_memory_heap_get_used_size (const sl_memory_heap_t * heap)
Retrieves the current amount of memory used in a specified heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Returns
Used heap size in bytes.
sl_memory_heap_get_high_watermark#
size_t sl_memory_heap_get_high_watermark (const sl_memory_heap_t * heap)
Retrieves a specified heap instance's high watermark.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Returns
Highest heap usage in bytes recorded.
sl_memory_heap_reset_high_watermark#
void sl_memory_heap_reset_high_watermark (sl_memory_heap_t * heap)
Resets a specified heap instance's high watermark to the current heap used.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
sl_memory_heap_get_retention_info#
sl_status_t sl_memory_heap_get_retention_info (const sl_memory_heap_t * heap, sl_memory_heap_retention_info_t * info)
Populates an sl_memory_heap_retention_info_t{} structure with retention statistics for a specified heap instance.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
| sl_memory_heap_retention_info_t * | [out] | info | Pointer to structure that will receive retention info. Must not be NULL. |
Returns
SL_STATUS_OK if successful.
SL_STATUS_NULL_POINTER if
infois NULL (no write toinfo).SL_STATUS_INVALID_PARAMETER if
heapis NULL or the heap is not registered for retention statistics (no write toinfo).SL_STATUS_NOT_AVAILABLE when statistics or bank retention control is disabled (struct is zeroed before returning).
Note
When retention statistics or bank retention control is disabled, the function returns SL_STATUS_NOT_AVAILABLE for non-NULL heap and zeroes the struct before returning.
info->retained_high_watermark is updated only when the application calls sl_memory_retention_update_high_watermark() (e.g. at sleep entry).
info->retained_banks_size counts only the part of each retained bank that overlaps the heap range; the first and last heap banks may be partial.
sl_memory_heap_get_retained_size#
size_t sl_memory_heap_get_retained_size (const sl_memory_heap_t * heap)
Retrieves the amount of heap that would be retained in the specified heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Returns
Retained size in bytes (0 if disabled or heap not registered).
sl_memory_heap_get_unretained_size#
size_t sl_memory_heap_get_unretained_size (const sl_memory_heap_t * heap)
Retrieves the amount of heap that would not be retained in the specified heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Unretained = heap free size + explicitly unretained allocations + pool free blocks. Pool free blocks (blocks returned to the pool via sl_memory_pool_free() and not yet re-allocated) count as unretained size.
Returns
Unretained size in bytes. (size_t)-1 if disabled, or
heapis NULL or not registered.
sl_memory_heap_get_retained_banks_size#
size_t sl_memory_heap_get_retained_banks_size (const sl_memory_heap_t * heap)
Retrieves the total size of RAM banks that would have retention enabled for the specified heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Returns
Retained banks size in bytes (0 if disabled or heap not registered).
sl_memory_heap_get_retained_bank_count#
size_t sl_memory_heap_get_retained_bank_count (const sl_memory_heap_t * heap)
Retrieves the number of RAM banks that would have retention enabled for the specified heap if entering EM2.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Handle to the heap instance. |
Returns
Retained bank count. (size_t)-1 if disabled, or
heapis NULL or not registered.
sl_memory_heap_get_absolute_retained_banks_mask#
uint64_t sl_memory_heap_get_absolute_retained_banks_mask (const sl_memory_heap_t * heap)
Retrieves the absolute retained-banks mask for the memory type of the given heap.
| Type | Direction | Argument Name | Description |
|---|---|---|---|
| const sl_memory_heap_t * | [in] | heap | Heap used to identify the retention control (memory type) to query. The mask covers all banks in that control. |
The heap is used only to select which retention control (memory type, e.g. DMEM, DTCM) to query. The returned mask is an absolute bitmap over all banks in that retention control (bank indices 0 to num_banks-1). It includes both banks that belong to this heap's region and banks outside this heap's region that are in the same memory type—so the mask aggregates retention across the entire memory type, not just this heap.
Returns
Absolute bitmap: bit i = 1 means bank i would be retained in EM2; bit i = 0 means unretained. Limited to 64 bits. Valid range 1..UINT64_MAX (all bits set = all banks retained). Returns 0 if retention control or statistics are disabled, or
heapis NULL or not registered (0 is not a valid mask because BSS/data always retain some banks).