Keil Logo

Address bits in XDATA

Next Thread | Thread List | Previous Thread Start a Thread | Settings

Details Message
Read-Only
Author
Alan Chen
Posted
22-May-2002 18:31 GMT
Toolset
C51
New! 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.

Read-Only
Author
Jon Young
Posted
22-May-2002 19:18 GMT
Toolset
C51
New! RE: Address bits in XDATA
try:

xdata struct 
{
  char AC_FAIL :1;
  char LOW_BAT :1;
} SYSTEM_TROUBLE1  _at_ 0x1000;


void main( void )
{
  SYSTEM_TROUBLE1.LOW_BAT = 1;
}

             ; FUNCTION main (BEGIN)
0000 901000            MOV     DPTR,#SYSTEM_TROUBLE1
0003 E0                MOVX    A,@DPTR
0004 4402              ORL     A,#02H
0006 F0                MOVX    @DPTR,A
0007 22                RET     
             ; FUNCTION main (END)
Read-Only
Author
Alan Chen
Posted
22-May-2002 19:41 GMT
Toolset
C51
New! RE: Address bits in XDATA
Thanks. I forgot all about "bit field".
Read-Only
Author
Andrew Neil
Posted
23-May-2002 09:41 GMT
Toolset
C51
New! RE: Address bits in XDATA
Beware!
From K&R, "Almost everything about fields is implementation-dependent"

Unfortunately, it is not documented in the C51 manual. :-(

See the following Knowledge Base articles, which document a couple of the quirks of Keil's implementation:
http://www.keil.com/support/docs/928.htm
http://www.keil.com/support/docs/1279.htm
Read-Only
Author
Andrew Neil
Posted
23-May-2002 13:55 GMT
Toolset
C51
New! RE: Address bits in XDATA
... and another thing: I seem to remember that the Keil implementation is pretty inefficient.

So, C51 bitfields are poorly documented, and the implementation is confusing and inefficient - but apart from that they're great!

Probably best to stick to masking, etc?
Read-Only
Author
Jon Ward
Posted
27-May-2002 08:26 GMT
Toolset
C51
New! RE: Address bits in XDATA
... 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
Read-Only
Author
Graham Cole
Posted
27-May-2002 10:16 GMT
Toolset
C51
New! RE: Address bits in XDATA
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.
Read-Only
Author
Jon Young
Posted
27-May-2002 13:29 GMT
Toolset
C51
New! RE: Address bits in XDATA
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)
Read-Only
Author
Jon Young
Posted
27-May-2002 14:46 GMT
Toolset
C51
New! RE: Address bits in XDATA
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)
Read-Only
Author
Jon Ward
Posted
27-May-2002 17:12 GMT
Toolset
C51
New! RE: Address bits in XDATA
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
Read-Only
Author
Jon Ward
Posted
27-May-2002 17:24 GMT
Toolset
C51
New! RE: Address bits in XDATA
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

Next Thread | Thread List | Previous Thread Start a Thread | Settings

  Arm logo
Important information

This site uses cookies to store information on your computer. By continuing to use our site, you consent to our cookies.

Change Settings

Privacy Policy Update

Arm’s Privacy Policy has been updated. By continuing to use our site, you consent to Arm’s Privacy Policy. Please review our Privacy Policy to learn more about our collection, use and transfers
of your data.