The following are the primary objectives of this exercise:
The exercises are based on Xenomai 3 using the Alchemy API.
int rt_task_create (RT_TASK *task, const char *name, int stack_size, int priority, int mode)
int rt_task_start (RT_TASK *task, void(*)(void *arg) entry, void *arg)
The following "ex01a.c" C code illustrates the creating and start of a
"demo" task which writes a message.
Note that in "main" the character array "str" is used for the name of the task.
This array must be long enough to store the string used in sprintf plus an additional null character.
#include <stdio.h> #include <signal.h> #include <unistd.h> #include <alchemy/task.h> RT_TASK hello_task; // function to be executed by task void helloWorld(void *arg) { RT_TASK_INFO curtaskinfo; printf("Hello World!\n"); // inquire current task rt_task_inquire(NULL,&curtaskinfo); // print task name printf("Task name : %s \n", curtaskinfo.name); } int main(int argc, char* argv[]) { char str[10]; printf("start task\n"); sprintf(str,"hello"); /* Create task * Arguments: &task, * name, * stack size (0=default), * priority, * mode (FPU, start suspended, ...) */ rt_task_create(&hello_task, str, 0, 50, 0); /* Start task * Arguments: &task, * task function, * function argument */ rt_task_start(&hello_task, &helloWorld, 0); }
To compile the program ex01.c we use the following Makefile
XENO_CONFIG := /usr/xenomai/bin/xeno-config CFLAGS := $(shell $(XENO_CONFIG) --posix --alchemy --cflags) LDFLAGS := $(shell $(XENO_CONFIG) --posix --alchemy --ldflags) CC := gcc EXECUTABLE := ex01a all: $(EXECUTABLE) %: %.c $(CC) -o $@ $< $(CFLAGS) $(LDFLAGS) clean: rm -f $(EXECUTABLE)
Then the command
> make
will build the executable ex01a which can be executed using
> ./ex01a
printf
is mapped to rt_printf
which puts text to be printed in a buffer.
The actual printing is done by a non-real-time periodic thread.
Xenomai uses the standard errors defined in the headers:
The Xenomai API specifies for each function is specified which specific errors are generated when an error happens. However the more general errors like passing the wrong value to a function are not specified by the API. Hence, it is possible to obtain an error code not specified in the API documentation.
The strerror
function provides a convenient way to stop a program and print the error. The
following example demonstrates this
#include <errno.h> ...
/* send message */
retval = rt_task_send(&task_struct[1], &task_mcb , NULL, TM_INFINITE);
if (retval < 0 )
{
printf("Sending error %d : %s\n",-retval,strerror(-retval));
} else {
printf("taskOne sent message to taskTwo\n");
}
Compile and run program ex01a.c as described above, using the files ex01a.c and Makefile.
Copy file ex01a.c to ex01b.c and introduce an error by changing
rt_task_start(&hello_task, &helloWorld, 0);into
rt_task_start(NULL, &helloWorld, 0);
Add ex01b to the EXECUTABLE list in the Makefile by
EXECUTABLE := ex01a ex01bNext build and run this program; observe the result.
Next introduce a return value for the 'rt_task_start' call and print the error code as described above.
Rebuild and rerun the new version of the program, observe the different output.
Last Updated: 26 June 2019 (Jozef Hooman)
Created by: Harco Kuppens
h.kuppens@cs.ru.nl