NetBurner 3.3
Preemptive Tasks

Preemptive Operation, Priorities and Blocking

In a preemptive operating system the highest priority task ready to run will always run. This is an extremely important point, so we will mention it again: the highest priority task ready to run will always run. This is different than a Windows or Unix system that employs a round-robin in which each task will run based on its time slice. If you create a high priority task that can always run and never blocks, then no lower priority tasks will ever run. Lower priority tasks can only run when a higher priority task blocks on a resource or blocking function call.

For example, there are two tasks A and B. Task A has priority 50 and Task B has priority 51. Since Task A is of higher priority, it will always run (and Task B will never run) unless it calls a blocking function. Task B will then run for as long as Task A blocks; this could be 1 second due to a call to OSTimeDly(TICKS_PER_SECOND), until a shared resource is available due to a call to OSSemPend(), or until data is available from a network connection due to a select() or read(). It both tasks are in a blocking state, then the RTOS idle task will run.

RTOS Blocking Functions

Generally any function that pends on a resource or creates a time delay:

I/O Functions That Can Block

Generally any function that does a read operation or pends on a file descriptor

  • select()
  • read(), including variants with timeouts
  • write(), blocks until at least one char can be written
  • gets()
  • getchar()
  • fgets()

Network Functions That Can Block

Generally calls that will pend on an incoming connection or received data

  • accept()
  • Creation of a UDPPacket packet object when initialized to receive data

Functions That Can Enable a Task To Be "Ready To Run"

Generally functions that post to pending objects

System Task Priorities

The number and type of system tasks and priorities priorities used by the system will depend on your platform and the system features used by your application. For example, if your application calls StartHTTP( ) to enable web services, then a system task will be created that handles web server requests. The system task priority levels are defined in \nburn\nbrtos\include\constants.h.

Task Creation

Whether you use the Application Wizard in NBEclipse to create a new application, or start with one of the example programs, you will notice that the point at which your application takes control is a function named UserMain(). UserMain() is a task created by the system. The first few lines will consist of system initialization functions such as init() and StartHttp().

Additional tasks are created with the OSTaskCreatewName() or OSSimpleTaskCreatewName() functions. The following is an example program that demonstrates the use of each function. When using OSTaskCreaewName() you specify all parameters:

  • Task function name
  • Optional parameter to pass to the task, NULL if not used
  • Top of the task stack
  • Bottom of the task stack
  • Task priority
  • Task name

A significant benefit of the full function call is that it returns the status of the task creation process. For example, one possible error is that you cannot create a second task at the same priority as any other task.

The 'OSSimpleTaskCreatewName()' implementation lets you specify just the task function, priority, and name.

/*
* This example demonstrates how to use two of the task creation
* functions:
* - OSSimpleTaskCreatewName()
* - OSTaskCreatewName()
*
*/
#include <init.h>
#include <stdlib.h>
#include <nbrtos.h>
#include <system.h>
#include <utils.h>
const char *AppName = "OSTaskCreate Example";
// Allocate stack space
uint32_t TaskAllParamsStack[USER_TASK_STK_SIZE];
/*-----------------------------------------------------------------------------
* Task created with OSTaskCreatewName() using all function parameters.
* The void *pd parameter can be cast to any type of data you wish to send to
* the task, or NULL if not used.
*----------------------------------------------------------------------------*/
void TaskAllParams(void *pd)
{
uint32_t loopCount = 0;
uint32_t delayTime = (uint32_t)pd;
iprintf("TaskAllParams delay time set to: %ld seconds\r\n", delayTime);
while (1)
{
iprintf("TaskAllParams, %ld\r\n", loopCount);
loopCount++;
OSTimeDly(TICKS_PER_SECOND * delayTime);
}
}
/*-----------------------------------------------------------------------------
* Task created with OSSimpleTaskCreatewName(). The primary difference from the
* full version is that it allocates the task stack for you.
*----------------------------------------------------------------------------*/
void TaskSimple(void *pd)
{
uint32_t loopCount = 0;
uint32_t delayTime = 6;
iprintf("TaskSimple delay time set to: %ld seconds\r\n", delayTime);
while (1)
{
iprintf("TaskSimple, %ld\r\n", loopCount);
loopCount++;
OSTimeDly(TICKS_PER_SECOND * delayTime);
}
}
/*-----------------------------------------------------------------------------
* UserMain
*----------------------------------------------------------------------------*/
void UserMain(void *pd)
{
uint32_t delayTime = 3;
int returnCode;
init(); // Initialize network stack
WaitForActiveNetwork(TICKS_PER_SECOND * 5); // Wait for DHCP address
iprintf("Creating TaskAllParams....");
returnCode = OSTaskCreatewName( TaskAllParams, // Task function name
(void *)delayTime, // Optional parameter to pass to the task function
&TaskAllParamsStack[USER_TASK_STK_SIZE], // Top of stack
TaskAllParamsStack, // Bottom of stack
MAIN_PRIO - 1, // Task priority
"TaskAllParams" ); // Task name
if (returnCode == OS_NO_ERR)
iprintf("Task creation successful\r\n");
else
iprintf("*** Error: status = %d\r\n", returnCode);
iprintf("Creating TaskSimple\r\n");
OSSimpleTaskCreatewName(TaskSimple, MAIN_PRIO - 2, "TaskSimple");
while (1)
{
OSTimeDly(TICKS_PER_SECOND * 1);
}
}

OSSimpleTaskCreatewName
#define OSSimpleTaskCreatewName(x, p, n)
This macro functions the same as OSTaskCreatewName().
Definition: nbrtos.h:1346
init.h
NetBurner System Initialization Header File.
OSTimeDly
void OSTimeDly(uint32_t to_count)
Delay the task until the specified value of the system timer ticks. The number of system ticks per se...
Definition: nbrtos.h:1368
system.h
NetBurner System Functions.
OSTaskCreatewName
uint8_t OSTaskCreatewName(void(*task)(void *dptr), void *data, void *pstktop, void *pstkbot, uint8_t prio, const char *name)
This function creates a new task.
WaitForActiveNetwork
bool WaitForActiveNetwork(uint32_t ticks_to_wait=120 *TICKS_PER_SECOND, int interface=-1)
Wait for an active network connection on at least one interface.
Definition: dhcpc.cpp:1550
OS_NO_ERR
#define OS_NO_ERR
No Error.
Definition: nbrtos.h:58
nbrtos.h
NetBurner Real-Time Operating System API.
init
void init()
System initialization. Normally called at the beginning of all applications.
Definition: init.cpp:29
AppName
const char * AppName
Definition: defappname.cpp:5