Using the NicheStack TCP/IP Stack - Nios II Edition Tutorial

ID 683574
Date 10/04/2021
Public
Document Table of Contents

1.7.3. Creating Tasks that Use the NicheStack TCP/IP Stack Sockets Interface

You must use the function call TK_NEWTASK to create any tasks that use the NicheStack networking services. You must create tasks that do not use networking services with the MicroC/OS-II function OSTaskCreate().

The NicheStack Networking Stack uses the TK_NEWTASK (defined in osportco.c) function to launch MicroC/OS-II tasks that use the networking services. TK_NEWTASK accepts a single argument, struct inet_taskinfo * nettask (defined in osport.h), which specifies the task name, the MicroC/OS-II thread priority, and the stack size. You can locate these files in the <Nios II EDS install path>/components/altera_iniche/UCOSII/src/nios2 directory. The struct inet_taskinfo structure is defined as follows:

struct inet_taskinfo {
TK_OBJECT_PTR(tk_ptr);/* pointer to static task object */
char * name;/* name of task */
TK_ENTRY_PTR(entry); /* pointer to code that starts task*/
int priority; /* MicroC/OS-II priority of the task */
int stacksize;/* size (bytes) of task’s stack */
char* stackbase; /* base of task’s stack */
};

For every networking task you create in your application, you must declare a local struct inet_taskinfo structure with the elements defined. These elements are listed in the following bullets, along with a brief explanation of their function:

  • TK_OBJECT_PTR(tk_ptr)—A pointer to a static task object, defined for a given task by the TK_OBJECT macro. The NicheStack Networking Stack makes use of the tk_ptr element during the operation. After declaring the variable name through the TK_OBJECT and populating the TK_OBJECT_PTR(tk_ptr), you do not need to do anything more.
  • char * name—This element contains a character string that corresponds to the name of the task. You can set it with any character string you choose.
  • TK_ENTRY_PTR(entry)—This element corresponds to the entry point or defined function name of the task that you want to run.
  • int priority—The MicroC/OS-II priority level for the task.
  • int stacksize—The MicroC/OS-II stack size for the task.
  • char* stackbase—This element in the structure is used by the NicheStack software. You must not change the element in the structure.

In addition to declaring the struct inet_taskinfo structure, you must invoke two macro definitions: TK_OBJECT and TK_ENTRY. These macros have the following uses:

  • TK_OBJECT(name)—Creates the static task object named name, which is used by NicheStack during operation. The static task object is also set in TK_OBJECT_PTR(tk_ptr). A NicheStack naming convention for the name parameter is to set it to the string “to_”, followed by the declared name of the struct inet_taskinfo instance.
  • TK_ENTRY(name)—Used to create a declaration of the task’s entry point, or function name. The name parameter is identical to the function name you specified for the task that you want to create, which must have the form void name (void). The name parameter sets the TK_ENTRY_PTR(entry) macro.

To create your own application tasks that use the services offered by the NicheStack TCP/IP Stack, follow these steps:

  1. Invoke Task Macros—Include the TK_OBJECT and TK_ENTRY macros, with information about your task.
  2. Define Task Parameters—Define your task application by filling in a local inet_taskinfo structure in your code.
  3. Wait for Stack Initialization—Before launching your task, wait until the external variable iniche_net_ready is set to TRUE. This variable sets to FALSE at run time and changes to TRUE when the NicheStack TCP/IP Networking Stack is operational.
  4. Launch Task—Call TK_NEWTASK while passing in a pointer to the inet_taskinfo structure for your task.

Following is a code sample for creating your own application task:

// Declaration of SSSNiosIISimpleSocketServerTask
void SSSNiosIISimpleSocketServerTask(void){
// task specific code
}
// Creation of NicheStack networking task
TK_OBJECT(to_ssstask);
TK_ENTRY(SSSNiosIISimpleSocketServerTask);
struct inet_taskinfo ssstask = {
&to_ssstask,
"simple socket server",
SSSNiosIISimpleSocketServerTask,
TASK_PRIORITY,
APP_STACK_SIZE,
};
while (!iniche_net_ready)
TK_SLEEP(1);
/* Create the main simple socket server task. */
TK_NEWTASK(&ssstask);

Networking tasks can hand off large processing jobs that are independent of networking to other tasks. This task load segmentation has the advantage of increasing control over memory usage for task stacks, as well as greater control over prioritization of jobs.

Be careful not to over utilize job distribution among several tasks at the same time, for the following reasons:

  • Additional tasks require additional CPU execution time to do task context-switching.
  • Limited number of priorities. Each task must have its own unique priority in MicroC/OS-II, and you do not want to run out of task priorities.