Partition memory: utility services and data structures

This article continues the look at RTOS partition memory.

Partition Pool Utility Services

Nucleus RTOS has three API calls which provide utility functions associated with partition pools: return information about a partition pool, return number of partition pools in the application and return pointers to all partition pools in the application. The first two of these are implemented in Nucleus SE.

Obtaining Partition Pool Information

This service call obtains a selection of information about a partition pool. The Nucleus SE implementation differs from Nucleus RTOS in that it returns less information, as object naming and suspend ordering are not supported and task suspend may not be enabled.

Nucleus RTOS API Call for Partition Pool Information

Service call prototype:

STATUS NU_Partition_Pool_Information(NU_PARTITION_POOL *pool, CHAR  *name, VOID **start_address, UNSIGNED *pool_size, UNSIGNED *partition_size, UNSIGNED *available, UNSIGNED *allocated, OPTION  *suspend_type, UNSIGNED *tasks_waiting, NU_TASK  **first_task);

Parameters:

pool – pointer to the partition pool about which information is being requested

name – pointer to an 8-character destination area for the partition pool’s name; this includes space for the null terminator.

start_address – a pointer to a variable, which will receive a pointer to the start of the partition pool data area

pool_size – a pointer to a variable, which will receive the size of the partition pool (in bytes)

partition_size – a pointer to a variable, which will receive the size of partitions in this pool

available – a pointer to a variable, which will receive the number of partitions currently available in this pool

allocated – a pointer to a variable, which will receive the number of partitions currently in use in this pool

suspend_type – pointer to a variable for holding the task suspend type; valid task suspend types are NU_FIFO and NU_PRIORITY .

tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this partition pool

first_task – a pointer to a task pointer into which is placed the pointer of the first suspended task

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_POOL – the partition pool pointer is not valid

Nucleus SE API Call for Partition Pool Information

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

STATUS NUSE_Partition_Pool_Information(NUSE_PARTITION_POOL pool, ADDR *start_address, U32 *pool_size, U16 *partition_size, U8 *available, U8 *allocated, U8 *tasks_waiting, NUSE_TASK *first_task)  

Parameters:

pool – the index of the partition pool about which information is being requested

start_address – a pointer to a variable, which will receive a pointer to the start of the partition pool data area

pool_size – a pointer to a variable, which will receive the size of the partition pool (in bytes)

partition_size – a pointer to a variable, which will receive the size of partitions in this pool

available – a pointer to a variable, which will receive the number of partitions currently available in this pool

allocated – a pointer to a variable, which will receive the number of partitions currently in use in this pool

tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this partition pool (nothing returned if task suspend is disabled)

first_task – a pointer to a variable of type NUSE_TASK which will receive the index of the first suspended task (nothing returned if task suspend is disabled)

Returns:

NUSE_SUCCESS – the call was completed successfully

NUSE_INVALID_POOL – the partition pool index is not valid

NUSE_INVALID_POINTER – one or more of the pointer parameters is invalid

Nucleus SE Implementation of Partition Pool Information

The implementation of this API call is quite straightforward:

The function returns the partition pool status. Then, if blocking API calls is enabled, the number of waiting tasks and the index of the first one are returned (otherwise these two parameters are set to 0).

Obtaining the Number of Partition Pools

This service call returns the number of partition pools configured in the application. Whilst in Nucleus RTOS this will vary over time and the returned value will represent the current number of pools, in Nucleus SE the value returned is set at build time and cannot change.

Nucleus RTOS API Call for Number of Partition Pools

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

UNSIGNED NU_Established_Partition_Pools(VOID);

Parameters:

None

Returns:

The number of created partition pools in the application

Nucleus SE API Call for Number of Partition Pools

This API call supports the key functionality of the Nucleus RTOS API.

Service call prototype:

U8 NUSE_Partition_Pool_Count(void);

Parameters:

None

Returns:

