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

Assign value issue in pdata variable

Hi all,

In my project, I write some codes like this sample:

1    void foo(char xdata *pbuf, char a, char b)
2    {
3       int pdata bufaddr;
4       long pdata testval;
5
6       testval = 0x200;
7       bufaddr = pbuf;
8    }
9
10   void main(void)
11   {
12      char xdata buf[10];
14
15      foo(buf, 0, 1);
16   }

And C51 would be compile these codes to this assembly:

             ; FUNCTION _foo (BEGIN)
                                           ; SOURCE LINE # 1
0000 8D00        R     MOV     a,R5
0002 8B00        R     MOV     b,R3
;---- Variable 'pbuf' assigned to Register 'DPTR' ----
0004 8F82              MOV     DPL,R7
0006 8E83              MOV     DPH,R6
                                           ; SOURCE LINE # 2
                                           ; SOURCE LINE # 6
0008 7800        R     MOV     R0,#LOW testval
000A 120000      E     LCALL   ?C?LSTKPDATA
000D 00                DB      00H
000E 00                DB      00H
000F 02                DB      02H
0010 00                DB      00H
                                           ; SOURCE LINE # 7
0011 AF82              MOV     R7,DPL
0013 7800        R     MOV     R0,#LOW bufaddr
0015 E583              MOV     A,DPH
0017 F2                MOVX    @R0,A
0018 08                INC     R0
0019 EF                MOV     A,R7
001A F2                MOVX    @R0,A
                                           ; SOURCE LINE # 8
001B 22                RET
             ; FUNCTION _foo (END)

             ; FUNCTION main (BEGIN)
                                           ; SOURCE LINE # 10
                                           ; SOURCE LINE # 11
                                           ; SOURCE LINE # 14
0000 7E00        R     MOV     R6,#HIGH buf
0002 7F00        R     MOV     R7,#LOW buf
0004 7B01              MOV     R3,#01H
0006 E4                CLR     A
0007 FD                MOV     R5,A
0008 020000      R     LJMP    _foo
             ; FUNCTION main (END)

C51 would assign parameter pbuf to DPTR when function foo is called. Then in foo function, program first would call ?C?LSTKPDATA to assign a constant long type value to testval. ?C?LSTKPDATA would do the following assembly:

D083     POP      DPH(0x83)
D082     POP      DPL(0x82)
E4       CLR      A
93       MOVC     A,@A+DPTR
F2       MOVX     @R0,A
08       INC      R0
7401     MOV      A,#0x01
93       MOVC     A,@A+DPTR
F2       MOVX     @R0,A
08       INC      R0
7402     MOV      A,#0x02
93       MOVC     A,@A+DPTR
F2       MOVX     @R0,A
08       INC      R0
7403     MOV      A,#0x03
93       MOVC     A,@A+DPTR
F2       MOVX     @R0,A
7404     MOV      A,#0x04
73       JMP      @A+DPTR

When finished ?C?LSTKPDATA, program would assign pbuf value to bufaddr. But pbuf is stored in DPTR, and ?C?LSTKPDATA used DPTR to assgin value before, it cause pbuf value in DPTR is overwrited, so the bufaddr would store the wrong value.

It seems this situation is caused by optimization of C51. I want to ask whether any method to prevent this situation occur.

Thanks all.

Parents
  • Hi Per,

    bufaddr is just a int type to store address of buffer. In my project, bufaddr is a register in page of PDATA to store address of buffer. Hardware have to read this value to determine where the data is saved. For example, if bufaddr store 0x1000, hardware would save data to address 0x1000 in XDATA

Reply
  • Hi Per,

    bufaddr is just a int type to store address of buffer. In my project, bufaddr is a register in page of PDATA to store address of buffer. Hardware have to read this value to determine where the data is saved. For example, if bufaddr store 0x1000, hardware would save data to address 0x1000 in XDATA

