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

XBANKING, LX51, Pointers and Assembler

Hi! I'm using XBANKING.a51 from
 "Keil\C51\Examples\FarMemory\3 XData Areas on T89C51RD2"
 for access to various types of memory MCU Atmel AT89C5131.

  I'm define memory model - Large, "User Classes" as:

XDATA (X:0x008000-X:0x009FFE)             // off-chip XRAM
HDATA_EEPROM (X:0x020000-X:0x0207FF)      // on-chip EEPROM
HDATA (X:0x010000-X:0x0103FF)             // on-chip XRAM

  And variables as:
in file MAIN.c

unsigned char       *Pointer1, *Pointer2;
unsigned char far   onBufer;              // on-chip XRAM
unsigned char xdata offBufer;             // off-chip XRAM
unsigned code       cBufer = "Welcome";   // on-chip ROM

in file EEPROM.c

#pragma USERCLASS (HDATA = EEPROM)
unsigned char far   EEBufer;              // on-chip EEPROM

I'm programming next code:

Pointer1 = onBufer;                       // pointer to 0x01AABB
Pointer2 = cBuffer;                       // pointer to 0xFFCCDD
memcpy(Pointer1, Pointer2, 20);

Compiling my program and view "Disassembly Window":

...
Pointer1 = onBuffer;
908010   MOV      DPTR,#Pointer1(0x8010)
7402     MOV      A,#0x02                 // on-chip EEPROM area !!!
F0       MOVX     @DPTR,A
A3       INC      DPTR
74AA     MOV      A,#0xAA
F0       MOVX     @DPTR,A
A3       INC      DPTR
74BB     MOV      A,#0xBB
F0       MOVX     @DPTR,A
Pointer2 = cBuffer;
A3       INC      DPTR
74FF     MOV      A,#0xFF
F0       MOVX     @DPTR,A
A3       INC      DPTR
74CC     MOV      A,#0xCC
F0       MOVX     @DPTR,A
A3       INC      DPTR
74DD     MOV      A,#0xDD
F0       MOVX     @DPTR,A
memcpy(Pointer1, Pointer2, 20);
...

