Version 1/45 - Next ยป - Current version
Anthony Rowe, 03/03/2007 11:08 am


= Signals And Semaphores =

A signal is a message that a task can use to wakeup one or more tasks waiting on an
event or events. When waiting on an event, a task is suspended and does not consume
CPU time. Nano-RK supports 31 unique signals. It is possible to wait on multiple
signals such that any one of them can wake a task from sleep. All signals must be
statically defined as integers between 1 and 31 in the nrk_cfg.h file.
A semaphore is a protected variable and constitutes the classic method for restricting
access to shared resources (e.g. storage,actuators etc) in a multiprogramming environment.
Signals are used to allow one task to wakeup another task (or tasks) that
are suspended on an event. Nano-RK implements semaphores and signals such that
tasks that are suspended on an event or waiting for access to a semaphore will not be
scheduled until the corresponding signal is sent or semaphore becomes available.

{{{
// Resource count must be at least 1
#define NRK_MAX_RESOURCE_CNT 1
// Define ALL signals below
#define RTL_RX_PKT_EVENT (NRK_MAX_RESOURCE_CNT+1)
#define RTL_TX_PKT_EVENT (NRK_MAX_RESOURCE_CNT+2)
#define NRK_UART_RX_EVENT (NRK_MAX_RESOURCE_CNT+3)
#define MY_APP_EVENT (NRK_MAX_RESOURCE_CNT+4)
}}}
Example of defined events in nrk_cfg.h file.

'''uint8_t nrk_get_resource_id(uint8_t *resrc)'''
Get the resource id_number of the specified resource pointer.

'''int32_t nrk_event_signal(uint8_t event_num)'''
This function is used to signal tasks that are waiting on events using nrk_event_wait().
See example below.

{{{
// This will send out the MY_APP_EVENT signal defined in nrk_cfg.h
// SIG is a helper macro to generate the bitmask version of the event ID
nrk_event_signal( SIG );
}}}

Signal a custom event.

'''uint32_t nrk_event_wait(uint8_t event_num)'''
This function will wait for a set events. nano-RK supports up to 31 signals. Each signal
represents a bit in a 32 bit number (bit 0 is reserved) so it is possible to logically
OR multiple signals together if you wish to wait on a combination of events. The 32
bit number returned by nrk_event_wait() corresponds to the signal that was returned.
When waiting on multiple signals, this should be used to determine which signal actually
triggered the wakeup. All signals should be defined in the nrk_cfg.h file for each
project.

{{{
uint32_t event_mask;
...
event_mask=nrk_event_wait( SIG| SIG | SIG);
// Once we wakeup, lets check which event triggered the wakeup
if(event_mask==SIG) nrk_kprintf(PSTR);
if(event_mask==SIG) nrk_kprintf(PSTR);
if(event_mask==SIG) nrk_kprintf(PSTR);

}}}

Example of waiting on UART data, an rtl packet or a custom application
event.

'''uint8_t * nrk_create_semph(uint8_t count,uint8_t highest_prio_task,uint8_t init_state)'''
This function creates a semaphore resource, with a priority ceiling for PCPE. It allows
you to specify number of entries allowed into the critical section and set a priority
ceiling on the critical section to allow the system to implement Priority Ceiling Protocol
Emulation. count sets the number of entities that are able to access the critical section
specified by the semaphore. task_hi_prio sets the ceiling value for the task; Note if
using PCPE this should be the highest priority task accessing the critical section.

{{{
NrkSemph * semph1;
NrkSemph * semph2;
uint8_t numMeat;
uint8_t numWater;
int main() {
numMeat=2;
numWater=4;
// task3 hihghest prio task entering critical section
semph1=nrk_create_semph(1,3);
// task2 highest prio task entering critical section
semph2=nrk_create_semph(1,2);
}
//Task of Priority 1
Task1() {
nrk_pend_semph(semph1);
numMeat--;
nrk_post_semph(semph1);
nrk_pend_semph(semph2);
Nano-RK 8 SIGNALS AND SEMAPHORES
numWater--;
nrk_post_semph(semph2);
}
// Task of Prioirty 2
Task2() {
nrk_pend_semph(semph1);
numMeat--;
nrk_post_semph(semph1);
}
// Task of Priority 3
Task3() {
nrk_pend_semph(semph1);
numMeat--;
nrk_post_semph(semph1);
nrk_pend_semph(semph2);
numWater--;
nrk_post_semph(semph2);
}
}}}

Example of how to use semaphores.

'''int8_t nrk_semph_post(uint8_t* rsrc)'''
Semaphore post simply takes the address of the created semaphore and posts the semaphore.
This should be called after exiting the critical section. This allows other tasks to access
the protected region.

'''int8_t nrk_semph_pend(uint8_t *rsrc )'''
Semaphore pend simply takes the address of the created semaphore and pends the
semaphore. Its intention is to protect critical sections of code. This will cause the task
to go to a suspended state if the semaphore count is violated by allowing access into
the critical section.

{{{
typedef uint8_t NrkSemph;
}}}

This is the type that should be used to define a semaphore. See code examples above.

[wiki:nrk-api Contents] [wiki:nrk-api-device-drivers Device Drivers]