Partition memory - introduction and basic services
Memory partitions were introduced in a previous article, where a comparison with the standard C malloc() function was made. A partition is a memory area obtained from a partition pool. This offers a flexible means for tasks to obtain and release data storage in a deterministic and reliable fashion.
In Nucleus SE, partition pools are configured at build time. There may be a maximum of 16 partition pools configured for an application. If no partition pools are configured, no data structures or service call code appertaining to partition pools are included in the application.
A partition pool is simply an area of memory, which is divided into a specific number of fixed sized partitions. The user has complete control over the size and number of partitions in each pool. Tasks may request to be allocated memory partitions and receive a pointer to the storage area. It is the task’s responsibility not to write data outside of the partition. The partition may be deallocated by any task by passing the pointer to an API function. Requesting the allocation of a partition, when no more are available, may result in an error or task suspension, depending on options selected in the API call and the Nucleus SE configuration.
Configuring Memory Partitions
Number of Partition Pools
As with most aspects of Nucleus SE, the configuration of partition pools is primarily controlled by #define statements in nuse_config.h. The key setting is NUSE_PARTITION_POOL_NUMBER, which determines how many partition pools are configured for the application. The default setting is 0 (i.e. no partition pools are in use) and you can set it to any value up to 16. An erroneous value will result in a compile time error, which is generated by a test in nuse_config_check.h (this is included into nuse_config.c and hence compiled with this module) resulting in a #error statement being compiled.
Choosing a non-zero value is the “master enable” for partition pools. This results in some data structures being defined and sized accordingly. Data structures in ROM require initializing to suitable values that characterize each partition pool. More on data structures in the next article. It also activates the API enabling settings.
Every API function (service call) in Nucleus SE has an enabling #define symbol in nuse_config.h. For partition pools, these are:
By default, all of these are set to FALSE, thus disabling each service call and inhibiting the inclusion of any implementation code. To configure partition pools for an application, you need to select the API calls that you want to use and set their enabling symbols to TRUE.
Here is an extract from the default nuse_config.h file:
A compile time error will result if a partition pool API function is enabled and no partition pools are configured (except for NUSE_Partition_Pool_Count() which is always permitted). If your code uses an API call, which has not been enabled, a link time error will result, as no implementation code will have been included in the application.
Partition Pool Service Calls
Nucleus RTOS supports seven service calls, which appertain to partition pools that provide the following functionality:
Allocate a partition: NU_Allocate_Partition(). Implemented by NUSE_Partition_Allocate() in Nucleus SE.
Deallocate a partition: NU_Deallocate_Partition(). Implemented by NUSE_Partition_Deallocate() in Nucleus SE.
Provide information about a specified partition pool: NU_Partition_Pool_Information(). Implemented by NUSE_Partition_Pool_Information() in Nucleus SE.
Return a count of how many partition pools are (currently) configured for the application: NU_Established_Partition_Pools(). Implemented by NUSE_Partition_Pool_Count() in Nucleus SE.
Add a new partition pool to the application (create): NU_Create_Partition_Pool(). Not implemented in Nucleus SE.
Remove a partition pool from the application (delete): NU_Delete_Partition_Pool(). Not implemented in Nucleus SE.
Return pointers to all the partition pools (currently) in the application: NU_Partition_Pool_Pointers(). Not implemented in Nucleus SE.
The implementation of each of these service calls is examined in detail.
It may be noted that no reset function is provided (in either Nucleus RTOS or Nucleus SE). This is intentional. It is very common practice for one task to allocate a partition and pass a pointer to another task (which will probably deallocate it later). If a partition pool were to be reset, all the partitions would be marked as unused, but there is no means of tracking and notifying all tasks that may be using the partitions.
Partition Allocation and Deallocation Services
The fundamental operations, which can be performed on a partition pool, are allocating a partition (i.e. marking a partition as used and returning its address) from it and deallocating a partition (i.e. marking a partition as unused). Nucleus RTOS and Nucleus SE each provide two basic API calls for these operations, which will be discussed here.
Allocating a Partition
The Nucleus RTOS API call for allocating a partition is very flexible, enabling you to suspend indefinitely, or with a timeout, if the operation cannot be completed immediately; i.e. you try to allocate a partition from a pool in which all partitions are currently allocated. Nucleus SE provides the same service, except task suspend is optional and timeout is not implemented.
Nucleus RTOS API Call for Partition Allocation
Service call prototype:
STATUS NU_Allocate_Partition(NU_PARTITION_POOL *pool,
VOID **return_pointer, UNSIGNED suspend);
NU_SUCCESS – the call was completed successfully
NU_NO_PARTITION – no partitions are available
NU_INVALID_POOL – the partition pool pointer is invalid
NU_INVALID_POINTER – the data return pointer is NULL
NU_INVALID_SUSPEND – suspend was attempted from a non-task thread
NU_TIMEOUT – no partition is available even after suspending for the specified timeout period
NU_POOL_DELETED – partition pool was deleted while the task was suspended
Nucleus SE API Call for Allocating
This API call supports the key functionality of the Nucleus RTOS API.
Service call prototype:
STATUS NUSE_Partition_Allocate(NUSE_PARTITION_POOL pool, ADDR *return_pointer, U8 suspend);
pool – the index (ID) of the partition pool to be utilized
return_pointer – a pointer to a variable of type ADDR which will receive the address of the allocated partition
suspend – specification for task suspend; may be NUSE_NO_SUSPEND or NUSE_SUSPEND
NUSE_SUCCESS – the call was completed successfully
NUSE_NO_PARTITION – no partitions are available
NUSE_INVALID_POOL – the partition pool index is invalid
NUSE_INVALID_POINTER – the data return pointer is NULL
NUSE_INVALID_SUSPEND – suspend was attempted from a non-task thread or when blocking API calls were not enabled