在STM32上移植ucosII跑任务的时候,发现程序竟然死掉了,没有运行。程序也比较简单,总共有4个任务,外加一个串口中断,由串口中断控制其中一个任务,然后这个任务启动和关闭另外三个任务。
第一个任务,点亮led1。由任务4创建和删除该任务
第二个任务,点亮led2。由任务4创建和删除该任务
第三个任务,点亮led3。由任务4创建和删除该任务
第四个任务,控制前三个任务,根据串口接收的数据分别创建和删除对应的任务。
其中前三个任务的优先级都比第四个的任务优先级都要高。
在任务4的程序中,会等待mode_shaolu的值。当串口接收数据的时候,串口中断程序会使该值改变,然后while不成立,往下执行,根据mode_shaolu的值去执行不同的程序,但是发现,串口数据发后,程序根本就没有执行起来。通过硬件仿真,去跟踪看看是什么地方出问题了。
硬件仿真,发现mode_shaolu确实因为串口收到数据而改变了,但是while循环,一直跳不出来。这可奇怪了,这明明条件都不符合了。
一看汇编,就发现问题了。mode_shaolu赋值给了r0寄存器。然后就一直判断r0寄存器是不是为0。为0的话,就继续比较,而没有重新载入mode_shaolu的值。所以,当然就造成的效果是while循环一直退不出了。
原来这一切就是编译器优化的问题。在初始的时候,给mode_shaolu赋了一个初值0。但是在程序中没有改变这个值,编译器就自己将这个值给优化成0了。所以就造成上面这个效果了。
所以,我们要让编译器不要自己做这个优化。
这有两种方法了,一种是对编译器设置,让编译器编译的时候不要优化。
在MDK中,选择优化等级为0。
第二个方法就是将这个变量添加volatile属性。
即声明变量的时候,前面加volatile,告诉编译器这个变量不要进行任何优化。
硬件仿真,程序跳出while循环了。查看生成的汇编代码:
发现汇编代码都变了,先将变量的值载入到r0中,然后比较r0和0。相等的话,在将变量的值载入到r0中,在比较。这样r0的值就一直是变量的值。
在嵌入式的编程中,要注意变量优化的问题。如果编译器对代码优化的话,对一些在外部改变程序的变量,要注意声明为vloatile,防止编译器对其进行优化,从而使代码没有实现我们想要的功能。