1:任务有切换,但切换到某个任务,总是出现hardfault错误?【现象:给出错的任务换一个大小一样但名字不一样的堆栈就可以,使用原来名字的堆栈就是出错】
解决:1:查看hardfault寄存器,找到出错的原因-->提示是fault上报导致
2:查看其它的fault寄存器,发现是用法fault-->具体为异常返回时试图非法加载EXC_RETURN到PC...
3: 又查看出错任务的堆栈(使用PSP,通过PSP查看,hardfault使用msp),找出出错时(进入hardfault前)的PC与LR,再跳到该PC处,还是不能发现不了问题。
4:直接在应用层调试,查看任务的堆栈,发现任务的堆栈256个字节都使用了,推测是堆栈溢出导致的问题,加大堆栈到512个字节,上面的现象解决,错误排除。
【其实还可以在内存中对某个地址加上观察点来试一下,我没有做】
但是为什么给出错的任务换一个大小一样但名字不一样的堆栈就可以,使用原来名字的堆栈就是出错?原因是这两个堆栈分配的空间是不一样的,而且程序中还有很多的数据分配在RAM中,两个堆栈有可能都溢出了,但是没出错的堆栈有可能是他溢出后,它的堆栈没有被其他的代码修改,或者堆栈溢出没有影响带其他的变量或者数据等,不出错其实是一个巧合。
所以在uC/OS编程中,如果出现上述分析的用法fault错误,非法加载EXC_RETURN到PC,很可能就是堆栈溢出后,被其他程序修改导致,加大堆栈试一下。
2:一个任务的堆栈大小怎么估算?
在uC/OS II中,创建任务,至少要考虑到被切换,任务切换至少使用17个寄存器(68个字节),这时再加上任务的局部变量、参数传递、函数调用等还要使用堆栈,所以至少要大于 68多 的字节。【68字节的堆栈只能符合空函数之类很简单的函数,因为在任务函数中,函数内各个私有变量以及函数调用时参数的传递基本都是使用CPU寄存器或堆栈配合来实现,这样栈肯定要大于68,如果这时栈太小,那么程序运行到需要一些开销很大的数值等时,很可能因为溢出造成hardfault错误】
方法1:可以先分配大的堆栈,再使用堆栈检验功能,带任务运行一段时间,估计堆栈使用最多的时候已经过了,再通过堆栈检验函数查看具体的堆栈使用了多少,再可以修改代码或者动态分配内存在创建任务。
方法2:来自网上自己还没有验证:
这个不是这样滴,微扣死吐 有个高级选择,CreateTaskPrxx 里面可以选择一个类似于debug模式,然后里面有个类似于stackDepth的东西,Run起来就可以知道这个Task大概用了多少ram了。当然了,前提是必须把Task的所有路径运行完毕。
PS:一般人我不告诉他的,看你是原子锅的粉丝就额外给你的建议。
3:任务划分
在uC/OS II工程中,可能会包含多种外设,可能会有很多种功能,比如键盘,显示等等, 其实任务划分时最好将各功能 任务化, 比如显示就单独成立一个显示任务,键盘就单独成立一个键盘扫描任务,任务之间通信通过各种通信机制进行; 不能在各个任务之间,将各种的功能太过交叉化,比如显示功能,该功能模块可能会有多个显示函数接口,那么如果不单独将显示做出一个独立的任务,那么在很多任务中就要交叉使用这个显示函数接口,如果某一个显示函数接口在函数可重入性方面做的不好,就会引发程序错误;那如果将显示独立做成一个任务【也就是将函数都变成该任务的私有函数】,那其他的任务想要显示时,可以通过邮箱或消息队列与显示任务通信,这样程序就会安全很多。
目前,各功能单独成立为一个任务,比如显示功能成为显示任务,文件系统通过一个任务来管理,这样文件系统任务要显示时,就向显示任务的消息队列里面发送显示消息,而不是直接在本任务中调用显示函数。
4:资源同步
采样任务将AD的采样结果转换并存储到数组data[]中,显示任务从data[]中读取数据并显示。
两个任务需要访问同一个资源:data[],那么时就可以先定义一个互斥信号量,任务一个任务需先获取该互斥信号量再进行操作,最后释放信号量。
用简单的二值信号来解决资源访问冲突,因为没有优先级的反转,容易锁住(为什么?或者不是这样
,待求证),比如低优先级的任务在获取了二值信号量还没有释放时就被高优先级的任务抢占
什么是共享资源?共享资源就是被两个或以上的并发程序单元(如:ISR与任务、任务与任务)访问的资源,共享资源一定是全局资源,但是全局资源不一定是共享资源,如字体数组,是全局的数值,但只被单个任务使用(显示任务),就不是共享资源;
什么是资源同步?访问共享资源的代码段位临界区(关键段落),各个临界区访问共享资源时,一定要保住互斥访问,要做到这点,就需要使用相关的措施,这些措施就是资源同步。
为什么要使用资源同步?因为可读可写的共享资源的访问一定要在互斥条件下进行,只有这样才能保证共享资源的可靠性与完整性;如当前的A临界区要用到共享资源,且这时的共享资源对A有效,那如果不适用资源同步,就很有可能在A使用对于自己有效的共享资源时,共享资源被修改,造成错误。
是不是所有的共享资源都是需要进行资源同步?不一定,如一些共享资源的属性是只读,不能被写,所有使用它的代码段,只能读取它,不能修改它,所以不需要资源同步;对于那些可读可写的共享资源,一定要进行资源同步。
|