Task Management

The core of Nano-RK is a Real-Time scheduler that supports preemptive scheduling, task synchronization and deadlock prevention. This guarantees that even under worst case conditions tasks will meet deadlines. We now discuss the details of the scheduler’s ability to enforce timeliness guarantees as well as predicable lifetime.

Nano-RK saves energy by ensuring that tasks never poll for a resource. Instead, tasks block on certain events (such as being woken up at a certain point of time or on the arrival of a network packet) and can be unblocked when the events occur. If there are no tasks eligible to run, the system can be powered down.

Nano-RK uses priority-based preemptive scheduling and while we provide explicit support for periodic tasks, we also support aperiodic and sporadic tasks in our framework. The highest priority task that is eligible to run in the system is always scheduled by the operating system. A periodic task can suspend itself before its CPU reserve has
expired and wait until its next scheduled period. This adds slack to the system that can be used by soft real-time tasks.

Task synchronization is important in any system with multiple tasks that access a shared resource. In order to bound the blocking time encountered by a higher priority task, we implement priority ceiling protocol (PCP) emulation (Highest Locker Priority). This prevents the phenomenon of priority inversion wherein a shared resource needed by the high-priority process is currently being used by a lower-priority process. In Nano-RK, each mutex is associated with a priority ceiling value. When a mutex is acquired, the priority of the task is elevated to the priority ceiling of the mutex. Once the mutex is released, the priority of the task reverts to its original level. PCP allows offline schedulability analysis to bound the priority inversion problem.

 1#include <nrk.h>
 2#include <include.h>
 3#include <ulib.h>
 4#include <stdio.h>
 6int main ()
 8   nrk_setup_ports();
 9   nrk_setup_uart(UART_BAUDRATE_115K2); 
10   printf( "Starting up...\r\n" );
11   nrk_init();
12   nrk_time_set(0,0);
13   nrk_create_taskset();  // User defined function application task config
14   nrk_start();
15   return 0;

Typical startup code required to setup and begin Nano-RK.


void nrk_setup_ports( void )

Parameters: none.
Return Values: none

This function configures the cpu specific ports based on the current platform. For
instance, it may configure UART0 or UART1 as the primary serial output based on
which hardware you have selected in the makefile.


void nrk_init( void )

Parameters: none.
Return Values: none

This should be called before nrk_start() and before any user tasks are defined. This
function configures the kernel stack, resources, the idle task and default TCB parameters.


void nrk_start( void )

Parameters: none.
Return Values: none

Call this function once user tasks have been defined to start Nano-RK. This function
schedules the first high priority task and begins execution of the OS. This function will
never return and any state currently associated with the kernel stack thus far will be


nrk_status_t nrk_activate_task( nrk_task_type * )

Parameters: nrk_task_type * task pointer
Return Values: nrk_status_t NRK_OK upon success and NRK_ERROR on failure

This function makes a user defined task runnable upon calling nrk_start. It operates on the nrk_task_type structure defined below.

 1typedef struct task_type {
 2   void *Ptos;             // Top of stack pointer
 3   void *Pbos;             // Bottom of stack pointer
 4   void (*task)();         // Function pointer to task entry point
 5   uint8_t prio;           // Task priority, higher value has greater priority
 6   uint8_t Type;           // Type of task
 7   uint8_t [[SchType]];        // Type of scheduling
 8   nrk_time_t period;      // Period of Task
 9   nrk_time_t cpu_reserve; // CPU Reserve of task
10   nrk_time_t offset;      // Starting offset phase
11} nrk_task_type;

Task parameters set by a user to define a task.
Related links: nrk_time_t

 2nrk_task_type TaskOne;
 4void Task1(void);
 6void nrk_create_taskset()
 8   nrk_task_set_entry_function( &TaskOne, Task1);
 9   nrk_task_set_stk( &TaskOne, Stack1, NRK_APP_STACK_SIZE);
10   TaskOne.prio = 2;
11   TaskOne.FirstActivation = TRUE;
12   TaskOne.Type = BASIC_TASK;
13   TaskOne.SchType = PREEMPTIVE;
14   TaskOne.period.secs = 0;
15   TaskOne.period.nano_secs = 200*NANOS_PER_MS;
16   TaskOne.cpu_reserve.secs = 0;
17   TaskOne.cpu_reserve.nano_secs = 50*NANOS_PER_MS;
18   TaskOne.offset.secs = 0;
19   TaskOne.offset.nano_secs= 0;
20   nrk_activate_task (&TaskOne);

Example of how a user would create a task that executes every 200ms with
a 50ms reserve. Notice the task entry point and the task’s stack are passed
as functions to the task structure.


nrk_status_t nrk_terminate_task()

| Parameters: | none | | Return Values: | nrk_status_t NRK_OK upon success and NRK_ERROR on failure |
This can be called by a task to terminate itself. After being called, the task will no
longer be scheduled.


uint8_t nrk_get_pid()

Parameters: none
Return Values: uint8_t containing the current task PID

This functions returns the task ID to the currently running task. The task is given a
unique ID before it is executed once nrk_start() is called. Returns the current task


uint8_t nrk_wait_until_next_period()

Parameters: none
Return Values: NRK_ERROR or NRK_OK

This function suspends a task until the start of its next period. When the task is suspended,
other tasks can execute. If the system has no more tasks to execute, it will
automatically enter a power-down state to save energy. Returns 1 upon success and 0
upon failure.


uint8_t nrk_halt()

Parameters: none
Return Values: none

This functions halts the OS forever. If NRK_WATCHDOG is enabled and there is no HALT_ON_ERROR defined in nrk_cfg.h, then nrk_halt() will reboot the node by allowing the watchdog timer to expire.

Prev: Contents Next: Static Configuration Top