The whole truth about the RTOS. Article # 15. Memory sections: services and data structures

Original author: Colin Walls
  • Transfer


In this article, we continue to consider sections of RTOS memory.

Nucleus RTOS has three API calls that provide utility functions related to memory partition pools: returning partition pool information, returning the number of partition pools in an application, and returning pointers to all partition pools in an application. The first two calls are implemented in the Nucleus SE.

Previous articles in the series:
Article # 14. Memory sections: introduction and basic services
Article # 13. Task data structures and unsupported API calls
Article # 12. Task Services
Article # 11. Tasks: configuration and introduction to the API
Article # 10. Scheduler: Additional Features and Saving Context
Article # 9. Scheduler: implementation
Article # 8. Nucleus SE: Internal Design and Deployment
Article # 7. Nucleus SE: Introduction
Article # 6. Other RTOS services
Article # 5. Interaction between tasks and synchronization
Article # 4. Tasks, Context Switching and Interrupts
Article # 3. Tasks and planning
Article # 2. RTOS: Structure and Real Time
Article # 1. RTOS: introduction.

Retrieving partition pool information


This service call allows you to get partial information about the partition pool. The implementation of the Nucleus SE differs from the Nucleus RTOS in that less information is returned in it, since the assignment of names to the objects and suspension requests are not supported, and the suspension of the task is impossible.

Calling for information about the partition pool in Nucleus RTOS


Call Prototype:

STATUS NU_Partition_Pool_Information (NU_PARTITION_POOL * pool, CHAR * namewords, VOID ** start_address, UNSIGNED * pool_size, UNSIGNED * partition_size, UNSIGNED * available, UNSIGNED * allocated, OPTION * suspend_type, UNSIGNED * tasks_shadowing_shadowed, 4S unclaimed *, 2016).

Parameters:

pool - a pointer to the partition pool about which information is requested;
name - pointer to the 8-character destination area for the name of the partition pool; includes space for terminating zero;
start_address - a pointer to a variable that receives a pointer to the beginning of the section pool data area;
pool_size - pointer to the variable that receives the size of the partition pool (in bytes);
partition_size- pointer to the variable that receives the size of the sections in this pool;
available - a pointer to a variable that receives the number of currently available partitions in this pool;
allocated - a pointer to a variable that receives the number of currently used sections in this pool;
suspend_type - a pointer to a variable to get the type of task suspension; valid suspension types are NU_FIFO and NU_PRIORITY ;
tasks_waiting - pointer to a variable that receives the number of suspended tasks in this section pool;
first_task is a pointer to the task pointer in which the pointer to the first suspended task is located.

Return value:

NU_SUCCESS - the call was completed successfully;
NU_INVALID_POOL - invalid pointer to partition pool.

Calling for information about partitioning in Nucleus SE


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 index, partition, index, partition partition, o , * partition_site, NUSE_TASK * first_task
start_address - a pointer to a variable that receives a pointer to the beginning of the section pool data area;
pool_size - pointer to the variable that receives the size of the partition pool (in bytes);
partition_size - a pointer to a variable that receives the size of partitions in this pool;
available - a pointer to a variable that receives the number of currently available partitions in this pool;
allocated - a pointer to a variable that receives the number of currently used sections in this pool;
tasks_waiting - pointer to a variable that receives the number of suspended tasks in this section pool (if task suspension is disabled, 0 is returned);
first_task - a pointer to a variable of type NUSE_TASK , which receives the index of the first suspended task (if the suspension of tasks is disabled, 0 is returned).

Return value:

NUSE_SUCCESS - the call was successful;
NUSE_INVALID_POOL - incorrect partition pool index;
NUSE_INVALID_POINTER - one or more of the passed pointers are incorrect.

Implementing information retrieval and partitioning in Nucleus SE


The implementation of such an API call is simple to implement:



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

Getting the number of partition pools


This call returns information about the number of partition pools configured in the application. While in Nucleus RTOS, this number changes over time, and the return value will represent the current number of pools, in Nucleus SE, the return value is set at build time and remains unchanged.

Call to get the number of partition pools in the Nucleus RTOS


The call supports the core functionality of the Nucleus RTOS API.

Call prototype:

UNSIGNED NU_Established_Partition_Pools (VOID);

Parameters:

None.

Return value: The

number of partition pools created in the application.

Call to get the number of partition pools in a Nucleus SE


This service call supports the core functionality of the Nucleus RTOS API.

Call prototype:

U8 NUSE_Partition_Pool_Count (void);

Parameters:

None

Return Value: The

number of partition pools created in the application.

Implementation


The implementation of this API call is extremely simple: the #define value of the character NUSE_PARTITION_POOL_NUMBER is returned .

Data structures


Like all other Nucleus SE objects, partition pools use structure arrays in both ROM and RAM, the number of which depends on the number of pools specified in the settings.

I strongly recommend that application code refer to such data structures through API functions, rather than directly. This will avoid incompatibility with future versions of the Nucleus SE and unwanted side effects, and also simplifies porting the application to the Nucleus RTOS. The following is a detailed description of the data structures for easier understanding of the work of the service call code and for debugging.

The data structure of the kernel, placed in RAM


These data structures include:

NUSE_Partition_Pool_Partition_Used [] - an array of type U8 , having one entry for each configured partition pool, containing the count of the pools currently used;
NUSE_Partition_Pool_Blocking_Count [] is an array of type U8 containing a counter of blocked tasks in each pool of partitions. This array exists if blocking an API call is possible.

Such data structures are initialized with zeros using NUSE_Init_ Partition_Pool () when the Nucleus SE is started. This is logical because it makes every section in each pool unused (free). The next article will provide a full description of startup procedures in the Nucleus SE.

Below are descriptions of the data structures in the nuse_init.c file .



