I use cw6.4 and when I use optimization it comes out an annoying problem.
the optimization setting are:
optimization level 4;
IPA FILE level optimization;
codes as follows:
void Delay20(void)
{
KEYCNT=0;
while(KEYCNT<=19)
{
// asm{NOP};
}
}
If I do not use asm{NOP}; the result of disassmble are :
; 2808: void Delay20(void)
; 2809: {
; 2810:
; 2811: KEYCNT=0;
; 2812: while(KEYCNT<=19)
; 2813: {
; 2814:
; 2815: // asm{NOP};
;
0x00000000 _Delay20:
; Delay20:
0x00000000 0x4E560000 link a6,#0
;
; 2816: }
; 2817:
; 2818:
;
0x00000004 0x60FE bra.s *+0 ; 0x00000004
;
; 2819: }
0x00000006 0x4E71 nop
And if use asm{NOP}; the result of disassmble are :
; 2807: //~~~~~~~delay20ms~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
; 2808: void Delay20(void)
; 2809: {
; 2810:
;
0x00000000 _Delay20:
; Delay20:
0x00000000 0x4E560000 link a6,#0
;
; 2811: KEYCNT=0;
; 2812: while(KEYCNT<=19)
; 2813: {
; 2814:
;
0x00000004 0x42B900000000 clr.l _KEYCNT
0x0000000A 0x7013 moveq #19,d0
0x0000000C 0x6002 bra.s *+4 ; 0x00000010
;
; 2815: asm{NOP};
;
0x0000000E 0x4E71 nop
;
; 2816: }
; 2817:
; 2818:
;
0x00000010 0xB0B900000000 cmp.l _KEYCNT,d0
0x00000016 0x64F6 bcc.s *-8 ; 0x0000000e
;
; 2819: }
0x00000018 0x4E5E unlk a6
0x0000001A 0x4E75 rts
why thy are so different ?It is quite annoying>...
Is KEYCNT global and updated else where, ie interrupt ?
If so declare it volatile and the compiler should do the right thing.
Hi
Thanks for your reply.In fact the variable KEYCNT is really updated in a periodic interrupt.My project works well now.BUT I did not quite catch you.You mean Variables assigned to registers through compiler optimization may be corrupted during execution? If so ,where? Would you plz explain it some further more?
Thanks
Doom.
No, nothing will get 'corrupted', but a variable that is otherwise not used in a loop may get optimized away. Declaring it 'volatile' tells the compiler that the variable may get updated outside of the scope visible to the compiler, so it needs to re-read that variable every time it wants to use the variable.
In your case, the variable apparently was not declared 'volatile', so the compiler assumed it knew everything there was to know about KEYCNT, and since no modification was visible in the code (without the NOP), the variable was optimized away.
Inserting the NOP, the compiler didn't know at least a small part of the code, so it couldn't optimize as aggressively, even though no 'volatile' was used.
If you will, I wrote an article on 'volatile' (and 'const', but that's not relevant here; 'restrict' is mentioned, but not yet included...), which you may find at http://www.bezem.de/pdf/tqinc.pdf.
HTH,
Johan
Hi
Thanks again!
I have read your article .The last part is a little complicated but it is very helpful.
Regards
doom
Well, they are not so different to me.
First, your loop seems to be an endless loop, since KEYCNT is never incremented after initialization.
So the first compilation without asm(NOP) simply implements this endless loop by a branch instruction jumping onto itself. 'unlk' and 'rts' are not necessary, since this loop will never exit.
And since the compiler doesn't know anything about the inline assembler code, adding the asm(NOP) will need to include this assembler instruction in the final code, then checking the value of KEYCNT once more just in case the assembler code has changed the value of KEYCNT without the C compiler knowing anything about it. It will remain endless, of course...
HTH,
Johan
Hi Johan
As a matter of fact, KEYCNT is updated in an interrupt.I take Chris’ advice and my project is working well.Tanks all the same.
regards
doom