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

Address bits in XDATA

Hi, I am looking for a way to write some C51 functions to set or clear bits stored in the 8051 external data memory. For example, the following code was done in the 8051 assembly language:

;*******************************
SYSTEM_TROUBLE1   XDATA   1000H
AC_FAIL   ACC.0
LOW_BAT   ACC.1
.
.
SYSTEM_TROUBLE2   XDATA   1001H
TELCO1_FAIL   ACC.0
TELCO2_FAIL   ACC.1
.
.
;*******************************
.
.
MOV DPTR, #SYSTEM_TROUBLE1
MOVX A, @DPTR
SETB AC_FAIL
MOVX @DPTR
.
.
How can I implement such function in C51? Thanks.

Parents
  • ... and another thing: I seem to remember that the Keil implementation is pretty inefficient.

    I've used both bit-fields and bit masking and have not noticed a real difference in the code generated for either.

    /*--------------------------------------
    Struct for bit field test.
    --------------------------------------*/
    struct bf_st
    {
    unsigned int bf1: 4;
    unsigned int bf2: 3;
    unsigned int bf3: 9;
    };
    
    struct bf_st bfst;    // Structure for 3 bit fields (16 bits)
    
    /*--------------------------------------
    Unsigned int for bit mask test.
    --------------------------------------*/
    unsigned int bfui;    // int for 3 bit fields (16 bits)
    
    /*--------------------------------------
    Macros used to read and write bits in
    the unsigned int.
    --------------------------------------*/
    #define Get_BF1a  (bfui & 0x0F)
    #define Get_BF2a  ((bfui >> 4) & 0x07)
    #define Get_BF3a  ((bfui >> 7) & 0x01FF)
    
    #define Set_BF1a(x)  (bfui = (bfui & ~0x000F) | (x) & 0x0F)
    #define Set_BF2a(x)  (bfui = (bfui & ~0x0070) | ((x) & 0x07) << 4)
    #define Set_BF3a(x)  (bfui = (bfui & ~0xFF80) | ((x) & 0x1FF) << 7)
    
    
    /*--------------------------------------
    Function to test bit field.
    --------------------------------------*/
    void test_bitfield (void)
    {
    volatile unsigned int y;
    
    bfst.bf1 = 14;
    bfst.bf2 = 7;
    bfst.bf3 = 0x1A5;
    
    y = bfst.bf1;
    y = bfst.bf2;
    y = bfst.bf3;
    }
    
    /*--------------------------------------
    Function to test bit masking.
    --------------------------------------*/
    void test_bitmask (void)
    {
    volatile unsigned int y;
    
    Set_BF1a(14);
    Set_BF2a(7);
    Set_BF3a(0x1A5);
    
    y = Get_BF1a;
    y = Get_BF2a;
    y = Get_BF3a;
    }

    The function test_bitfield tests a struct with 3 bit fields (4, 3, and 9 bits wide). A write and a read is performed to all bit fields.

    The function test_bitmask test an unsigned int that is masked into 3 blocks (4, 3, and 9 bits wide). A write and a read is performed to each.

    Note that each function writes and reads in the same way. The resulting code is as follows:

    test_bitfield

                 ; FUNCTION test_bitfield (BEGIN)
      34          void test_bitfield (void)
      35          {
      36   1      volatile unsigned int y;
      37   1      
      38   1      bfst.bf1 = 14;
    0000 E500        R     MOV     A,bfst+01H
    0002 54F0              ANL     A,#0F0H
    0004 850000      R     MOV     bfst,bfst
    0007 440E              ORL     A,#0EH
    0009 F500        R     MOV     bfst+01H,A
      39   1      bfst.bf2 = 7;
    000B 850000      R     MOV     bfst,bfst
    000E 4470              ORL     A,#070H
    0010 F500        R     MOV     bfst+01H,A
      40   1      bfst.bf3 = 0x1A5;
    0012 547F              ANL     A,#07FH
    0014 FF                MOV     R7,A
    0015 74D2              MOV     A,#0D2H
    0017 F500        R     MOV     bfst,A
    0019 EF                MOV     A,R7
    001A 4480              ORL     A,#080H
    001C F500        R     MOV     bfst+01H,A
      41   1      
      42   1      y = bfst.bf1;
    001E FF                MOV     R7,A
    001F 750000      R     MOV     y,#00H
    0022 EF                MOV     A,R7
    0023 540F              ANL     A,#0FH
    0025 F500        R     MOV     y+01H,A
      43   1      y = bfst.bf2;
    0027 E500        R     MOV     A,bfst
    0029 C4                SWAP    A
    002A F8                MOV     R0,A
    002B 54F0              ANL     A,#0F0H
    002D C8                XCH     A,R0
    002E E500        R     MOV     A,bfst+01H
    0030 C4                SWAP    A
    0031 540F              ANL     A,#0FH
    0033 48                ORL     A,R0
    0034 750000      R     MOV     y,#00H
    0037 5407              ANL     A,#07H
    0039 F500        R     MOV     y+01H,A
      44   1      y = bfst.bf3;
    003B AE00        R     MOV     R6,bfst
    003D E500        R     MOV     A,bfst+01H
    003F 7807              MOV     R0,#07H
    0041         ?C0006:
    0041 CE                XCH     A,R6
    0042 C3                CLR     C
    0043 13                RRC     A
    0044 CE                XCH     A,R6
    0045 13                RRC     A
    0046 D8F9              DJNZ    R0,?C0006
    0048 FF                MOV     R7,A
    0049 EE                MOV     A,R6
    004A 5401              ANL     A,#01H
    004C F500        R     MOV     y,A
    004E 8F00        R     MOV     y+01H,R7
      45   1      }
    0050 22                RET     
                 ; FUNCTION test_bitfield (END)


    test_bitmask
                 ; FUNCTION test_bitmask (BEGIN)
      50          void test_bitmask (void)
      51          {
      52   1      volatile unsigned int y;
      53   1      
      54   1      Set_BF1a(14);
    0000 E500        R     MOV     A,bfui+01H
    0002 54F0              ANL     A,#0F0H
    0004 850000      R     MOV     bfui,bfui
    0007 440E              ORL     A,#0EH
    0009 F500        R     MOV     bfui+01H,A
      55   1      Set_BF2a(7);
    000B 548F              ANL     A,#08FH
    000D 850000      R     MOV     bfui,bfui
    0010 4470              ORL     A,#070H
    0012 F500        R     MOV     bfui+01H,A
      56   1      Set_BF3a(0x1A5);
    0014 547F              ANL     A,#07FH
    0016 FF                MOV     R7,A
    0017 74D2              MOV     A,#0D2H
    0019 F500        R     MOV     bfui,A
    001B EF                MOV     A,R7
    001C 4480              ORL     A,#080H
    001E F500        R     MOV     bfui+01H,A
      57   1      
      58   1      y = Get_BF1a;
    0020 750000      R     MOV     y,#00H
    0023 E500        R     MOV     A,bfui+01H
    0025 540F              ANL     A,#0FH
    0027 F500        R     MOV     y+01H,A
      59   1      y = Get_BF2a;
    0029 E500        R     MOV     A,bfui
    002B C4                SWAP    A
    002C F8                MOV     R0,A
    002D 54F0              ANL     A,#0F0H
    002F C8                XCH     A,R0
    0030 E500        R     MOV     A,bfui+01H
    0032 C4                SWAP    A
    0033 540F              ANL     A,#0FH
    0035 48                ORL     A,R0
    0036 750000      R     MOV     y,#00H
    0039 5407              ANL     A,#07H
    003B F500        R     MOV     y+01H,A
      60   1      y = Get_BF3a;
    003D E500        R     MOV     A,bfui+01H
    003F AE00        R     MOV     R6,bfui
    0041 7807              MOV     R0,#07H
    0043         ?C0007:
    0043 CE                XCH     A,R6
    0044 C3                CLR     C
    0045 13                RRC     A
    0046 CE                XCH     A,R6
    0047 13                RRC     A
    0048 D8F9              DJNZ    R0,?C0007
    004A FF                MOV     R7,A
    004B EE                MOV     A,R6
    004C 5401              ANL     A,#01H
    004E F500        R     MOV     y,A
    0050 8F00        R     MOV     y+01H,R7
      61   1      }
    0052 22                RET     
                 ; FUNCTION test_bitmask (END)

    As you can see, the bit masking code is actually 2 bytes longer. If you carefully compare these functions, you'll find that the code generated is nearly identical.

    Jon

