Advertisement

Signals

January 08, 2018

Colin Walls-January 08, 2018

In this RTOS Revealed, I am going to look at signals, which are the simplest method of inter-task communication supported by Nucleus SE. They provide a very low cost means of passing simple messages between tasks.

Using Signals

Signals are different from all the other types of kernel object in that they are not autonomous – signals are associated with tasks and have no independent existence. If signals are configured for an application, each task has a set of eight signal flags.

Any task can set the signals of another task. Only the owner task can read the signals. The read is destructive – i.e. the signals are cleared by the process of reading. No other task can read or clear a task’s signals.

There is a facility in Nucleus RTOS that enables a task to nominate a function that is run when another task sets one or more of its signal flags. This is somewhat analogous to an interrupt service routine. This capability is not supported in Nucleus SE; tasks need to interrogate their signal flags explicitly.

Configuring Signals

As with most aspects of Nucleus SE, the configuration of signals is primarily controlled by #define statements in nuse_config.h. The key setting is NUSE_SIGNAL_SUPPORT, which enables the facility (for all tasks in the application). There is no question of specifying the number of signals – there is simply a set of eight flags for each task in the application.

Setting this enable parameter is the “master enable” for signals. This causes a data structure to be defined and sized accordingly, of which more later in this article. It also activates the API enabling settings.

API Enables

Every API function (service call) in Nucleus SE has an enabling #define symbol in nuse_config.h. For signals, these are:

NUSE_SIGNALS_SEND
NUSE_SIGNALS_RECEIVE

By default, both of these are set to FALSE, thus disabling each service call and inhibiting the inclusion of any implementation code. To configure signals 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:

#define NUSE_SIGNAL_SUPPORT  FALSE   /* Enables support for signals */
#define NUSE_SIGNALS_SEND    FALSE   /* Service call enabler */
#define NUSE_SIGNALS_RECEIVE FALSE   /* Service call enabler */

A compile time error will result if a signals API function is enabled and the signals facility has not been enabled. 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. Of course, the enabling of the two API functions is somewhat redundant, as there would be no point in enabling signals support and not having these APIs available. The enables are included for compatibility with other Nucleus SE features.

Signals Service Calls

Nucleus RTOS supports four service calls that appertain to signals, that provide the following functionality:

  • Send signals to a specified task. Implemented by NUSE_Signals_Send() in Nucleus SE.

  • Receive signals. Implemented by NUSE_Signals_Receive() in Nucleus SE.

  • Register a signal handler. Not implemented in Nucleus SE.

  • Enable/disable (control) signals. Not implemented in Nucleus SE.

The implementation of each of these service calls is examined in detail.

Signals Send and Receive Services

The fundamental operations, that can be performed on a task’s set of signals, are sending data to it (which may be done by any task) and reading data from it (and thus clearing the data, which may only be done by the owner). Nucleus RTOS and Nucleus SE each provide two basic API calls for these operations, that will be discussed here.

Since signals flags are bits, they are best visualized as binary numbers. As standard C does not historically support a representation of binary constants (only octal and hexadecimal), the Nucleus SE distribution includes a useful header file – nuse_binary.h – which contains #define symbols of the form b01010101 for all 256 8-bit values. Here is an extract from the nuse_binary.h file:

#define b00000000 ((U8) 0x00)
#define b00000001 ((U8) 0x01)
#define b00000010 ((U8) 0x02)
#define b00000011 ((U8) 0x03)
#define b00000100 ((U8) 0x04)
#define b00000101 ((U8) 0x05)

Sending Signals

Any task may send signals to any other task in the application. Sending signals involves setting one or more of the signal flags. This is an OR operation that has no effect upon flags set previously.

Nucleus RTOS API Call for Sending Signals

Service call prototype:

STATUS NU_Send_Signals(NU_TASK *task, UNSIGNED signals);

Parameters:

task – pointer to control block of the task that owns the signal flags to be set

signals – the value of the signal flags to be set

Returns:

NU_SUCCESS – the call was completed successfully

NU_INVALID_TASK – the task pointer is invalid

Nucleus SE API Call for Sending Signals

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

Service call prototype:

STATUS NUSE_Signals_Send(NUSE_TASK task, U8 signals);

Parameters:

task – the index (ID) of the task that owns the signal flags to be set

signals – the value of the signal flags to be set

Returns:

NUSE_SUCCESS – the call was completed successfully

NUSE_INVALID_TASK – the task index is invalid

Nucleus SE Implementation of Sending Signals

Here is the complete code for the NUSE_Signals_Send() function:

STATUS NUSE_Signals_Send(NUSE_TASK task, U8 signals)
{
    #if NUSE_API_PARAMETER_CHECKING
        if (task >= NUSE_TASK_NUMBER)
        {
            return NUSE_INVALID_TASK;
        }
    #endif
    NUSE_CS_Enter();
    NUSE_Task_Signal_Flags[task] |= signals;
    NUSE_CS_Exit();
    return NUSE_SUCCESS;
}

The code is very simple. After any parameter checking, the signal values are ORed into the specified task’s signal flags. Task blocking is not relevant to signals.

Receiving Signals

A task may only read its own set of signal flags. The process of reading them is destructive; i.e. it also results in the flags being cleared.

Nucleus RTOS API Call for Receiving Signals

Service call prototype:

UNSIGNED NU_Receive_Signals(VOID);

Parameters: none

Returns: the signals flags value

Nucleus SE API Call for Receiving Signals

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

Service call prototype:

U8 NUSE_Signals_Receive(void);

Parameters: none

Returns: the signal flags value

Nucleus SE Implementation of Receiving Signals

Here is the complete code for the NUSE_Signals_Receive() function:

U8 NUSE_Signals_Receive(void)
{
    U8 signals;
    NUSE_CS_Enter();
    signals = NUSE_Task_Signal_Flags[NUSE_Task_Active];
    NUSE_Task_Signal_Flags[NUSE_Task_Active] = 0;
    NUSE_CS_Exit();
    return signals;
}

The code is very simple. The flags value is copied, the original value cleared and the copy returned by the API function. Task blocking is not relevant to signals.

Continue reading on page two >>

 

< Previous
Page 1 of 2
Next >

Loading comments...