Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

FreeRTOS provides methods for multiple threads or tasks, mutexes, semaphores and software timers. A tick-less mode is provided for low power applications. Thread priorities are supported. In addition there are several schemes of memory. 

OpenWSN Integration

In OpenWSN FreeRTOS has been encapsulate and hidden behind our very simple scheduler.h interface. In that way our code stays agnostic to the underlaying scheduler.

...

  • Rx Task: handles callbacks triggered by packets comming from the MAC layer and pushes them up. The usual case is when a packet is received at the Low MAC and this is pushed up the stack until it reaches the target layer (e.g ICMPv6). This task has the highest priority.
  • Send Done and timers Task: Once an ACK from a sent packet is received, this confirms the succes on the packet transmission and this information is pushed up the stack for those tasks waiting that notification. Note that this is similar than the previous case but however we prefer to separate in another tasks with lowest priority than that of receiving a packet. This task also handles OpenWSN timer callbacks such RPL DIO timer or 6top maintenance tasks.
  • App Task: This task is used to move packets down the stack. Basically applications or upper layers use it to send down the packet to the High MAC until it is inserted into the MAC layer queue. It has the lowest priority.

In OpenWSN, the MACROS DISABLE_INTERRUPTS and ENABLE_INTERRUPTS are used to protect critical sections. When using a RTOS, however, we do not want to disable the operation of the RTOS but instead we want some sort of mutual exclusion to disable task preemption. This is achieved by a global lock semaphore

 

Code Block
languagecpp
themeEclipse
#define INTERRUPT_DECLARATION()        (rtos_sched_v.xStackLock != NULL ? (rtos_sched_v.xStackLock=rtos_sched_v.xStackLock) : ( rtos_sched_v.xStackLock = xSemaphoreCreateMutex()))
#define DISABLE_INTERRUPTS()           xSemaphoreTakeFromISR( (rtos_sched_v.xStackLock), &globalPriorityTaskWoken )
#define ENABLE_INTERRUPTS()            xSemaphoreGiveFromISR( (rtos_sched_v.xStackLock),&globalPriorityTaskWoken )

 

The scheduler operation has been implemented as follows:

  • Each task looks into the callback list for those callbacks that fall in its priority range (see task_prio_t enum). If a callback for that particular priority is found then the freertos task executes it and subsequently block in its sempahore until is triggered again by the scheduler. This trigger happens when a new callback for a certain priority is pushed into the list.
Code Block
languagecpp
themeEclipse
void scheduler_push_task(task_cbt cb, task_prio_t prio) {
	BaseType_t xHigherPriorityTaskWoken;
	xHigherPriorityTaskWoken = pdFALSE;
	//=== step 1. insert the task into the task list
	scheduler_push_task_internal(cb, prio);
	debugpins_slot_toggle();
	//=== step 2. toggle the appropriate semaphore so the corresponding handler takes care of it
	if (prio < SCHEDULER_STACK_PRIO_BOUNDARY) {
		xSemaphoreGiveFromISR(rtos_sched_v.xRxSem, &xHigherPriorityTaskWoken);
	} else if (prio >= SCHEDULER_STACK_PRIO_BOUNDARY
			&& prio < SCHEDULER_SENDDONETIMER_PRIO_BOUNDARY) {
		xSemaphoreGiveFromISR(rtos_sched_v.xSendDoneSem,
				&xHigherPriorityTaskWoken);
	} else if (prio >= SCHEDULER_SENDDONETIMER_PRIO_BOUNDARY
			&& prio <= SCHEDULER_APP_PRIO_BOUNDARY //includes TASKPRIO_MAX
	) {
		xSemaphoreGiveFromISR(rtos_sched_v.xAppSem, &xHigherPriorityTaskWoken);
	} else {
		leds_error_blink();
		while (1)
			;
	}
	portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

As said the FreeRTOS tasks unlock when a callback is pushed and execute the task that it has been inserted.

 

Code Block
languagecpp
themeEclipse
/**
 \brief Handles application packets, brinding them down the stack until they are queued,
        ready for the lowwer MAC to consume.
 */
static void vAppTask(void* pvParameters) {
	taskList_item_t* pThisTask = NULL;
	xSemaphoreTake(rtos_sched_v.xAppSem, portMAX_DELAY); //take it for the first time so it blocks right after.
	while (1) {
		xSemaphoreTake(rtos_sched_v.xAppSem, portMAX_DELAY);
		debugpins_fsm_toggle();
		scheduler_find_next_task_and_execute( SCHEDULER_SENDDONETIMER_PRIO_BOUNDARY,
		                                      SCHEDULER_APP_PRIO_BOUNDARY, pThisTask);
	}
}

 

Developing applications with FreeRTOS

 

One interesting thing to do once a RTOS is supported is to have some application level tasks that handle the application activity without constraining the OpenWSN activity. This can be easily achived by letting the application to create a FreeRTOS task. 

TODO (WIP)