Event flag groups: utility services and data structures

This article continues the look at event flag groups.

Event Flag Group Utility Services

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

Event Flag Group Information

This service call obtains a selection of information about an event flag group. 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 Event Group Information

Service call prototype:

STATUS NU_Event_Group_Information(NU_EVENT_GROUP *group,
CHAR *name, UNSIGNED *even
t_flags, UNSIGNED *tasks_waiting,
NU_TASK **first_task);

Parameters:

group – pointer to the user-supplied event flag group control block

name – pointer to an 8-character destination area for the event flag group’s name; this includes space for the null terminator

event_flags – a pointer to a variable, which will receive the current value of the specified event flag group

tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this event flag group

first_task – a pointer to a variable of type NU_TASK which will receive a pointer to the first suspended task

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_GROUP – the event flag group pointer is not valid

Nucleus SE API Call for Event Group Information

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

Service call prototype:

STATUS NUSE_Event_Group_Information(NUSE_EVENT_GROUP group,
U8 *event_flags, U8 *tasks_waiting, NUSE_TASK *first_task);

Parameters:

group – the index of the event flag group about which information is being requested

event_flags – a pointer to a variable, which will receive the current value of the specified event flag group

tasks_waiting – a pointer to a variable which will receive the number of tasks suspended on this event flag group (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_GROUP – the event flag group index is not valid

Nucleus SE Implementation of Event Group Information

The implementation of this API call is quite straightforward:

*event_flags = NUSE_Event_Group_Data[group]; #if NUSE_BLOCKING_ENABLE     *tasks_waiting = NUSE_Event_Group_Blocking_Count[group];    if (NUSE_Event_Group_Blocking_Count[group] != 0)    {        U8 index;         for (index=0; index<NUSE_TASK_NUMBER; index++)        {            if ((LONIB(NUSE_Task_Status[index]) ==                 NUSE_EVENT_SUSPEND)                && (HINIB(NUSE_Task_Status[index]) == group))            {                *first_task = index;                break;            }        }    }    else    {        *first_task = 0;    } #else     *tasks_waiting = 0;    *first_task = 0; #endif return NUSE_SUCCESS;

The function returns the value of the event flag group. 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 Event Flag Groups

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

Nucleus RTOS API Call for Event Flag Group Count

Service call prototype:

UNSIGNED NU_Established_Event_Groups(VOID);

Parameters:

None

Returns:

The current number of created event flag groups in the application

Nucleus SE API Call for Event Flag Group Count

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

Service call prototype:

U8 NUSE_Event_Group_Count(void);

Parameters:

None

Returns:

The number of configured event flag groups in the application

Nucleus SE Implementation of Event Flag Group Count

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

Data Structures

Event flag groups utilize one or two data structures – both in RAM – which, like other Nucleus SE objects, are tables, included and dimensioned according to the number of groups 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.

RAM Data

These data structures are:

NUSE_Event_Group_Data[] – This is an array of type U8 , with one entry for each configured event flag group and is where the event flag data is stored.

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

These data structures are all initialized to zeros by NUSE_Init_Event_Group() when Nucleus SE starts up. 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:

RAM U8 NUSE_Event_Group_Data[NUSE_EVENT_GROUP_NUMBER]; #if NUSE_BLOCKING_ENABLE     RAM U8 NUSE_Event_Group_Blocking_Count[NUSE_EVENT_GROUP_NUMBER]; #endif

ROM Data

There are no ROM data structures associated with event flag groups.

Event Flag Group Data Footprint

Like all kernel objects in Nucleus SE, the amount of data memory required for event flag groups is readily predictable.

The ROM data footprint for all the event flag groups in an application is 0.

The RAM data footprint (in bytes) for all the event flag groups in an application, when blocking API calls is enabled, is simply: NUSE_EVENT_GROUP_NUMBER * 2 .

Otherwise it is just NUSE_EVENT_GROUP_NUMBER .

Unimplemented API Calls

Three event flag group API calls found in Nucleus RTOS are not implemented in Nucleus SE:

Create Event Flag Group

This API call creates an event flag group. It is not needed with Nucleus SE, as event flag groups are created statically.

Service call prototype:

STATUS NU_Create_Event_Group(NU_EVENT_GROUP *group, CHAR *name);

Parameters:

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

name – pointers to a 7-character, null-terminated name for the event flag group

Returns:

NU_SUCCESS – indicates successful completion of the service

NU_INVALID_GROUP – indicates the event flag group control block pointer is NULL or already in use

Delete Event Flag Group

This API call deletes a previously created event flag group. It is not needed with Nucleus SE, as event flag groups are created statically and cannot be deleted.

Service call prototype:

STATUS NU_Delete_Event_Group(NU_EVENT_GROUP *group);

Parameters:

group – pointer to partition event flag group control block

Returns:

NU_SUCCESS – indicates successful completion of the service

NU_INVALID_GROUP – indicates the event flag group pointer is invalid

Event Flag Group Pointers

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

Service call prototype:

UNSIGNED NU_Event_Group_Pointers(NU_EVENT_GROUP *pointer_list,
UNSIGNED maximum_pointers);

Parameters:

pointer_list – pointer to an array of NU_EVENT_GROUP pointers; this array will be filled with pointers to established event flag groups in the system

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

Returns:

The number of NU_EVENT_GROUP 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. Event flag groups 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 event flag group. 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_EVENT_GROUP as being equivalent to U8 ; a variable – not a pointer – of this type then serves as the event flag group 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 upon in any way.

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

Number of Flags in a Group

In Nucleus RTOS, an event flag groups contain 32 flags; in Nucleus SE I reduced this to eight, as this is likely to be sufficient for simpler applications and saves RAM. Nucleus SE could be modified quite readily, if larger event flag groups were required.

Consume Flags Option

In Nucleus RTOS, there is an option to clear (consume) event flags when they are retrieved. I chose to omit this from Nucleus SE for simplicity, as the actual consume (deletion) of flags takes place when all the blocked tasks have received their retrieved flags; this would have been difficult to implement. The retrieving task can always clear the event flags by means of a further API call, if required.

Unimplemented API Calls

Nucleus RTOS supports seven service calls to work with event flag groups. 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 semaphores.


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.