The number of configured partition pools in the application

Implementation

The implementation of this API call is almost trivially simple: the value of the #define symbol NUSE_PARTITION_POOL_NUMBER is returned.

Data Structures

Partition pools utilize a number of data structures – in ROM and RAM – which, like other Nucleus SE objects, are a series of tables, included and dimensioned according to the number of pools configured and options selected.

I strongly recommend that application code does not access these data structures directly, but uses the provided API functions. This avoids incompatibility with future versions of Nucleus SE and unwanted side-effects and simplifies porting of an application to Nucleus RTOS. The details of data structures are included here to facilitate easier understanding of the working of the service call code and for debugging.

Kernel RAM Data

These data structures are:

NUSE_Partition_Pool_Partition_Used[] – This is an array of type U8 , with one entry for each configured partition pool, which contains a count of the number of partitions currently in use.

NUSE_Partition_Pool_Blocking_Count[] – This type U8 array contains the counts of how many tasks are blocked on each partition pool. This array only exists if blocking API call support is enabled.

These data structures are all initialized to zeros by NUSE_Init_ Partition_Pool() when Nucleus SE starts up. This is logical, as it renders every partition in every pool unused. A future article will provide a full description of Nucleus SE start-up procedures.

Here are the definitions of these data structures in nuse_init.c file.

User RAM

It is the user’s responsibility to provide an area of RAM for data storage for each configured partition pool. The size of this RAM area must accommodate the size and number of partitions configured (see ROM Data below), with an additional byte for each partition in the pool. Each partition has a data area preceded by a single status byte.

ROM Data

These data structures are:

NUSE_Partition_Pool_Data_Address[] – This is an array of type ADDR , with one entry for each configured partition pool, which contains the address of the start of the data storage area.

NUSE_Partition_Pool_Partition_Number[] – This is an array of type U8 , with one entry for each configured partition pool, which contains the number of partitions in the pool.

NUSE_Partition_Pool_Partition_Size[] – This is an array of type U16 , with one entry for each configured partition pool, which contains the partition size for the pool.

These data structures are all declared and initialized (statically, of course) in nuse_config.c , this:

Partition Pool Data Footprint

Like all kernel objects in Nucleus SE, the amount of data memory required for partition pools is readily predictable.

The ROM data footprint (in bytes) for all the partition pools in an application may be computed thus:

NUSE_PARTITION_POOL_NUMBER * (sizeof(ADDR) + 2)

The kernel RAM data footprint for all the partition pools in an application, when blocking API calls is enabled, is simply two bytes per partition pool. If blocking is disabled, only one byte is required.

The user RAM size for each partition pool varies, but, as mentioned above, may be computed for a pool of index n thus:

NUSE_Partition_Pool_Partition_Number[n] *
(NUSE_Partition_Pool_Partition_Size[n] + 1)

Unimplemented API Calls

Three partition pool API calls found in Nucleus RTOS are not implemented in Nucleus SE:

Create Partition Pool

This API call creates a partition pool. It is not needed with Nucleus SE, as objects are created statically.

Service call prototype:

STATUS NU_Create_Partition_Pool(NU_PARTITION_POOL *pool,
CHAR *name, VOID *start_address,
UNSIGNED pool_size,
UNSIGNED partition_size,
OPTION suspend_type); 

Parameters:

pool – pointer to a user-supplied partition pool control block; this will be used as a “handle” for the partition pool in other API calls

name – pointers to a 7-character, null-terminated name for the partition pool

start_address – specifies the starting address for the partition pool memory area

pool_size – the total number of bytes in the memory area

partition_size – the number of bytes for each partition in the pool. There is a small amount of memory “overhead” associated with each partition; this overhead is required by the two data pointers used

suspend_type – specifies how tasks suspend on the partition pool; valid options for this parameter are NU_FIFO and NU_PRIORITY

Returns:

NU_SUCCESS – indicates successful completion of the service

NU_INVALID_POOL – indicates the partition pool control block pointer is NULL

NU_INVALID_MEMORY – indicates the memory area specified by start_ address is NULL

NU_INVALID_SIZE – indicates the partition size is either 0 or larger than the total partition memory area

NU_INVALID_SUSPEND – indicates the suspend_type parameter is invalid

Delete Partition Pool

This API call deletes a previously created partition pool. It is not needed with Nucleus SE, as objects are created statically and cannot be deleted.

Service call prototype:

STATUS NU_Delete_Partition_Pool(NU_PARTITION_POOL *pool);

Parameters:

pool – pointer to partition pool control block

Returns:

NU_SUCCESS – indicates successful completion of the service

NU_INVALID_POOL – indicates the partition pool pointer is invalid

Partition Pool Pointers

This API call builds a sequential list of pointers to all partition pools in the system. It is not needed with Nucleus SE, as objects are identified by a simple index, not a pointer, and it would be redundant.

Service call prototype:

UNSIGNED NU_Partition_Pool_Pointers(NU_PARTITION_POOL **pointer_list,
UNSIGNED maximum_pointers);  

Parameters:

pointer_list – pointer to an array of NU_PARTITION_POOL pointers; this array will be filled with pointers to established partition pools in the system

maximum_pointers – the maximum number of pointers to place in the array

Returns:

The number of NU_PARTITION_POOL pointers placed into the array

Compatibility with Nucleus RTOS

With all aspects of Nucleus SE, it was my goal to maintain as high a level of applications code compatibility with Nucleus RTOS as possible. Partition pools are no exception and, from a user’s perspective, they are implemented in much the same way as in Nucleus RTOS. There are areas of incompatibility, which have come about where I determined that such an incompatibility would be acceptable, given that the resulting code is easier to understand, or, more likely, could be made more memory efficient. Otherwise, Nucleus RTOS API calls may be almost directly mapped onto Nucleus SE calls. A future article will include further information on using Nucleus SE for users of Nucleus RTOS.

Object Identifiers

In Nucleus RTOS, all objects are described by a data structure – a control block – which has a specific data type. A pointer to this control block serves as an identifier for the partition pool. In Nucleus SE, I decided that a different approach was needed for memory efficiency, and all kernel objects are described by a number of tables in RAM and/or ROM. The size of these tables is determined by the number of each object type that is configured. The identifier for a specific object is simply an index into those tables. So, I have defined NUSE_PARTITION_POOL as being equivalent to U8 ; a variable – not a pointer – of this type then serves as the task identifier. This is a small incompatibility, which is easily handled if code is ported to or from Nucleus RTOS. Object identifiers are normally just stored and passed around and not operated on in any way.

Nucleus RTOS also supports naming of partition pools. These names are only used for target-based debug facilities. I omitted them from Nucleus SE to save memory.

Partition Size and Number

In Nucleus RTOS a partition pool is configured in terms of the overall pool size and the partition size (which carries a two pointer overhead); these parameters are expressed as type UNSIGNED , which is probably 32 bits. In Nucleus SE a partition pool is configured in terms of partition size (to which an additional byte of overhead is added) and number of partitions; these parameters are expressed as a U16 and U8 respectively.

Unimplemented API Calls

Nucleus RTOS supports seven service calls to work with partition pools. Of these, three are not implemented in Nucleus SE. Details of these and of the decision to omit them was outlined above.

The next RTOS Revealed article will look at signals.


Colin Walls has over thirty years experience in the electronics industry, largely dedicated to embedded software. A frequent presenter at conferences and seminars and author of numerous technical articles and two books on embedded software, Colin is an embedded software technologist with Mentor Embedded [the Mentor Graphics Embedded Software Division], and is based in the UK. His regular blog is located at: http://blogs.mentor.com/colinwalls. He may be reached by email at colin_walls@mentor.com

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.