# XC8 - constant ROM allocation for PIC12F1501

I have troubles with const memory allocation with XC8. I try to do this:

const unsigned char patterns[12] = {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
};


but I get this error: "can't find 0xC words (0xc withtotal) for psect "stringtext" in class "STRCODE" (largest unused contiguous range 0x57)". That's strange because space needed is less than space available (contiguous). In the user guide:

stringtext psect must be linked within the first half of each program memory page

I'm not quite sure why. I guess the compiler fills all the first halves before trying to find space for constants. Can anyway advice me how to give a hint to the compiler where to locate the constants section? Or Is there any other way to workaround this problem.

I'm using MPLAB because I find it difficult to use MPLAB X.

P.S. Keep in mind that the ROM is almost full - only 0x57 bytes left. It's well fragmented in small sections in order to fit better.

stringtext psect must be linked within the first half of each program memory page

This restriction only applies to 'baseline' PICs such as the 12C509, which can only call subroutines in the first half of each 256 byte page. Why does this matter? In older PICs there are no instructions for reading data from ROM, so a method was developed called Table Read, in which data arrays are stored as a sequence of RETLW instructions (return from subroutine with literal in working register).

The 12F1501 is one of the new generation of enhanced mid range PICs which can use their index register to read the ROM directly, so it has no restrictions on placement of data in the ROM. However the XC8 compiler still insists on trying to align stringtext on page boundaries, and refuses to put it in page zero even when only a few bytes of initialization code are 'in the way'! This may result in running out of space even though you have a significant amount of 'free' ROM.

The easiest way around this problem is to simply force your arrays into a code section - then the compiler should align them on word boundaries with no gaps (like normal code). Just add a section specifier to each array definition, like this:-

const __section("mystringtext") unsigned char patterns[12] = {
0, 0, 0, 0,
0, 0, 0, 0,
0, 0, 0, 0,
};


There are multiple ways the CPU can access memory. Some instructions (which I believe are the default) can only access memory within a certain range of where the instruction executes from (they are basically relative to that instruction).

Thus it can be critical where data is allocated in order for these instructions to access it.

There is a special keyword __far that tells the compiler that this variable should be accessed from further away than normal. Qualifying your array with that keyword should allow it to work, although at reduced efficiency than otherwise. As the manual says:

The __far qualifier can be used to indicate that variables or functions are located in ‘far memory’. Exactly what constitutes far memory is dependent on the target device, but it is typically memory that requires more complex code to access. Expressions involving far-qualified objects usually generate slower and larger code.

And it goes on to site some examples:

__far int serialNo;
__far int ext_getCond(int selector);


Note that __far, as the examples show, can also be used on functions if they should be needed to be called from further away in memory than a relative call can resolve.