Xenomai: API service tags https://xenomai.org/documentation/xenomai-3/html/xeno3prm/api-tags.html
驱动简介
Xenomai 3 的rtdm驱动更像一般的Linux驱动,named device会在/dev/rtdm/xxx创建一个设备文件。而用户空间使用时,写得来也和Linux的一般char设备相似,open/close/read/write/ioctl,只不过实际上在link的时候这些函数都被做了手脚,替换成了libcobalt.so中的函数(参见 /usr/xenomai/lib/cobalt.wrappers)。这样就导致在使用rtdm驱动时无须 xeno-config --skin=rtdm --cflags / --ldflags,而是用api对应的配置即可,例如如果用posix api,则应使用 xeno-config --posix --cflags / --ldflags
自动初始化
默认link时会自动加上 /usr/xenomai/lib/xenomai/bootstrap.o,并配合上相应的ldflags,直接把用户的main函数替换为xenomai_main,读取相关的命令行参数,同时调用xenomai_init初始化xenomai各个模块。如果一个动态库使用了rtdm,那么 xeno-config --rtdm --ldflags也会默认带上 bootstrap.o,最后link的时钟会导致 xenomai_main重复定义无法编译过,即使编译过也会导致assert错误或者xenomai_init被多次调用,所以库使用的ldflags应该在生成时加上–no-auto-init,即 xeno-config --rtdm --ldflags --no-auto-init
nrt和rt的函数调用
rtdm驱动中有一些函数有两个版本,例如 ioctl_nrt和ioctl_rt,在Xenomai 2时会根据当前是primary还是secondary来调用rt或nrt,但是Xenomai 3不是这样了,如果有rt版本,那么会先切到primary去调用rt的版本,如果rt返回-ENOSYS(也可不实现ioctl_rt),就会切到secondary再调用nrt的版本。这个在 https://xenomai.org/migrating-from-xenomai-2-x-to-3-x/#Adaptive_syscalls 讲了,如果不注意这一项,在primary时调用了其他linux内核函数,可能导致系统死机(不响应)
mmap
和普通的Linux驱动一样,也支持mmap系统调用了。rtdm驱动只要实现ops->mmap即可,这个函数实现也比较简单,根据内存的性质调用 rtdm_mmap_vmem/rtdm_mmap_kmem/rtdm_mmap_iomem等函数即可。
RTDM
实时驱动程序模型(RTDM)为实时设备驱动程序的用户和开发人员提供了一个统一的接口
Cobalt
Cobalt在双内核配置中补充了本机Linux内核
Alchemy API
传统 RTOS APIs的编程接口
参考http://www.cs.ru.nl/J.Hooman/DES/XenomaiExercises/Exercise-1.html
利用task management services
1创建一项实时任务
int rt_task_create (RT_TASK *task, const char *name, int stack_size, int priority, int mode)
2启动实时任务
int rt_task_start (RT_TASK *task, void(*)(void *arg) entry, void *arg)
hello world例程
#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);
}
注意
Note that by adding the “posix” flag in the Makefile, 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.
编译实时项目
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)
命令行编译
make
执行
./ex01a
nice website
http://www.cs.ru.nl/J.Hooman/DES/XenomaiExercises/