本帖最后由 熊猫烧香 于 2017-1-2 12:33 编辑
主程序架构大概是while(1)循环判断定时器100ms标志是否置位,如果置位LCD屏显示。问题是:keil的target中的memory如果选择small模式,主程序正常,而选择large模式,主程序卡死,指示灯不闪烁
void main(void)
{
while(1)
{
if(nTimer100MSflag ==1)
{
LedRun = ~LedRun;
nTimer100MSflag =0;
lcd_show();
}
}
}
后排查发现lcd_show() 调用的一个延时函数有问题,延时函数如下:
void Delay_1ms(u16 x)
{
u16 i ,j;
for(j=0;j<x;j++)
{
for(i=0;i<100;i++);
}
}
延时反汇编如下:
37: void Delay_1ms(u16 x)
38: {
39: u16 i ,j;
40: for(j=0;j<x;j++)
C:0x3152 E4 CLR A
C:0x3153 FD MOV R5,A
C:0x3154 FC MOV R4,A
C:0x3155 C3 CLR C
C:0x3156 ED MOV A,R5
C:0x3157 9F SUBB A,R7
C:0x3158 EC MOV A,R4
C:0x3159 9E SUBB A,R6
C:0x315A 5015 JNC C:3171
41: {
42: for(i=0;i<100;i++);
C:0x315C E4 CLR A
C:0x315D FB MOV R3,A
C:0x315E FA MOV R2,A
C:0x315F 0B INC R3
C:0x3160 BB0001 CJNE R3,#0x00,C:3164
C:0x3163 0A INC R2
C:0x3164 EB MOV A,R3
C:0x3165 6464 XRL A,#0x64
C:0x3167 4A ORL A,R2
C:0x3168 70F5 JNZ C:315F
43: }
如果延时函数的变量i和j用volatile或data修饰,主程序也正常。如果用xdata修饰,程序卡死。虽然问题可以避免,但还是想请教一下,为什么large模式下会出现这种问题?谢谢!
再补充一个现象,如果把延时函数改一下,在large模式下也正常.如下
void Delay_1ms(u16 x)
{
u16 i ,j;
for(j=0;j<100;j++)
{
for(i=0;i<x;i++);
}
}
其反汇编如下:
49: void Delay_1ms(u16 x)
50: {
51: u16 i ,j;
52: for(j=0;j<100;j++)
C:0x3152 E4 CLR A
C:0x3153 FD MOV R5,A
C:0x3154 FC MOV R4,A
53: {
54: for(i=0;i<x;i++);
C:0x3155 E4 CLR A
C:0x3156 FB MOV R3,A
C:0x3157 FA MOV R2,A
C:0x3158 C3 CLR C
C:0x3159 EB MOV A,R3
C:0x315A 9F SUBB A,R7
C:0x315B EA MOV A,R2
C:0x315C 9E SUBB A,R6
C:0x315D 5007 JNC C:3166
C:0x315F 0B INC R3
C:0x3160 BB0001 CJNE R3,#0x00,C:3164
C:0x3163 0A INC R2
C:0x3164 80F2 SJMP C:3158
55: }
补充一下:
延时函数5级优化,主程序正常:
#pragma OPTIMIZE(5)
void Delay_1ms(u16 x)
{
u16 i , j;
for(j=0;j<x;j++)
{
for(i=0;i<100;i++);
}
}
#pragma OPTIMIZE(8)
对应反汇编:
41: void Delay_1ms(u16 x)
42: {
43: u16 i , j;
44: for(j=0;j<x;j++)
C:0x31B3 E4 CLR A
C:0x31B4 FD MOV R5,A
C:0x31B5 FC MOV R4,A
C:0x31B6 C3 CLR C
C:0x31B7 ED MOV A,R5
C:0x31B8 9F SUBB A,R7
C:0x31B9 EC MOV A,R4
C:0x31BA 9E SUBB A,R6
C:0x31BB 501A JNC C:31D7
45: {
46: for(i=0;i<100;i++);
C:0x31BD E4 CLR A
C:0x31BE FB MOV R3,A
C:0x31BF FA MOV R2,A
C:0x31C0 C3 CLR C
C:0x31C1 EB MOV A,R3
C:0x31C2 9464 SUBB A,#0x64
C:0x31C4 EA MOV A,R2
C:0x31C5 9400 SUBB A,#0x00
C:0x31C7 5007 JNC C:31D0
C:0x31C9 0B INC R3
C:0x31CA EB MOV A,R3
C:0x31CB 7001 JNZ C:31CE
C:0x31CD 0A INC R2
C:0x31CE 80F0 SJMP C:31C0
47: }
延时函数6级优化,主程序卡死:
#pragma OPTIMIZE(6)
void Delay_1ms(u16 x)
{
u16 i , j;
for(j=0;j<x;j++)
{
for(i=0;i<100;i++);
}
}
#pragma OPTIMIZE(8)
对应反汇编:
41: void Delay_1ms(u16 x)
42: {
43: u16 i , j;
44: for(j=0;j<x;j++)
C:0x326D E4 CLR A
C:0x326E FD MOV R5,A
C:0x326F FC MOV R4,A
C:0x3270 C3 CLR C
C:0x3271 ED MOV A,R5
C:0x3272 9F SUBB A,R7
C:0x3273 EC MOV A,R4
C:0x3274 9E SUBB A,R6
C:0x3275 5015 JNC C:328C
45: {
46: for(i=0;i<100;i++);
C:0x3277 E4 CLR A
C:0x3278 FB MOV R3,A
C:0x3279 FA MOV R2,A
C:0x327A 0B INC R3
C:0x327B BB0001 CJNE R3,#0x00,C:327F
C:0x327E 0A INC R2
C:0x327F EB MOV A,R3
C:0x3280 6464 XRL A,#0x64
C:0x3282 4A ORL A,R2
C:0x3283 70F5 JNZ C:327A
47: }
谢谢大家!暂时先以调整优化等级为方案解决这个问题!
元旦花了3天终于找到原因:
由于程序中使用了绝对地址定义变量,而这个地址是0xEF,导致栈地址是从0xF1开始,最终程序运行时导致栈溢出。感谢linqing171的提醒以及其他兄弟帮助!
定义了绝对地址变量内存分配如下:
REG 0000H 0008H ABSOLUTE "REG BANK 0"
DATA 0008H 0005H UNIT _DATA_GROUP_
000DH 0013H *** GAP ***
BIT 0020H.0 0001H.1 UNIT _BIT_GROUP_
0021H.1 0068H.7 *** GAP ***
IDATA 00EFH 0002H ABSOLUTE
IDATA 00F1H 0001H UNIT ?STACK
去掉绝对地址变量内存分配如下:
* * * * * * * D A T A M E M O R Y * * * * * * *
REG 0000H 0008H ABSOLUTE "REG BANK 0"
DATA 0008H 0005H UNIT _DATA_GROUP_
000DH 0013H *** GAP ***
BIT 0020H.0 0001H.1 UNIT _BIT_GROUP_
0021H.1 0000H.7 *** GAP ***
IDATA 0022H 004EH UNIT ?ID?TIMER
IDATA 0070H 0001H UNIT ?STACK
|