/*环境keil4 + STM32*/
/*函数体和它的汇编代码*/
/*全局变量写入*/
void SetCalStatus1(gUINT8 Par1,gUINT8 Par2)
{
gUINT32 CPUStatus = 0x05;
gUINT8 Temp = 6;
__nop();
CalendarStatus = Par1;
__nop();
CalendarStatus = Par2;
__nop();
}
0x08000A02 0800 LSRS r0,r0,#0
// 198: {
0x08000A04 B510 PUSH {r4,lr} /*下面使用了R4压入堆栈,LR返回地址*/
// 199: gUINT32 CPUStatus = 0x05;
0x08000A06 2205 MOVS r2,#0x05 /*赋值CPUStatus*/
// 200: gUINT8 Temp = 6;
// 201:
0x08000A08 2306 MOVS r3,#0x06 /*赋值Temp*/
// 202: __nop();
0x08000A0A BF00 NOP
// 203: CalendarStatus = Par1; /*316由汇编器计算得出*/
0x08000A0C 4C4F LDR r4,[pc,#316] ; @0x08000B4C /*加载全局变量CalendarStatus的地址*/
0x08000A0E 7020 STRB r0,[r4,#0x00] /*把R0,即参数1,写入CalendarStatus地址处*/
// 204: __nop();
0x08000A10 BF00 NOP
// 205: CalendarStatus = Par2;
0x08000A12 7021 STRB r1,[r4,#0x00] /*把R1,即参数1,写入CalendarStatus地址处*/
// 206: __nop();
0x08000A14 BF00 NOP
// 207: }
0x08000A16 BD10 POP {r4,pc} /*R4和PC出栈*/
/*调用这个函数的C代码和汇编代码*/
GPIO_ResetBits(BEEP_PORT,BEEP);
SetCalStatus1(3,4);
while(1)
{
。。。。。。
0x08000A62 483D LDR r0,[pc,#244] ; @0x08000B58
0x08000A64 F001FA51 BL.W GPIO_ResetBits (0x08001F0A)
// 334: SetCalStatus1(3,4);
0x08000A68 2104 MOVS r1,#0x04 /*加载参数到r1*/
0x08000A6A 2003 MOVS r0,#0x03 /*加载参数到r0*/
0x08000A6C F7FFFFCA BL.W SetCalStatus1 (0x08000A04) /*调用函数*/
// 335: while(1)
// 336: {
。。。。。。
可以看到修改全局变量的值需要两条指令。
0x08000A0C 4C4F LDR r4,[pc,#316] ; @0x08000B4C /*加载全局变量CalendarStatus的地址*/
0x08000A0E 7020 STRB r0,[r4,#0x00] /*把R0,即参数1,写入CalendarStatus地址处*/
在RTOS中如果在不关中断保护的情况下,修改全局变量的值,有可能在这两句之间产生任务切换。
/*全局变量读取*/
gUINT8 GetCalStatus1()
{
gUINT8 Temp;
__nop();
Temp = CalendarStatus;
__nop();
return Temp;
}
// 201: __nop();
0x08000A04 BF00 NOP
// 202: Temp = CalendarStatus;
0x08000A06 4955 LDR r1,[pc,#340] ; @0x08000B5C /*加载全局变量的地址*/
0x08000A08 7808 LDRB r0,[r1,#0x00] /*载入全局变量值*/
// 203: __nop();
// 204:
// 205: return Temp;
0x08000A0A BF00 NOP
206: }
可以看到读取全局变量的值也需要需要两条指令,如果在两条指令之间切换任务,
在任务切换回来可能就会出现,读出的是旧值。