首页 > 系统相关 >Xenomai 再探

Xenomai 再探

时间:2023-03-23 09:23:47浏览次数:48  
标签:rt RT TASK err task printf Xenomai

一、Xenomai API 接口使用总结

  1. 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函数进行延时处理,会存在上下文切换过程。


  2. 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 还未测试成功!


  3. Queue-操作: Xenomai提供了一套IPC实时线程通信方案 rt_queue , 能够采用 bind 的方式在不同的实时线程中通过queue的名称获取指定的队列句柄,从而进行数据交换的操作,其基本使用流程如下:

    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-->while

    相关测试代码如下(编译程序,输入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);
    }
    

  4. HEAP-操作: 在使用Xenomai预先申请的内存池内容时,Xenomai提供了 heap 相关的操作API,在创建heap过程中,如果配置heap模式为 H_SINGLE 则在 rt_heap_alloc 函数调用时,需要将所有内存全部申请完,否则程序报错。同时 Heap 内存操作还提供了 rt_heap_bind 的绑定功能,从而能够方便 RT-Task 之间进行 IPC 内存共享通讯。具体参考程序:MainRTHeap.c

    root@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 
    

    标签:rt,RT,TASK,err,task,printf,Xenomai
    From: https://www.cnblogs.com/uestc-mm/p/17246221.html

相关文章

  • xenomai初探
    Xenomai定义一个realtime的系统需要保证其工作在给定的时间限制之内完成。系统不需要以最快的速度完成任务,但是需要在指定的定时时间范围内完成。在这个前提条件下,realt......
  • 【原创】xenomai UDD介绍与UDD用户态驱动示例
    目录xenomaiUDD与用户态驱动示例一、UDD介绍二、UDD原理及框架1.内存映射2.中断处理UDD与UIO的区别3.linuxUIO与xenomaiUDD框架对比3.1UIO机制3.2UDD机制三、UDD应......