Children
  • "bufaddr is just a int type to store address of buffer."

    Yes, but the fact that you take an xdata pointer and stores the value in an integer (stored in pdata) indicates that you are playing with tricky code that is very likely to hurt you down the line.

    Why not continue to store an xdata pointer? You shouldn't see pointers as integer values unless there are very specific incentives from doing it. Such an incentive could be a mail primitive that takes an extra parameter where you, depending on type of mail, might sometimes just want to send an integer value, and sometimes a pointer to an object.

    But jumping between integers and pointers means that the compiler can't help you by keeping track of possible type errors in the code.

  • Sorry, it seems that my sample code let all misunderstand my question.

    Actually, the code having the issue in my project is the following:

    1915    BYTE MsReadOnePage(BYTE xdata * pbBuf,UINT iBlockAddr,BYTE bPageAddr)
    1916    {
    1917            BYTE bIntVal;
    1918
    1919            /* Set transfer length */
    1920            CardByteLenReg = 0x200;
    1921
    1922            /* Set CardFifoAdr */
    1923            CardFifoAdrReg = pbBuf;
    1924
    1925            if( !MsSetReadCmdParameter(DATA_AND_EXTRA_DATA_BY_PAGE,iBlockAddr,bPageAddr) )
    1926            {
    1927                    return FAILURE;
    1928            }
    1929
    1930            bIntVal = MsGetInt();
    1931
    1932            if( bIntVal == FAILURE )
    1933            {
    1934                    return FAILURE;
    1935            }
    ...
    1960            return SUCCESS;
    1961    }
    

    In this function, some basic data type is defined as the following:

    #define  BYTE   unsigned char
    #define  UINT   unsigned int
    #define  ULONG  unsigned long
    

    CardByteLenReg, CardFifoAdrReg is the hardware registers accessed as external ram by 8051. In project, I declare them to pdata and access them

    UINT  volatile pdata    CardFifoAdrReg                  _at_ 0x20;
    ULONG volatile pdata    CardByteLenReg                  _at_ 0x22;
    

    C51 compile this function to these assembly:

                 ; FUNCTION _MsReadOnePage (BEGIN)
                                               ; SOURCE LINE # 1915
    0000 8C00        R     MOV     iBlockAddr,R4
    0002 8D00        R     MOV     iBlockAddr+01H,R5
    0004 8B00        R     MOV     bPageAddr,R3
    ;---- Variable 'pbBuf' assigned to Register 'DPTR' ----
    0006 8F82              MOV     DPL,R7
    0008 8E83              MOV     DPH,R6
                                               ; SOURCE LINE # 1916
                                               ; SOURCE LINE # 1920
    000A 7800        E     MOV     R0,#LOW CardByteLenReg
    000C 120000      E     LCALL   ?C?LSTKPDATA
    000F 00                DB      00H
    0010 00                DB      00H
    0011 02                DB      02H
    0012 00                DB      00H
                                               ; SOURCE LINE # 1923
    0013 AF82              MOV     R7,DPL
    0015 7800        E     MOV     R0,#LOW CardFifoAdrReg
    0017 E583              MOV     A,DPH
    0019 F2                MOVX    @R0,A
    001A 08                INC     R0
    001B EF                MOV     A,R7
    001C F2                MOVX    @R0,A
                                               ; SOURCE LINE # 1925
    001D AD00        R     MOV     R5,iBlockAddr+01H
    001F AC00        R     MOV     R4,iBlockAddr
    0021 7F20              MOV     R7,#020H
    0023 120000      R     LCALL   _MsSetReadCmdParameter
    0026 EF                MOV     A,R7
    0027 7002              JNZ     ?C0367
                                               ; SOURCE LINE # 1926
                                               ; SOURCE LINE # 1927
    0029 FF                MOV     R7,A
    002A 22                RET
                                               ; SOURCE LINE # 1928
    002B         ?C0367:
                                               ; SOURCE LINE # 1930
    002B 120000      R     LCALL   MsGetInt
    ;---- Variable 'bIntVal' assigned to Register 'R7' ----
                                               ; SOURCE LINE # 1932
    002E EF                MOV     A,R7
    002F 7002              JNZ     ?C0369
                                               ; SOURCE LINE # 1933
                                               ; SOURCE LINE # 1934
    0031 FF                MOV     R7,A
    0032 22                RET
                                               ; SOURCE LINE # 1935
    0033         ?C0369:
    ...
                                               ; SOURCE LINE # 1961
    005F         ?C0368:
    005F 22                RET
                 ; FUNCTION _MsReadOnePage (END)
    

    These code would have the same problem with the sample code in my first post when assigning value to CardByteLenReg and CardFifoAdrReg: DPTR is overwrited in ?C?LSTKPDATA, so CardFifoAdrReg would be assigned a wrong value.

    What should I do to avoid this situation occur?

  • Sorry, it seems that my sample code let all misunderstand my question.

    That's one of the common problems caused by trying to present a problem while not presenting the actual problem. Writing good problem reports is a seriously underestimated skill.

    It can take very deep understanding of all tools and languages involved to boil down a given source code to the minimal, yet sufficient example that still actually demonstrates the problem faithfully. You got one thing right in your first code sample: self-sufficiency, i.e. you showed code that actually compiled as-is, with no further assumptions, unknown include files, etc (Unfortunately, you got this wrong the second time round). You did get the other major aspect wrong the first time round, though: making sure that the code is still functionally equivalent to the original which you didn't want to publish. Exchanging static, volatile fixed-address variables for unqualified automatic ones totally changed the scope of the problem.

    It would still be better if you changed the type of CardFifoAdrReg to (xdata void *), and brought your second sample code into stand-alone, compilable form, but from what I can see, that does look like you might have a support case to bring to Keil's attention there. Because whatever goes wrong there, it appears to happen between the compiler and its support library functions, so there's little else you could do about it.

    A possible workaround suggests itself, though: switch order of assignments to those two registers, if the hardware behind them permits it.