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實時執行緒通訊方案 rt_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
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