Reply
  • ... and another thing: I seem to remember that the Keil implementation is pretty inefficient.

    I've used both bit-fields and bit masking and have not noticed a real difference in the code generated for either.

    /*--------------------------------------
    Struct for bit field test.
    --------------------------------------*/
    struct bf_st
    {
    unsigned int bf1: 4;
    unsigned int bf2: 3;
    unsigned int bf3: 9;
    };
    
    struct bf_st bfst;    // Structure for 3 bit fields (16 bits)
    
    /*--------------------------------------
    Unsigned int for bit mask test.
    --------------------------------------*/
    unsigned int bfui;    // int for 3 bit fields (16 bits)
    
    /*--------------------------------------
    Macros used to read and write bits in
    the unsigned int.
    --------------------------------------*/
    #define Get_BF1a  (bfui & 0x0F)
    #define Get_BF2a  ((bfui >> 4) & 0x07)
    #define Get_BF3a  ((bfui >> 7) & 0x01FF)
    
    #define Set_BF1a(x)  (bfui = (bfui & ~0x000F) | (x) & 0x0F)
    #define Set_BF2a(x)  (bfui = (bfui & ~0x0070) | ((x) & 0x07) << 4)
    #define Set_BF3a(x)  (bfui = (bfui & ~0xFF80) | ((x) & 0x1FF) << 7)
    
    
    /*--------------------------------------
    Function to test bit field.
    --------------------------------------*/
    void test_bitfield (void)
    {
    volatile unsigned int y;
    
    bfst.bf1 = 14;
    bfst.bf2 = 7;
    bfst.bf3 = 0x1A5;
    
    y = bfst.bf1;
    y = bfst.bf2;
    y = bfst.bf3;
    }
    
    /*--------------------------------------
    Function to test bit masking.
    --------------------------------------*/
    void test_bitmask (void)
    {
    volatile unsigned int y;
    
    Set_BF1a(14);
    Set_BF2a(7);
    Set_BF3a(0x1A5);
    
    y = Get_BF1a;
    y = Get_BF2a;
    y = Get_BF3a;
    }

    The function test_bitfield tests a struct with 3 bit fields (4, 3, and 9 bits wide). A write and a read is performed to all bit fields.

    The function test_bitmask test an unsigned int that is masked into 3 blocks (4, 3, and 9 bits wide). A write and a read is performed to each.

    Note that each function writes and reads in the same way. The resulting code is as follows:

    test_bitfield

                 ; FUNCTION test_bitfield (BEGIN)
      34          void test_bitfield (void)
      35          {
      36   1      volatile unsigned int y;
      37   1      
      38   1      bfst.bf1 = 14;
    0000 E500        R     MOV     A,bfst+01H
    0002 54F0              ANL     A,#0F0H
    0004 850000      R     MOV     bfst,bfst
    0007 440E              ORL     A,#0EH
    0009 F500        R     MOV     bfst+01H,A
      39   1      bfst.bf2 = 7;
    000B 850000      R     MOV     bfst,bfst
    000E 4470              ORL     A,#070H
    0010 F500        R     MOV     bfst+01H,A
      40   1      bfst.bf3 = 0x1A5;
    0012 547F              ANL     A,#07FH
    0014 FF                MOV     R7,A
    0015 74D2              MOV     A,#0D2H
    0017 F500        R     MOV     bfst,A
    0019 EF                MOV     A,R7
    001A 4480              ORL     A,#080H
    001C F500        R     MOV     bfst+01H,A
      41   1      
      42   1      y = bfst.bf1;
    001E FF                MOV     R7,A
    001F 750000      R     MOV     y,#00H
    0022 EF                MOV     A,R7
    0023 540F              ANL     A,#0FH
    0025 F500        R     MOV     y+01H,A
      43   1      y = bfst.bf2;
    0027 E500        R     MOV     A,bfst
    0029 C4                SWAP    A
    002A F8                MOV     R0,A
    002B 54F0              ANL     A,#0F0H
    002D C8                XCH     A,R0
    002E E500        R     MOV     A,bfst+01H
    0030 C4                SWAP    A
    0031 540F              ANL     A,#0FH
    0033 48                ORL     A,R0
    0034 750000      R     MOV     y,#00H
    0037 5407              ANL     A,#07H
    0039 F500        R     MOV     y+01H,A
      44   1      y = bfst.bf3;
    003B AE00        R     MOV     R6,bfst
    003D E500        R     MOV     A,bfst+01H
    003F 7807              MOV     R0,#07H
    0041         ?C0006:
    0041 CE                XCH     A,R6
    0042 C3                CLR     C
    0043 13                RRC     A
    0044 CE                XCH     A,R6
    0045 13                RRC     A
    0046 D8F9              DJNZ    R0,?C0006
    0048 FF                MOV     R7,A
    0049 EE                MOV     A,R6
    004A 5401              ANL     A,#01H
    004C F500        R     MOV     y,A
    004E 8F00        R     MOV     y+01H,R7
      45   1      }
    0050 22                RET     
                 ; FUNCTION test_bitfield (END)


    test_bitmask
                 ; FUNCTION test_bitmask (BEGIN)
      50          void test_bitmask (void)
      51          {
      52   1      volatile unsigned int y;
      53   1      
      54   1      Set_BF1a(14);
    0000 E500        R     MOV     A,bfui+01H
    0002 54F0              ANL     A,#0F0H
    0004 850000      R     MOV     bfui,bfui
    0007 440E              ORL     A,#0EH
    0009 F500        R     MOV     bfui+01H,A
      55   1      Set_BF2a(7);
    000B 548F              ANL     A,#08FH
    000D 850000      R     MOV     bfui,bfui
    0010 4470              ORL     A,#070H
    0012 F500        R     MOV     bfui+01H,A
      56   1      Set_BF3a(0x1A5);
    0014 547F              ANL     A,#07FH
    0016 FF                MOV     R7,A
    0017 74D2              MOV     A,#0D2H
    0019 F500        R     MOV     bfui,A
    001B EF                MOV     A,R7
    001C 4480              ORL     A,#080H
    001E F500        R     MOV     bfui+01H,A
      57   1      
      58   1      y = Get_BF1a;
    0020 750000      R     MOV     y,#00H
    0023 E500        R     MOV     A,bfui+01H
    0025 540F              ANL     A,#0FH
    0027 F500        R     MOV     y+01H,A
      59   1      y = Get_BF2a;
    0029 E500        R     MOV     A,bfui
    002B C4                SWAP    A
    002C F8                MOV     R0,A
    002D 54F0              ANL     A,#0F0H
    002F C8                XCH     A,R0
    0030 E500        R     MOV     A,bfui+01H
    0032 C4                SWAP    A
    0033 540F              ANL     A,#0FH
    0035 48                ORL     A,R0
    0036 750000      R     MOV     y,#00H
    0039 5407              ANL     A,#07H
    003B F500        R     MOV     y+01H,A
      60   1      y = Get_BF3a;
    003D E500        R     MOV     A,bfui+01H
    003F AE00        R     MOV     R6,bfui
    0041 7807              MOV     R0,#07H
    0043         ?C0007:
    0043 CE                XCH     A,R6
    0044 C3                CLR     C
    0045 13                RRC     A
    0046 CE                XCH     A,R6
    0047 13                RRC     A
    0048 D8F9              DJNZ    R0,?C0007
    004A FF                MOV     R7,A
    004B EE                MOV     A,R6
    004C 5401              ANL     A,#01H
    004E F500        R     MOV     y,A
    0050 8F00        R     MOV     y+01H,R7
      61   1      }
    0052 22                RET     
                 ; FUNCTION test_bitmask (END)

    As you can see, the bit masking code is actually 2 bytes longer. If you carefully compare these functions, you'll find that the code generated is nearly identical.

    Jon

