原创:关于嵌入式操作系统的“反动言论”
本人最近在做ARM9,实现一个测试仪表的控制部分。外围包括一个实现数据采集和计算的DSP、液晶屏、一个键盘扫描电路、与PC通讯的串口、外中断等。到目前为止,都没有使用操作系统。当时的考虑是:UCOS比较简陋;LINUX太复杂,会影响进度;VXWORKS好是好,就是不知道到哪里去找,而且BSP也不是一件轻松的工作。另外,觉得根据这个产品的复杂性来说,没有操作系统也不是无法胜任。目前这项工作已告一段落。
现在需要锦上添花,支持以太网。就从网上找了一个移植的UCOS上的TCP/IP协议栈,想看看修改一下在没有OS的环境下是不是也可以跑,或者索性就用UCOS来支持。分析了这个协议栈(包括以太网驱动)的代码之后,笑了。因为按照嵌入式系统的一般看法,有网络接口,就应该使用操作系统;但是事情也不是绝对的。
协议栈本身可以没有任务。很多商用的协议栈(例如H.323)或GUI(例如FLNX),都可以在没有OS的情况下工作。在没有OS的情况下,你可以使用check型的接口而不是wait型的接口来访问。
协议栈中有一些定时器需要处理。也就是说,系统应该在定时到达时,调用指定的处理函数。我的系统中有一个5ms的内部定时器中断作为系统的主定时器(键盘扫描就是在这个中断里完成的)。可以以这个定时器中断为基础,实现一个多定时器的处理模块,或者干脆再找一个内部定时器(计算一下最近的一个定时会在多长时间之后发生?然后用这个时间来设置)。缺点:与理想定时器相比有延迟,延迟时间相当于你的单任务的主程序转一圈需要的时间。但是其实,大多数定时都不是那么严格的,慢一点也死不了人。
以太网的收发中断:以太网物理芯片会产生中断,需要中断服务程序。中断服务程序一般就是保存中断类型或设置一些标志。
以太网驱动需要一个任务来进行以太网帧的收发处理。该任务触发的条件是物理芯片发生中断,或者协议栈的发送请求。接收处理包括帧头的解析,以及进一步调用IP/ARP、TCP/UDP处理等。发送处理就是成帧和向物理芯片传送数据了。
如果你的处理器速度太快(有点搞笑),而以太网芯片的处理速度相对缓慢,有可能发生需要发送但被阻塞的情况;当然更多的是物理芯片收到的数据需要及时处理。这时候需要队列和信号量之类的机制的来调节。在协议栈和以太网驱动之间有两个队列,分别存放需要发送和接收到需要处理的数据包。
在没有OS(也就是单任务了)的情况下,发送处理没关系;问题是接收处理。假如我正在画一个界面,或者进行FFT,需要10ms,这个期间物理芯片收到的数据帧会溢出吧。
解决方法一:要求所有其他工作在1ms内告一段落,然后就要查询是不是需要接收了。这种思路不可取,那样的程序没有结构化可言。
解决方法二:在物理芯片中断服务程序中直接将收到到数据帧保存到接收队列。这种方法违反了“嵌入系统中中断服务程序应尽量短小”的规则。但是规则就是用来打破的。如果系统中没有另一个需要及时处理,而优先级又比较低的中断,就可以用这种方法。
解决方法三:现在还没有想起来呢。
实在不行,丢帧就丢帧了。TCP应该就可以部分解决丢帧的问题吧。就象别人和你说话太快了,你总可以说:麻烦你重说一遍,说慢一点。而且,如果你用一个低速处理器,挂在100M接口芯片上,然后还做大数据量的网络通讯,本来就处理不过来嘛。
于是,我的主程序可能变成这付样子:
while(1)
{
etherProcess(); //处理以太网帧的发送接收
timerProcess(); //管理定时器,在定时器到达时调用相应的处理函数
userNetProcess(); //在TCP/IP协议栈之上,处理用户级的事件
keyProcess(); //处理按键事件
uartProcess(); //处理UART事件
...
}
另外还有两个中断:
__irq etherInt(void);
__irq timerInt(void);
平心而论,有OS后,系统结构更清晰。但是如果你滥用OS中互斥之类的机制,死机就在眼前;如果没有必要的建立过多的任务,效率就会下降。
一家之言。只是觉得在嵌入系统中,单任务还是有潜力可挖的。
人类一思考,上帝就发笑,嘿嘿。
有奖活动 | |
---|---|
【有奖活动】分享技术经验,兑换京东卡 | |
话不多说,快进群! | |
请大声喊出:我要开发板! | |
【有奖活动】EEPW网站征稿正在进行时,欢迎踊跃投稿啦 | |
奖!发布技术笔记,技术评测贴换取您心仪的礼品 | |
打赏了!打赏了!打赏了! |