Where the bug or my error?

  • According to the code that you posted, "onBufer" is a character and not a pointer. The assignment statement would be incorrect, and you should get a warning (from lint if not the compiler -- you are using lint, right?) when you assign a charater to a pointer.

    unsigned char       *Pointer1, *Pointer2;
    unsigned char far   onBufer;              // on-chip XRAM
    unsigned code       cBufer = "Welcome";   // on-chip ROM
    
    Pointer1 = onBufer;                       // pointer to 0x01AABB
    Pointer2 = cBuffer;                       // pointer to 0xFFCCDD
    

    I suspect these are just typos, though. (In general, when posting code to the forum, it's a good idea to cut and paste to avoid introducing any differences by retyping the code.)

    From this line

    7402     MOV      A,#0x02                 // on-chip EEPROM area !!!
    


    I suspect what is really confusing you is the Keil tagging scheme. A far pointer is not a 24-bit address. It's a structured value with the first byte used as a tag byte to indicate the memory space (data, xdata, far, etc) and a 16-bit value that is the address in that memory space.

    The tag scheme is a bit unfortunate in that a tag value of 0 was used to mean "data" memory, not xdata. Then the tag for xdata is 1, and far memory is 2..7F. So, the tag value for all of the xdata/far memory is 1 higher than you would expect from a 3-byte address.

    Offset 0000H in xdata is represented as 010000H. Offset 0000H in the first segment of far data (the 64KB just beyond "xdata") is 020000H. But you probably want to think of that as "xdata address 010000H". If you want to think of addresses that way, then the far pointer representation is like a flat address, except that it's 10000H higher than you expect.

    See the FVAR and FARRAY macros in absacc.h. Also, see the comments in XBANKING.A51.

    ; R3 Value | Memory Type | Memory Class | Address Range                       *
    ; -----------------------+--------------+--------------------------           *
    ;    00    | data/idata  | DATA/IDATA   | I:0x00     .. I:0xFF                *
    ;    01    | xdata       | XDATA        | X:0x0000   .. X:0xFFFF              *
    ;  02..7F  | far         | HDATA        | X:0x010000 .. X:0x7E0000            *
    ;  81..FD  | far const   | HCONST       | C:0x800000 .. C:0xFC0000 (see note) *
    ;    FE    | pdata       | XDATA        | one 256-byte page in XDATA memory   *
    ;    FF    | code        | CODE         | C:0x0000   .. C:0xFFFF
    

  • Excuse, this mistake has turned out at creation of a question:
    Should be:

    unsigned char far onBufer[20];
    unsigned char xdata offBufer[20];
    unsigned char far EEBufer[20];

    Value of Pointer1 in "Hint" of Dedug windows is 0x01AABB. If R3 - memory type, then how to define simultaneously two types of far (EEPROM, on-chip XRAM).
    In function memcpy(Pointer1,Pointer1,20) disassembler check:

    C?CSTPTR:
    C:0x0DA0 BB0106 CJNE R3,#Test(0x01),C:0DA9 //if r3<>r1 is not HXDATA area
    C:0x0DA3 8982 MOV DP0L(0x82),R1
    C:0x0DA5 8A83 MOV DP0H(0x83),R2
    C:0x0DA7 F0 MOVX @DPTR,A
    C:0x0DA8 22 RET
    C:0x0DA9 5002 JNC C:0DAD
    C:0x0DAB F7 MOV @R1,A
    C:0x0DAC 22 RET
    C:0x0DAD BBFE02 CJNE R3,#CCAP4H(0xFE),C:0DB2
    C:0x0DB0 F3 MOVX @R1,A
    C:0x0DB1 22 RET
    C:0x0DB2 50FD JNC C:0DB1
    C:0x0DB4 020AD6 LJMP C?CSTXPTR(C:0AD6) // write to EEPROM or off-chip XRAM

  • Did you notice that the EEPROM variables are defined in a USER_CLASS.

    #pragma ORDER                      // keep variables in order of definition
    
    #pragma USERCLASS (HDATA = EEPROM) // use HDATA_EEPROM for E2PROM area
    
    #define DECLARE
    #include <eeprom.h>                // include all variables
    
    

  • OK, I have understood, it turns out, that memory and indexes are allocated as follows:

    +----------------+--------------+------------------------+--------------+-----------+
    |  Memory Type   | Memory Class |  Define in C language  | Address in C | R3 in ASM |
    +----------------+--------------+------------------------+--------------+-----------+
    | on-chip XDATA  |    HDATA     |         far            |  X:0x010000  |   0x02    |
    | off-chip XDATA |    XDATA     |         xdata          |  X:0x000000  |   0x01    |
    |    CODE        |    CODE      |         code           |  X:0x0000    |   0xFF    |
    |    EEPROM      | HDATA_EEPROM | far & (HDATA = EEPROM) |  C:0x0000    |   0x03    |
    +----------------+--------------+------------------------+--------------+-----------+
    * using standard files XBANKING.a51 and EEPROM.c
    


    There is another problem. In the menu "Options for Target" I choose "Memory Model = Lage: variables in XDATA". I have function in my program char Test (char value1, char *value2, char value3) in which parameters transferred through XDATA memory, but not through registers.
    XDATA memory is an off-chip. How to transfer parameters through on-chip XRAM?

  • There is no particular reason why on-chip XDATA has to be HDATA, while off-chip is XDATA.

    Presumably, you are looking at some specific case where this happened to be (or seem) convenient to whoever set it up?

  • I shall ask on another. I define variables as:

     char xdata A; // locate in off-chip XDATA
     char far B;   // locate in on-chip XDATA
    


    If the model of memory LARGE and a variable is defined as char C; , then where is placed a variable? It is necessary for me that in on-chip XDATA.

  • "It is necessary for me that in on-chip XDATA."

    If it is necessary, then just specify it explicitly.
    Simple.