User data in RAM


The user needs to allocate an area in the RAM for storing data for each partition pool. The amount of space in RAM must correspond to the volume of configured partitions (see “Data in ROM” below) with an additional byte for each partition in the pool. Each section of the data area is preceded by one status byte.

ROM data


These include:

NUSE_Partition_Pool_Data_Address [] - an array of type ADDR , with one entry for each configured partition pool, containing the address of the beginning of the storage area;
NUSE_Partition_Pool_Partition_Number [] - an array of type U8 with one entry for each configured partition pool, containing information on the number of partitions in the pool;
NUSE_Partition_Pool_Partition_Size [] is an U16 type array with one entry for each configured partition pool, containing the partition size for the pools.

Such data structures are declared and initialized (statically) in nuse_config.c :



Memory footprint for partition pool


As with all kernel objects in Nucleus SE, the amount of memory required for partition pools is predictable.

The ROM size (in bytes) for all application partition pools can be calculated as follows:

NUSE_PARTITION_POOL_NUMBER * (sizeof (ADDR) + 2)

The amount of kernel data in RAM for all application pool partitions takes only 2 bytes per partition pool when activated. , with no lock activated - 1 byte.

The amount of memory for storing user data in RAM varies for each partition pool, although, as already mentioned, for a pool with index n it can be calculated as:

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

Unrealized API calls


Three API calls for partition pools, implemented in the Nucleus RTOS, are not supported in Nucleus SE.

Create Partition Pool


This API call creates a pool of sections. In the Nucleus SE, it is not necessary because tasks are created statically.

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 - a pointer to a user control for partition pool management; used as a “handle” for the section pool in other API calls;
name is a pointer to the name of the partition pool, a 7-character string with a zero terminator;
start_address - sets the starting address for the memory area of ​​the partition pool;
pool_size is the total amount of memory in bytes;
partition_size- The amount of memory in bytes for each partition in the pool. Above this, there is an additional small amount of memory associated with each partition, which is realized thanks to the two data pointers used.
suspend_type - defines how tasks are suspended in the partition pool; valid parameter options are NU_FIFO and NU_PRIORITY .

Return value:

NU_SUCCESS - indicates the successful completion of the call;
NU_INVALID_POOL - indicates the zero value of the partition pool control unit ( NULL );
NU_INVALID_MEMORY - indicates the zero value of the memory area defined by start_ address ( NULL );
NU_INVALID_SIZE - indicates that the partition size is either 0 or greater than the memory allocated for the partition;
NU_INVALID_SUSPEND - incorrect value of suspend_type .

Deleting a partition pool


This API call removes the previously created partition pool. In the Nucleus SE, it is not necessary, since objects are created statically and cannot be deleted.

Call prototype:

STATUS NU_Delete_Partition_Pool (NU_PARTITION_POOL * pool);

Parameters:

pool - a pointer to the partition pool control block;

Return value:

NU_SUCCESS - indicates the successful completion of the call;
NU_INVALID_POOL - indicates an incorrect value of the partition pool pointer;

Section Pool Pointers


This API call builds a sequential list of pointers to all partition pools in the system. This is not necessary in the Nucleus SE, since objects are identified by an index, not a pointer.

Call prototype:

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

Parameters:

pointer_list - pointer to an array of pointers NU_PARTITION_POOL ; the array is filled with pointers to the configured pools in the system;
maximum_pointers - the maximum number of pointers that can be placed in an array.

Return value: The

number of NU_PARTITION_POOL pointers placed in the array.

Nucleus RTOS Compatibility


When developing the Nucleus SE, one of the main tasks was to ensure a high level of code compatibility with Nucleus RTOS. Partition pools are no exception, and, from a developer’s point of view, they are implemented in much the same way as in Nucleus RTOS. Some existing areas of incompatibility are acceptable, although it is worth considering that the final code is easier to understand and more efficient in terms of memory. However, Nucleus RTOS API calls can be almost directly used as Nucleus SE calls. In the future, an article is planned with information on the use of Nucleus SE by Nucleus RTOS users.

Object IDs


In Nucleus RTOS, all objects are described by data structures (control units) of a particular type. A pointer to this control block is used as an identifier for the partition pool. I decided that a different approach was needed in Nucleus SE to use memory more efficiently. All kernel objects are described by several tables in RAM and / or ROM. The sizes of these tables are determined by the number of configurable types of all objects. The identifier for a particular object is the index in these tables. Therefore, I have defined NUSE_PARTITION_POOL equivalent to U8after which the variable (not a pointer) of this type serves as the task identifier. This small incompatibility is easy to understand if the code is ported from or to Nucleus RTOS. Object identifiers are usually stored and transmitted unchanged.

Nucleus RTOS also supports naming of partition pools. These names are used only when debugging. I excluded them from the Nucleus SE to save memory.

The number of sections and their volume


In the Nucleus RTOS, the partition pool is configured for the total volume of the pool and the volume of the partitions (which carry 2 more pointers). These parameters are defined as UNSIGNED (approximately 32 bits). In the Nucleus SE, the partition pool is configured based on the volume of the partition (for which an extra byte is added) and the total number of partitions. These parameters are defined as U16 and U8, respectively.

Unrealized API calls


Nucleus RTOS supports 7 partitioning calls, 3 of which are not implemented in Nucleus SE. In more detail about these calls and about the reasons of their exception is stated above.

The next article will be devoted to signals.

About the author: Colin Walls has been working in the electronics industry for more than thirty years, spending a significant amount of time on embedded software. He is now an embedded software engineer in Mentor Embedded (a division of Mentor Graphics). Colin Walls often speaks at conferences and seminars, author of numerous technical articles and two books on embedded software. Lives in the UK. Colin's professional blog , e-mail: colin_walls@mentor.com.

Also popular now: