之前看到一篇文章:
uC/OS内核程序错误修改记录
相关文件名:OS_MUTEX.C
函数名:OS_EVENT *OSMutexCreate
(INT8U prio, INT8U *err)
改动原因:
内核在创建互斥信号量的函数OSMutexCreate中,由于数据类型不匹配产生了PIP参数不能保存的错误。
在函数OSMutexCreate创建一个互斥信号量时,调用函数传递一个PIP作为函数实参(PIP是优先级继承优先级,其作用是利用互斥信号量解决多任务系统中可能出现的优先级反转问题。即把占用共享资源的低优先级任务的优先级暂时提高到PIP,等其释放共享资源后再恢复到原来的优先级)。函数OSMutexCreate将实参prio保存到.OSEventCnt的高八位。由于prio是INT8U数据类型的变量,其长度是八位,prio左移八位后就等于0。所以应该将prio强制转换为16位类型的数据,再左移8位,然后与0xFF相“或”并保存到.OSEventCnt。
下图表示OSMutexCreate返回的事件控制块ECB的数据结构。
改动前后的程序对比:
改动前:
OS_EVENT *OSMutexCreate (INT8U prio, INT8U *err)
{
….
pevent->OSEventCnt = (prio << 8) | OS_MUTEX_AVAILABLE;
//由于prio是八位,左移八位后就等于0
pevent->OSEventPtr = (void *)0;
…
}
改动后:
OS_EVENT *OSMutexCreate (INT8U prio, INT8U *err)
{
INT16U pip = (INT16U) prio; //强制类型转换
….
pevent->OSEventCnt = (pip << 8) | OS_MUTEX_AVAILABLE;
//将pip的低八位左移到高八位并保存到OSEventCnt
pevent->OSEventPtr = (void *)0;
….
}
内核错误发现的经过和背景:
我们在做可行性系统测试时,利用互斥信号量来保证驱动程序对资源的独占访问(参见“四、多任务系统中驱动程序实现的问题和方法”)。测试系统在main函数中成功创建了一个MUTEX,并传递了PIP为3的参数值。同时测试系统创建了一个优先级为0级的任务,这个任务运行一次后就调用OSTaskDel(OS_PRIO_SELF)将自己删除。任务将自己删除以后操作系统应该永远不会再调度该任务(参见uC/OS-II书籍),可是测试发现这个优先级为0的任务继续运行。通过调试跟踪发现,调用OSMutexCreate函数创建MUTEX时,传递的PIP参数值(值为3)没有被函数保存到ECB结构中,而是将0保存到ECB中,从而使操作系统认为创建MUTEX时传递了PIP为0 的参数。这样,在后面调用OSMutexPend的函数中将优先级为0的任务又改变成就绪状态并得以继续运行,使uC/OS-II操作系统出现了调度错误。 这个错误在uC/OS-II后续的版本中做了修改。例如V2.88就没有这个问题。
========================================================================================================
于是将原子的ucosii v2.52升级到v2.91。
应用示例程序与http://www.openedv.com/posts/list/5268.htm相同。
|