views:

514

answers:

3

The Microchip PIC MPLAB (MCC18) compiler segments its memory into 256 chunks ( 0x100 ).

How can I create an array larger than 256 bytes?

char buffer[256];

Just to get to 256 I needed to make a seperate segment with a #pragma

#pragma udata segment_name
char buffer[256];
#pragma udata

So I can either force MCC18 to let allocate a larger buffer? or combine two memory segments?

+2  A: 

Perhaps someone with more knowledge will prove me wrong, but I don't think it's possible to do what you want. If the memory in your device is divided into segments of 256 bytes, then you can't have an array spanning them, AFAIK. If you did, it would have to jump through all sorts of hoops to let you treat the array as contiguous memory -- it would have to check each index you use to figure out which segment it should be in, then compute the offset and access it, or if you're accessing the array using pointer arithmetic, it must figure out what you're trying to access, which may be non-obvious or even unknown at compile time. I don't think it has a single memory model that it can use for all circumstances because of the way some memory locations are common across banks (I think the program counter is one such location), etc. I'm speaking largely from a knowledge of the typical PIC architecture and some experience with third-party C compilers. I don't have much experience with MPLAB itself, so take my answer with a grain of salt.

It may be possible for you to get around the restriction by allocating an array of pointers and then initializing each pointer to a new instance of whatever data type you want to store in it (I'm assuming a struct or something larger than a pointer), as this will not require the memory to be contiguous. Dynamic memory allocation on PICs is expensive, however, so this may not be a good option for you.

rmeador
It might be if there is some "FAR" pointer concept.
Marco van de Voort
+1  A: 

http://forum.microchip.com/printable.aspx?m=39357 (from the Microchip forums, which may be a better place to ask your question)

switchmode
Your right Microchip forums are a better place to ask this type of question. I'm just testing SO to see if people will answer embedded questions ( not just C# ).
Justin Tanner
+3  A: 

Pasting answer from:

http://forum.microchip.com/printable.aspx?m=39357

Just in case it goes away.

In Three Easy Steps Step 1: Assign the variable into a named section in source code:

#pragma udata big_scn
char big_array[0x180];
#pragma udata

Step 2: Create the larger region in the linker script: Before:

DATABANK NAME=gpr3 START=0x300 END=0x3FF
DATABANK NAME=gpr4 START=0x400 END=0x4FF

After:

DATABANK NAME=big_scn START=0x300 END=0x47F PROTECTED
DATABANK NAME=gpr4    START=0x480 END=0x4FF
SECTION  NAME=big_scn RAM=big_scn

Step 3: Reference only through a pointer:

char *big_array_ptr = &big_array[0];
big_array_ptr[0x100] = 5;
while( big_array_ptr[x] != 20 )

NOTE: I believe you can still reference the array directly instead of using a pointer. Seems to work for me.

The same information can be found in the following document:

MPLAB C18 C Compiler Getting Started Guide

Page 104.

Justin Tanner
Thank you for putting the solution instead of just a link that can die.
Robert
Note that if you do stuff like this, using the paid C18 compiler instead of the student one becomes more important. It can under circumstances optimize away bankloading
Marco van de Voort