How to access entire 512 bytes RAM of AT89C51RC in Keil C

Discussion in 'Embedded Systems and Microcontrollers' started by sinoj, Jun 4, 2007.

  1. sinoj

    Thread Starter New Member

    Jun 4, 2007
    For an application I require an unsigned char array of size 450. I am almost(not at all) familiar with AT89C51. Since 89C51 has only 128 bytes of onchip RAM I selected AT89C51RC which has 512 bytes of onchip RAM.I am using Keil C compiler. When I compiled by defining 'unsigned char arr[450]' in my application, it resulted in an output message 'error c249: DATA: SEGMENT TOO LARGE' and could not create th target. In the 'options for Target 'Target1'' menu 'Memory Model: small: all variables in DATA' was selected.

    Also when I selected AT89C51RC in the 'options for Target 'Target1'' menu, the short description regarding the currently selected Target Device was found mismatching with the original AT89C51RC datasheet information(for example: 1K XRAM). But when I just selected AT87F51RC the short description was found matching with the original datasheet information of AT89C51RC. Why so?. Are AT89C51RC and AT87F51RC having the same memory model?. What is the physical and logical difference between onchip RAM and XRAM?. How XRAM accessed using Keil?.

    How can I use the entire 512 bytes of onchip RAM of AT89C51RC?Do I need to set/clear 'EXTRAM' bit in the SFR 'AUXR' manually(in the program) to access the remaining 256 bytes? Or will the compiler do this automatically? No external RAM is used in this application. Kindly help me to access complete 512 bytes onchip RAM of AT89C51RC using Keil C compiler with minimum complexity.
  2. Papabravo


    Feb 24, 2006
    You are not the first person to be confused by the archtectural quirks of the 8051 architecture which was never intended to be the target of a C compiler.

    DATA memory refers to the first 128 bytes of the internal register space, with addresses 0x00 to 0x7F.
    IDATA memory refers to indirectly addressable RAM in the internal register space, with addresses 0x80 to 0xFF.
    SFR's are directly addressable registers that have an address space that overlaps IDATA, with addresses 0x80 to 0xFF
    XDATA is a 64K memory space, with addresses 0x0000 to 0xFFFF which in the ORIGINAL architecture was always supposed to be external to the chip and accessible with the MOVX instructions. Those instructions activated the WR* and RD* signals which are the alternate functions of P3.6 and P3.7
    SOME implementations put additional RAM on the chip with the processor core, but it still must be accessed as if it were off chip., with the MOVX instructions.
    The last memory space, CODE memory, is the code space which has addresses 0x0000 to 0xFFFF. This memory can only be read with the MOVC instruction. Instructions can be fetched using the PSEN* signal if the code space is external to the processor.

    The only possible way for you to have the array that you want is to place it in XDATA memory. The compiler should have a reserved word for that purpose.
    Code ( (Unknown Language)):
    2. xdata unsigned char myarray[450] ;
    for example
  3. Arm_n_Legs

    Active Member

    Mar 7, 2007
    unsigned xdata char *ptr;

    ptr = 0x38; // Example u wanna write 0x01 to xdata location 0x38
    *ptr = 0x01;
  4. Papabravo


    Feb 24, 2006
    No, that is not correct. With pointers you must understand that where they are allocated and where they point to are two different things. In your example it is the pointer itself which is located in xdata. Where it points is ambiguous. It could point to DATA, or it could point to XDATA, we simply don't know because there are two locations with the addresss 0x38.
  5. Arm_n_Legs

    Active Member

    Mar 7, 2007
    I tried a simple C program below and check the assembler codes generated by the Keil Compiler. The pointer declared with xdata seems to put data back to the xdata location. Cheers~

    unsigned char xdata *xPtr;
    unsigned char idata *iPtr;
    unsigned char code *codePtr;
    unsigned char x;

    void main()
    xPtr = 0x1234;
    *xPtr = 0x67;
    *iPtr = 0x89;
    codePtr = 0x100;
    x = *codePtr;

    Codes generated by Keil

    0000 750012 R MOV xPtr,#012H
    0003 750034 R MOV xPtr+01H,#034H
    0006 850082 R MOV DPL,xPtr+01H
    0009 850083 R MOV DPH,xPtr
    000C 7467 MOV A,#067H
    000E F0 MOVX @DPTR,A

    000F 750060 R MOV iPtr,#060H
    0012 A800 R MOV R0,iPtr
    0014 7689 MOV @R0,#089H

    0016 750001 R MOV codePtr,#01H
    0019 750000 R MOV codePtr+01H,#00H
    001C 850082 R MOV DPL,codePtr+01H
    001F 850083 R MOV DPH,codePtr
    0022 E4 CLR A
    0023 93 MOVC A,@A+DPTR
  6. Papabravo


    Feb 24, 2006
    So it is clear from the code that was generated that xPtr is located in DATA memory and points to XDATA memory.

    It is equally clear that iPtr is located in data memory and that it points to IDATA.

    Lastly codePtr is located in DATA memory and points to CODE Memory.

    Congratulations on running this little experiment and showing us the results. Thank you Masked Man.
  7. idris.bloom

    New Member

    May 4, 2012
    Sir how we differentiate b/w internal on chip xdata and off chip ram xdata..
    On chip 768 bytes of ram and off chip ram address. Also what Memory-Specific Pointers.
  8. Papabravo


    Feb 24, 2006
    For any 8051 variant you have to RTFDS. It will tell you where the on-chip XDATA begins and ends as well as where the off-chip XDATA begins and ends. We must be getting to the point where 64K of on-chip XDATA is not a very big challenge. Then there will be no external XDATA because it will all be on the silicon ... so to speak.