Vimman's Sky https://bbs.21ic.com/?194686 [收藏] [复制] [RSS] 如何把一件简单的事情做得复杂起来呢?请您仔细阅读我的blog。

日志

FreeRTOS之初体验

已有 2456 次阅读2009-2-22 10:46 |系统分类:嵌入式系统| FreeRTOS, 消息队列

1.OS前传->从前后台到两个while(1){}切换:


        记得是2007年的五一长假,想学习ARM7,利用一周时间在UV3上模拟跑通了两个while(1){}切换;那时候的想法很天真,每个前后台程序的主循环只要一个while(1){},加入有两个while(1){},能不能从这个while(1){}的随意一点切换至另一个while(1){}的中的某一点呢,或者两个while(1){}交替运行呢?从网上找了来一份uC/OS-II的任务切换的汇编代码来修改,那时候偶基本看不懂ARM7TDMI的汇编,经过一周的摸索,终于成功完成了两个while(1){}的时间片轮换,明白了OS的最基本概念->任务切换。看到虚拟串口print出来的"Task1 is running!","Task2 is running!",不禁想难道这就是传说中的OS。


2.FreeRTOS之初体验:


         现在总算明白了,任务切换本身并不难,难的是什么时候进行任务切换。


         在后来的项目中,偶把两个while(1){}切换的机制引入进来,其实并没有改变前后台系统的本质。比如定时器中断服务程序和主程序不就是两个while(1){}在切换吗?


         一个偶然机会,认识了FreeRTOS,并且下载了5.0.0版本的源代码。


        由于没有针对RealView编译器的Port,自己进行了修改,然后RealView对C内嵌汇编比较苛刻(可以参考编译器文档),仿照其他的Port来修改很费劲。虽然最后能运行了,但是发现对PortEXIT_SWITCHING_ISR宏的处理不能实现。后来找到了5.1.1版本,里面终于有了针对RVDS的Port,将其拿到5.0.0版本中几乎不用怎么修改就可以用。


        现在系统已经在LPC2138目标板上跑起来了,该板有RTC,KeyBoard,5.7寸单色LCD,两路24位ADC模拟量输入,打印机,FlashMemory存储。启动了三个Task,TimerTask,MainTask,PrintTask,按优先级从高到低排列。


        TimerTask调用API vTaskDelayUntil实现精确的cycle级延时。键盘扫描,ADC转换结果的读取等都放在了这个里面执行。当键盘值或ADC值取得后通过消息队列通知MainTask。为了时间按秒更新,同时还向MainTask发送1s定时消息。


       MainTask通过调用API xQueueReceive每隔一定时间检查消息队列是否接收到消息,处理消息并更新LCD界面。当接收到打印键按下时,MainTask会给PrintTask发送消息。PrintTask也调用xQueueReceive每隔一定时间检查它的消息队列。最初,偶准备把MainTask和PrintTask合并,但考虑掉打印过程是一个比较慢的过程,打印过程中可能会影响LCD的显示,因此决定把PrintTask独立成一个单独的任务。起初,对于xQueueReceive( xQueue, pvBuffer, xTicksToWait )的第三个参数不太明白,后来才知道为了延时一定Ticks再检查。最开始我向xTicksToWait 传递的值为0,这样由于PrintTask优先级低时钟得不到运行。把PrintTask和MainTask改成同一优先级,就可以打印了,证明FreeRTOS把相同优先级的任务做time slicing调度。后来明白了xTicksToWait 的意义,就又把PrintTask恢复为低优先级,将MainTask的xQueueReceive设置成每隔一定时间检查消息队列。这样PrintTask便有了控制CPU的可能。


看到系统稳定运行了几个小时后,才发现有了OS就是爽。否则打印这样的事务怎么处理才好呢?


一点小小的感受,希望大家赐教啊^_^


路过

鸡蛋

鲜花

握手

雷人

发表评论 评论 (1 个评论)

回复 Cheney 2009-2-23 05:13
王博,写得不错,看到你就等于看到了中国教育未来的曙光.