Chris O'Byrne - YAVRTOS

Using semaphores

Semaphores are used to send signals between tasks, or between tasks and ISRs.

Example 1 - signalling between tasks

semaphore_t sema;

void semaphore_receiving_task(void *p) {
        while (1) {
                wait_for_increment_of(&sema, 1);
                do_stuff();
        }
}

void semaphore_writing_task(void *p) {
        while (1) {
                wait_for_conditions_to_be_right();
                increment_semaphore_by(&sema, 1); // This makes the "wait_for_increment_of()" function in the receiving task return
        }
}
In the above example, if the semaphore_receiving_task is of higher priority than the semaphore_writing_task, then as soon as the increment_semaphore_by() call is made, the semaphore_receiving_task will start executing.

Example 2 - signalling tasks from an ISR

The classic use of semaphores is to provide tasks with an easy means of implementing a delay. This is done by having a semaphore increment during the tick - then tasks can use that semaphore's value to suspend themselves for a known period of time.
semaphore_t tick;

// This is a function that runs every tick - we use it to increment the tick semaphore value by one
uint8_t tick_interrupt() {
        increment_semaphore_by(&tick, 1);
        return 1;
}

// e.g. the TIMER1_COMPA interrupt is our tick interrupt
TASK_ISR(TIMER1_COMPA_vect, tick_interrupt())

// This task needs to periodically delay by 100 ticks
void periodical_task(void *p) {
        while (1) {
                ...
                wait_for_increment_of(&tick, 100); // This function call won't return until 100 ticks have elapsed
                ...
        }
}

YAVRTOS and YAVRTOS documentation Copyright © 2007-2008 Chris O'Byrne. Email - chris <at> obyrne <dot> com