This discussion has been locked.
You can no longer post new replies to this discussion. If you have a question you can start a new discussion

Overkeen Optimisation of Volatile variable

I have ported some code to an 8051 based processor using Keil C51 v7.06 (from Cosmic for ST7).

The code worked fine with Cosmic, and indeed nearly all of it works with C51. One area is causing trouble. The original code used a global counter value that was incremented by a timer interrupt routine. This was then used for things like timing key press events to determine long or short key press times and take appropriate action. The code is as follows:

-----module1.c------

volatile unsigned char rtc_count;

/*
** Timer 1 interrupt, every 25ms
**  Used for other things too - but simplified for posting
*/
void RTC_int(void) interrupt 3
{
    ++rtc_count;
}

-----module2.c------
extern volatile unsigned char rtc_count;

   rtc_count = 0;

   while (read_keys() == TEST) {
      if (rtc_count >= 80) {
          // 2 seconds elapsed
    	    break;
      }
   }

   if  (rtc_count >= 80) {
        // do long keypress action
   }
   else {
        // do short keypress actions
   }
The trouble appears to be that the volatile is NOT recognised. Holding the key will not result in the break statement ever happening.

If I change the while loop to include a statement that actually uses the rtc_value, such as:

   while (read_keys() == TEST) {
      printf("%u%, (unsigned int)rtc_count);
      if (rtc_count >= 80) {
          // 2 seconds elapsed
    	    break;
      }
   }

Then the 2 second keypress works every time.

The listing file for the first piece of code is as follows:
0013 E4                CLR     A
0014 900000      E     MOV     DPTR,#rtc_count
0017 F0                MOVX    @DPTR,A
                                           ; SOURCE LINE # 811
0018 900000      E     MOV     DPTR,#sysinfo
001B E0                MOVX    A,@DPTR
001C FF                MOV     R7,A
001D 13                RRC     A
001E 13                RRC     A
001F 543F              ANL     A,#03FH
0021 20E00F            JB      ACC.0,?C0138
0024         ?C0139:
                                           ; SOURCE LINE # 812
0024 120000      E     LCALL   read_sr
0027 BF4109            CJNE    R7,#041H,?C0138
                                           ; SOURCE LINE # 821
002A 900000      E     MOV     DPTR,#rtc_count
002D E0                MOVX    A,@DPTR
002E C3                CLR     C
002F 9450              SUBB    A,#050H
0031 40F1              JC      ?C0139
                                           ; SOURCE LINE # 823
0033         ?C0138:


If I add the printf statement (actually an sprintf, and call to LCD output routine) the lisitng code is as follows:

0013 E4                CLR     A
0014 900000      E     MOV     DPTR,#rtc_count
0017 F0                MOVX    @DPTR,A
                                           ; SOURCE LINE # 811
0018 900000      E     MOV     DPTR,#sysinfo
001B E0                MOVX    A,@DPTR
001C FF                MOV     R7,A
001D 13                RRC     A
001E 13                RRC     A
001F 543F              ANL     A,#03FH
0021 20E044            JB      ACC.0,?C0138
0024         ?C0139:
                                           ; SOURCE LINE # 812
0024 120000      E     LCALL   read_sr
0027 EF                MOV     A,R7
0028 6441              XRL     A,#041H
002A 703C              JNZ     ?C0138
                                           ; SOURCE LINE # 818
002C 7BFF              MOV     R3,#0FFH
002E 7A00        R     MOV     R2,#HIGH ?SC_129
0030 7900        R     MOV     R1,#LOW ?SC_129
0032 900000      E     MOV     DPTR,#?_sprintf?BYTE+03H
0035 120000      E     LCALL   ?C?PSTXDATA
0038 900000      E     MOV     DPTR,#rtc_count
003B E0                MOVX    A,@DPTR
003C FF                MOV     R7,A
003D 900000      E     MOV     DPTR,#?_sprintf?BYTE+06H
0040 E4                CLR     A
0041 F0                MOVX    @DPTR,A
0042 A3                INC     DPTR
0043 EF                MOV     A,R7
0044 F0                MOVX    @DPTR,A
0045 7B01              MOV     R3,#01H
0047 7A00        E     MOV     R2,#HIGH message
0049 7900        E     MOV     R1,#LOW message
004B 120000      E     LCALL   _sprintf
                                           ; SOURCE LINE # 819
004E 7B01              MOV     R3,#01H
0050 7A00        E     MOV     R2,#HIGH message
0052 7900        E     MOV     R1,#LOW message
0054 900000      E     MOV     DPTR,#?_PrintLCDString?BYTE+04H
0057 7401              MOV     A,#01H
0059 F0                MOVX    @DPTR,A
005A 7D02              MOV     R5,#02H
005C 120000      E     LCALL   _PrintLCDString
                                           ; SOURCE LINE # 821
005F 900000      E     MOV     DPTR,#rtc_count
0062 E0                MOVX    A,@DPTR
0063 C3                CLR     C
0064 9450              SUBB    A,#050H
0066 40BC              JC      ?C0139
                                           ; SOURCE LINE # 823
0068         ?C0138:


Optimisation is set to level 8, and the memory model is LARGE. I cannot easily change both as we are nearing the memory capacity of the device, and it overflows (I guess I can cut out some code and try it, but I really shouldn't have to do that).

In both cases of the above, the last few lines clearly show the value of the counter is being read and tested. But in the latter the long keypress works, and I can see the value of the rtc_count increment to 80 on the latter too (so it is not being reset by something else - there are no other changes to the code!).

Most confounding.

I have tried changing the test from the simple "if (var > const)" to "if (func() > const)" with func() returning the rtc_count variable, and that does not work either.

I would be grateful for any constructive suggestions. As I mentioned at the top, this will compile and work on a Cosmic compiler.

Thankyou
Gary

0