Children
  • I think that Andy was thinking of bit fields that comprise a single bit - which is after all what the original question was about. They are not as efficient as they could be.

    See: http://www.keil.com/forum/docs/thread1291.asp

    Particularly strange is testing a single bit field in, for example, an if statement. Of course, it can all be done with masks, but that is inellegant and error prone.

  • Can you give an example?

    The following looks pretty good.

    xdata struct 
    {
      char AC_FAIL :1;
      char LOW_BAT :1;
    } SYSTEM_TROUBLE1  _at_ 0x1000;
    
    
    void main( void )
    {
      if( SYSTEM_TROUBLE1.AC_FAIL )
        SYSTEM_TROUBLE1.LOW_BAT = 1;
    }
    
                 ; FUNCTION main (BEGIN)
    0000 901000            MOV     DPTR,#SYSTEM_TROUBLE1
    0003 E0                MOVX    A,@DPTR
    0004 30E003            JNB     ACC.0,?C0002
    0007 4402              ORL     A,#02H
    0009 F0                MOVX    @DPTR,A
    000A         ?C0002:
    000A 22                RET     
                 ; FUNCTION main (END)
    

  • Opps, sorry, I picked the wrong flag to test. You are correct, bit fields are inefficient.
    
    It would also be great if the compiler also optimized:
    <bitfield> <op> <const> or <const> <op> <bitfield> 
    Where <op> is ==, !=, <, >, <=, >=, &&, ||
    
    xdata struct 
    {
      char AC_FAIL :1;
      char LOW_BAT :1;
    } SYSTEM_TROUBLE1  _at_ 0x1000;
    
    
    void main( void )
    {
      if( SYSTEM_TROUBLE1.LOW_BAT )
        SYSTEM_TROUBLE1.AC_FAIL = 1;
    }
    
                 ; FUNCTION main (BEGIN)
    0000 901000            MOV     DPTR,#SYSTEM_TROUBLE1
    0003 E0                MOVX    A,@DPTR
    0004 FF                MOV     R7,A
    0005 C3                CLR     C
    0006 13                RRC     A
    0007 30E004            JNB     ACC.0,?C0002
    000A EF                MOV     A,R7
    000B 4401              ORL     A,#01H
    000D F0                MOVX    @DPTR,A
    000E         ?C0002:
    000E 22                RET     
                 ; FUNCTION main (END)
    

  • Opps, sorry, I picked the wrong flag to test. You are correct, bit fields are inefficient.

    Uhhhh. You only tested one case of bit-fields -- a 1-bit bit-field. I would make more tests before making such a broad, sweeping statement.

    Anyway, what is so inefficient about the code that was generated?

    Jon

  • Graham,

    Thanks for that. I missed your earlier post. The points you make are very good and I've passed them on to engineering to incorporate in a future release.

    Jon