FreeRTOS is a popular real-time operating system kernel for embedded devices, that has been ported to more than 35 microcontrollers. It is distributed under the GPL with an optional exception. The exception permits users' proprietary code to remain closed source while maintaining the kernel itself as open source, thereby facilitating the use of FreeRTOS in proprietary applications.
FreeRTOS is designed to be small and simple. The kernel itself consists of only three or four C files. To make the code readable, easy to port, and maintainable, it is written mostly in C, but there are a few assembly functions included where needed (mostly in architecture-specific scheduler routines).
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.
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.
#ifndef __SCHEDULER_H #define __SCHEDULER_H /** \addtogroup kernel \{ \addtogroup Scheduler \{ */ #include "opendefs.h" //=========================== define ========================================== typedef enum { TASKPRIO_NONE = 0x00, // tasks trigger by the stack rx TASKPRIO_STACK_LOWMAC = 0x01, TASKPRIO_STACK_HIGHMAC = 0x02, TASKPRIO_STACK_6TOP = 0x03, TASKPRIO_STACK_IP = 0x04, TASKPRIO_STACK_ROUTING = 0x05, TASKPRIO_STACK_TRANSPORT = 0x06, // tasks going up the stack - sendone and timers TASKPRIO_SENDDONE_TIMERS_MAC = 0x07, TASKPRIO_SENDDONE_TIMERS_6TOP = 0x08, TASKPRIO_SENDDONE_TIMERS_IP = 0x09, TASKPRIO_SENDDONE_TIMERS_ROUTING = 0x0a, TASKPRIO_SENDDONE_TIMERS_TRANSPORT = 0x0b, //app tasks - down the stack TASKPRIO_APP_HIGH = 0x0c, TASKPRIO_APP_MED = 0x0d, TASKPRIO_APP_LOW = 0x0e, TASKPRIO_MAX = 0x0f, } task_prio_t; #define TASK_LIST_DEPTH 10 //=========================== typedef ========================================= typedef void (*task_cbt)(void); typedef struct task_llist_t { task_cbt cb; task_prio_t prio; void* next; uint16_t counter; } taskList_item_t; //=========================== module variables ================================ typedef struct { taskList_item_t taskBuf[TASK_LIST_DEPTH]; taskList_item_t* task_list; uint8_t numTasksCur; uint8_t numTasksMax; } scheduler_vars_t; typedef struct { uint8_t numTasksCur; uint8_t numTasksMax; } scheduler_dbg_t; //=========================== prototypes ====================================== void scheduler_init(void); void scheduler_start(void); void scheduler_push_task(task_cbt task_cb, task_prio_t prio); /** \} \} */ #endif
The implementation is still simple, the main idea is to have 3 FreeRTOS tasks handling the operation of the OpenWSN protocol stack.
- 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)
- Send Done 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.
- App Task:
TODO (WIP)