compilation8051sdcc

How 8051 XDATA memory spaces are handled in pointers?


I am developing for the Cypress EZ-USB FX2LP which contains a 8051 core and I use SDCC for compilation.

I noticed that I can (sometimes?) omit the __xdata annotation for pointers and my firmware will still run fine even when using pointer to a XDATA region.

For example, it will compile and execute fine with the following declaration:

uint16_t crc16(const uint8_t *data, uint8_t len);

instead of

uint16_t crc16(__xdata const uint8_t *data, uint8_t len);

From what I understood, XDATA is 16-bit addressable while DATA is 8-bit addressable. Does the SDCC compiler automatically promote pointers to 16-bit when they could point to XDATA?


Solution

  • It is correct that pointers of a "generic" type don't have to have the same bit width as explicit "section" pointers. But compilers commonly don't promote pointers.

    As you revealed by a comment, your project uses the medium data model that allocates variables in the PDATA section.

    The PDATA section is identical with the XDATA section concerning the hardware, and it needs a 16-bit address. However, it is accessed by 8-bit pointers (R0 and R1 on processor level). The upper half of the address comes from the SFR P2. In its "normal" life, P2 is used to store the value for port 2. But if you connect external memory, the port P2 will be used for the upper bits necessary to address this memory, it is multiplexed. So the SFR is free for this usage.

    Note 1: AFAIR, you can even split the port, using less than 8 bits for the address memory, and keeping the leftover bits as port bits, if you don't use external CODE memory. If you use external CODE, all of port P2 will be used to output the upper half of the program counter. Be sure that you understand all implications!

    The initial value of P2 is 0xFF (for "all pins are inputs"), but the startup code of SDCC initializes it with 0x00. So by accident, you accessed the first 256 bytes in the external memory.

    To access other "pages" (this is the "P" in PDATA, it means "paged data") you simply write their upper address bits into P2 before reading or writing.

    Note 2: Some library functions might be smart enough to change P2 if they cross the page boundary. Before using this, make sure it is the case!