Pololu Robotics & Electronics
Menu
My account Comments or questions? About Pololu Contact Ordering information Distributors

XDATA, PDATA, CODE, and function parameters


#1

I got a few Wixels to replace a old project that used to run on some ZigBee AVRs. I’m extremely familiar with GCC for AVR and ARM but 8051 is not something I work with often.

I am reading through SDCC’s manual explaining XDATA, PDATA, and CODE. So far I know the following

  • PDATA starts at the same address as XDATA except only up to one page before needing a write to a SFR to change the page
  • PDATA is 256 bytes long
  • CC2511 is a medium memory model device, so stack default to PDATA
  • SDCC with place parameters on external memory by default for medium memory model devices, unsure if they mean XDATA or PDATA

My questions are:

  • what is the behavior of the compiler if I pass a buffer declared as XDATA into a function that expects a char pointer without any memory space attributes? will standard memcpy or strcpy care? is the memory paging for PDATA automatic?
  • is the compiler smart enough to put constant strings into CODE for me? Or is each printf going to chew up RAM? if so, is there a way to avoid this? AVR GCC has the PSTR macro to help with this.
  • is it safe to modify the makefile to just say --model-large and avoid the headache of putting XDATA on everything?

and one more… say I make a lookup table like this

#define KRF_HOP_MAP 75, 163, 250, 43, 13, 184, 128, 210
static const uint8_t CODE krf_chanMap[] = { KRF_HOP_MAP };

is the data stored in flash or is the data stored in RAM?

Thanks


#2

Hello.

Thank you for your interest in the Wixel.

The CC2511F32 is not a medium memory model device. The memory model is just an option you can pass to SDCC to control how memory is used, and it is not inherent to the microcontroller.

The Wixel SDK uses the “medium” memory model. This means that variables (including local variables, global variables, and function parameters) are placed in PDATA by default.

If you change the memory model to “large”, variables would be stored in XDATA by default. It would take more instructions to access those variables, so your program would be bigger and slower. I tried changing the memory model to “large” just now and I noticed that the usb_serial app increased in size by about 10%. If you want to change the memory model, besides changing the Makefile, you would need to recompile xpage.rel and change delay.s. There might be other issues with changing the memory model; we have not tested it much.

We’ve found that it works pretty well to just put variables that are larger than a few bytes into XDATA, and let almost everything else be stored in PDATA. If you ever run out of space in PDATA, SDCC will let you know, and you can move some variables to XDATA.

If you use a function declared as void foo(unsigned char *);, with no memory attributes, then that function will expect to receive SDCC’s generic pointer. A generic pointer is three bytes, and one of the bytes is used to specify what memory space the pointer is pointing to.

SDCC’s generic pointers are wasteful to use on the CC2511, because the CC2511 maps all of its flash and RAM into a single unified memory space. Everything in flash and RAM can be accessed as if it were in XDATA. This mapping is described in the “Memory Map” section of the CC2511 datasheet. If you are writing a function that takes a pointer, I would recommend putting the XDATA qualifier on the pointer: void foo(unsigned char XDATA *). Then the pointer argument will only be 2 bytes, and it will be more efficient to work with it, and it can still point to anything.

Yes, string literals in your code like "hello world" will be stored in code space (flash).

Yes, if you define an array with either CODE or const qualifiers, it will be stored in code space (flash).

You can check the output of SDCC to see where it is storing your variables. The “.map” file shows the addresses and memory space of every variable in your program. The “.lst” files show the assembly code SDCC has generated to access your variables in the corresponding “.c” file, so you can check to see how the variables are being accessed.

–David


#3

Thank you, that was extremely useful information

This kills code portability a bit though, oh well