实时操作系统若干问题

SYS/BIOS和uC/OS是可剥夺型实时操作系统,其特点是高优先级的任务可以无条件抢占CPU时间,这种情况下低优先级任务得不到任何运行的机会。在实时操作系统的任务设计中,任务间的分工、时序、优先级设计都是非常重要的方面,设计不当将引起诸多问题。本文总结了我在设计中遇到的几个这样的问题。

1.DM8168与C6678间通过I2C接口传输数据,DM8168为主发C6678为从收。C6678采用中断方式,在中断中把接收寄存器的数据读取出来存入一个FIFO,然后抛出信号量。读函数中等待信号量,然后从FIFO中读取数据拷贝给应用层。
在某次数据传输时发现DM8168发送数据C6678不能正常收到。先用示波器测量线上数据,发现数据正常,在数据末尾有ACK响应,说明硬件层正常。
然后用仿真器运行C6678,在中断中打断点,发现能正常进入中断,从中读出的数据也正确,还正常抛出了信号量。再在读函数的信号量返回处打断点,全速运行CPU未进入断点。恢复中断中的断点仍能断住且信号量抛送也能执行。
这时开始怀疑信号量有问题。查阅信号量API手册和实现源码也未发现问题。后来偶然暂停住CPU时发现正在执行另一个进程中的一个循环。查看CPU的Load发现已到达100%。
原来是另一个进程的优先级比调用I2C读函数的进程优先级高,且其中有一个分支会进入一个无阻塞的死循环,从而使得CPU无法执行I2C读,自然得不到数据。
最后是通过修改该分支的动作,让出一定的CPU,从而使得系统恢复正常。

2.仍然是DM8168与C6678间通信,改为使用网口。两者间的网络接口通过一片交换芯片在板上相连。C6678上使用NDK建立一个TCP服务器接收数据。然而在实际运行开始后,在DM8168上ping C6678不通。
在网络中接入一台PC机,用DM8168和PC机互Ping,均可以通,排除了DM8168的问题。
将交换芯片配置为镜像模式,从第三个接口把两者间数据引出,用PC机的Wireshark抓取数据。发现刚开机时两者数据交互正常,TCP握手也能正常完成,但之后C6678就再也不响应Ping包。
架上仿真器在C6678上调试,先在TCP完成握手后打断点,发现C6678能正常完成bind、listen、accept这几个步骤,后续是一个不间断的从监听句柄上读数据的过程。单步执行总是返回读不到数据,仔细再分析这个读函数发现原来用的是非阻塞读,即recv最后一个参数为0。这样recv就不停返回,占用CPU。而这个进程的优先级高于NDK核心进程优先级9,所以NDK都无法响应ping包。
将recv最后一个参数改为阻塞读,问题解决。

3.DM8168与C6678间的网口通信,仍然是这个问题,只不过占用CPU的是IPC库函数。最后修改时序避开这个问题。

总结一下,出现高优先级任务占用CPU的原因有很多:自己代码出现问题,其他接口函数的阻塞或非阻塞方式,其他库函数里未做说明的占用CPU。解决方法也各有不同。此类bug最重要的是定位问题。
现在调试经验丰富后再回头看这些案例,当使用CCS时要积极利用其ROV工具,其中有Load和Task、Semapore和Mailbox等多个模块,便于快速定位问题。这种情况下看Task模块会立即发现当前是哪个任务在运行,哪些任务被阻塞,哪些任务已Ready但暂时无法运行,这些都是系统当前状态的重要信息。当然利用Wireshark抓包和示波器抓线上波形都是万年不变的法宝,需要灵活应用。

你可能感兴趣的:(操作系统)