一、Xenomai API 接口使用总结
-
Alarm-操作: 在使用实时任务过程中,采用看门狗定时器进行延时操作时,会产生实时域到非实时域的上下文切换操作,从而导致实时线程实时性受到影响,具体如下:
void RT_TASK_CallBack_Handle(void *pUsrArg) { int err; T_RT_PARAM *rt_param = (T_RT_PARAM *)pUsrArg; rt_printf("## Running=[%d,%d] ##:%s-%d\n", rt_param->Param1, rt_param->Param2, __FUNCTION__, __LINE__); while(1) { err = rt_alarm_wait(&rt_param->alarm_desc); // rt_printf("Hello Xenomai World!\n"); } }
通过xenomai程序状态文件查看 MSW 参数的情况,发现其一直在增加:
cat sched/stat
root@MM5718v1:/proc/xenomai# cat sched/stat CPU PID MSW CSW XSC PF STAT %CPU NAME 0 0 0 15690 0 0 00018000 99.8 [ROOT/0] 0 2869 14 17 77 0 000680c0 0.0 RTDemoExe 0 2871 1 21 44 0 00040042 0.0 timer-internal 0 2872 20 40 47 0 00048042 0.0 TEST_TASK 0 0 0 69867498 0 0 00000000 0.2 [IRQ20: [timer]]
结论:不要在实时线程任务中启用Alarm函数进行延时处理,会存在上下文切换过程。
-
Cond-操作: 在使用
err = rt_cond_bind(&cond, "TEST_COND_VAR_NAME", TM_INFINITE);
函数去跨函数绑定条件变量的过程中,此函数必须在实时任务中去调用,否则调用不成功,且不会阻塞等待到该条件变量的创建。 程序按下s
即可触发执行rt_printf("&&& Hello KeyboardMonitor World!\n"); err = rt_cond_bind(&cond, "TEST_COND_VAR_NAME", TM_INFINITE); rt_printf("### Hello KeyboardMonitor World!\n");
上述代码块必须在实时线程中调用才会生效。bind的功能就像是socket编程中的bind功能,能够阻塞获取到指定名称的信号量对象,从而保证在当前实时线程中也能够获取到对应的信号量,从而完成实时线程控制。
clock_gettime(CLOCK_REALTIME, &time_stamp); time_stamp.tv_sec += 5; // 需要将cond等待时间向后设置5s作为终止时间 rt_printf("The Current TimeStamp=[%ld:%ld]\n", time_stamp.tv_sec, time_stamp.tv_nsec); err = rt_cond_wait_timed(&cond, &mutex_var, &time_stamp); // 设置了cond条件等待的时间节点,如果到达时间节点,条件为被设置则返回超时错误 -ETIMEDOUT if(0 != err) { rt_printf("Xenomai-CondVariable wait Error:[%d,%d,%d,%d,%d,%d,%d]!\n", err, -EINVAL, -EIDRM, -EINTR, -EWOULDBLOCK, -ETIMEDOUT, -EPERM); }
注意: 目前对于cond条件的
rt_cond_broadcast
以及rt_cond_signal
还未测试成功!
-
Queue-操作: Xenomai提供了一套IPC实时线程通信方案
graph TD; 实时线程Task1-->定义Task1-rt_queue队列-->阻塞绑定队列1rt_queue_bind-->定时获取队列数据rt_queue_receive_timed-->使用相关数据-->释放数据内存rt_queue_free 实时线程Task2-->定义Task2-rt_queue队列-->阻塞绑定队列2rt_queue_bind-->申请数据内存rt_queue_alloc-->更新内存数据内容-->发送队列数据rt_queue_send 主实时线程Task-->定义原始rt_queue队列-->创建相关队列rt_queue_create-->whilert_queue
, 能够采用 bind 的方式在不同的实时线程中通过queue的名称获取指定的队列句柄,从而进行数据交换的操作,其基本使用流程如下:相关测试代码如下(编译程序,输入i键即可):
void RT_TASK_Queue_CallBack_Handle(void *pUsrArg) { int err; int counter = 0; int SamplePeriod = 200000000; T_RT_PARAM *rt_param = (T_RT_PARAM *)pUsrArg; rt_printf("## Running=[%d,%d] ##:%s-%d\n", rt_param->Param1, rt_param->Param2, __FUNCTION__, __LINE__); RT_QUEUE rt_queue; RT_QUEUE_INFO rt_queue_info; rt_printf("&&& Hello KeyboardMonitor World!\n"); err = rt_queue_bind(&rt_queue, "RT_QUEUE_DEMO", TM_INFINITE); rt_printf("### Hello KeyboardMonitor World!\n"); err = rt_queue_inquire(&rt_queue, &rt_queue_info); rt_printf("The KeyBoard RT-Queue[%s]:\n", rt_queue_info.name); rt_printf(" Number of task currently waiting on the queue for messages:[%d]\n", rt_queue_info.nwaiters); rt_printf(" Number of messages pending in queue:[%d]\n", rt_queue_info.nmessages); rt_printf(" Queue Mode Bits:[%d]\n", rt_queue_info.mode); rt_printf(" Maximum number of messages in queue:[%d]\n", rt_queue_info.qlimit); rt_printf(" Size of memory pool for holding message buffers:[%d]\n", rt_queue_info.poolsize); rt_printf(" Amount of memory consumed from the buffer pool:[%d]\n", rt_queue_info.usedmem); struct timespec time_stamp; void *buf_addr = NULL; ssize_t buf_size; rt_task_set_periodic(NULL, TM_NOW, SamplePeriod); // 200ms更新一次 while(1) { rt_task_wait_period(NULL); rt_printf("Hello Xenomai-CondVariable World[%d]!\n", counter); clock_gettime(CLOCK_REALTIME, &time_stamp); time_stamp.tv_nsec += 100000; // rt_printf("The Current TimeStamp=[%ld:%ld]\n", time_stamp.tv_sec, time_stamp.tv_nsec); buf_size = rt_queue_receive_timed(&rt_queue, &buf_addr, &time_stamp); if(buf_size > 0) { rt_printf("Show the Buffer Content:"); for(int i=0 ; i < buf_size ; i++) { rt_printf(" %d", ((char *)buf_addr)[i]); } rt_printf("\n"); } rt_queue_free(&rt_queue, buf_addr); } err = rt_queue_unbind(&rt_queue); }
-
HEAP-操作: 在使用Xenomai预先申请的内存池内容时,Xenomai提供了 heap 相关的操作API,在创建heap过程中,如果配置heap模式为
H_SINGLE
则在rt_heap_alloc
函数调用时,需要将所有内存全部申请完,否则程序报错。同时 Heap 内存操作还提供了rt_heap_bind
的绑定功能,从而能够方便 RT-Task 之间进行 IPC 内存共享通讯。具体参考程序:MainRTHeap.c
标签:rt,RT,TASK,err,task,printf,Xenomai From: https://www.cnblogs.com/uestc-mm/p/17246221.htmlroot@MM5718v1:~/Burnish# ./RTDemoExe Heap Informations: Number of tasks waitting for aviliable memory alloc:0 The Heap Mode Flags given while Creation:0 Size of the Heap(Bytes) While Create:10 Bytes Maximum amount of memory avaliable from heap:1032 Bytes Amount of memory currently consumed:3250 Bytes Name of memory heap:HeapTest The iPointer[0]= 0 1 2 3 4 5 6 7 8 9