本帖最后由 manhuami2007 于 2017-1-4 22:49 编辑
通过调试和阅读代码,发现是因为串口出现了类似死锁的问题。 什么是死锁?
死锁是指两个或两个以上进程在执行过程中,由于竞争资源或者由于彼此通讯而造成的阻塞状态。 因此死锁的重点是多个进程使用同一资源。 没有操作系统为何出现的多个进程呢?没有操作系统的嵌入式系统中也存在两个进程:
根据上面的分析,我们知道是由于主循环在使用外设的同时,中断也要使用这个外设。 先看看HAL库操作外设的简单流程图
程序先检查外设是否上锁,如果上锁则直接退出,没有上锁则上锁之后接着进行相应的设置最后执行后续操作。 问题就出在这个上锁上。我的程序使用的外设是UART,使用中断接收数据,使用DMA发送数据。在中断中收到一个字节之后,再打开中断接收下一个字节。在主循环中使用DMA发送相关的数据。 那么当主程序中使用正在设置UART发送时,也就是UART还处于锁定的状态时,进入了UART接收中断,这时在中断用又要设置UART接收,此时UART处于锁定状态,所以UART的接收设置肯定会失败。从而造成UART不能再接收数据。 怎么处理呢?这种情况下,我们不能在中断中等待外设释放锁定,因为此时主循环中的程序无法执行,因此不能释放资源。 所以我们应该在中断中通过函数的返回值判断操作是否成功,若没有成功则设置一个标志位,然后再在主循环中检查这个标志位,并在主循环中重新进行操作。 总结避免死锁最根本的方法就是防止在主循环与中断中同时使用同一外设。 如果不能避免,那么尽量做到执行每个函数后,都判断返回值是否正确,并对执行失败的操作做相应的处理。 |
微信公众号
手机版
由LDREX,STREX,LDREXH,STREXH,LDREXB,STREXB和CLREX指令配合内部的全局监视器来完成
内存的某一地址处用于标志一个外设是否空闲,在内核请求外设前,先来一个ldrex看看外设是否空闲,如果busy(可能是之前的一个任务崩溃,需要特殊处理),继续尝试;如果空闲,再来一个strex(因为当前任务可能被OS切出,可能发生A任务ldr,B任务str同一个外设,就乱套了),如果成功,说明该外设已被改任务独占,该任务可以安全地使用该外设;如果失败,则发生了os切换的情况,需要继续重试。任务使用完后需要对外设进行释放。这样实现的互锁机制,保证一个外设在一段时间内只能被一个任务使用