Microchip's XC8 Linker doesn't recognize some custom section names

Slightly related to this one: https://softwareengineering.stackexchange.com/questions/254734/microchip-xc8-how-to-pack-code-against-an-upper-limit

I can relocate code just fine, but I'm having some trouble with constants:

Example code:

#include <xc.h>

unsigned char buffer[16];

__section("SecConst1") const unsigned char constants1[] = "const1";
__section("SecConst2") const unsigned char constants2[] = "const2";
//__section("SecText1") const unsigned char constants1[] = "const1";
//__section("SecText2") const unsigned char constants2[] = "const2";

__section("SecText1") void fill_buffer1(void)
{
unsigned char i = sizeof(constants1);
do
{
i--;
buffer[i] = constants1[i];
}
while(i);
}

__section("SecText2") void fill_buffer2(void)
{
unsigned char i = sizeof(constants2);
do
{
i--;
buffer[i] = constants2[i];
}
while(i);
}

__section("SecText") void main(void)
{
while(1)
{
fill_buffer1();
fill_buffer2();
}
}


-L-aClass1=1200h-17FFh,1800h-1FFDh -L-dClass1=2 -L-pSecText1=Class1 -L-pSecText2=Class1 -L-pSecText=Class1


If I build it with no linker options, or if I only specify the functions (as above), it builds with no errors and I see all of the section names in the map file, so I know they're all there. But if I specify where to place a constant, the build fails because that section name was not defined. If I switch to the other set of constant declarations (swap the comments), then those names are suddenly not defined.

I feel that this is a bug in the toolchain, and I've told Microchip about it via their support site, but does anyone know of a good workaround?

I'd rather not specify the address of every constant directly in the source code because the complete project has a lot of them and they can all change size and contents from one version to the next.

I'm using a PIC16F1454, but I'm pretty sure that doesn't matter for this problem.

I submitted a ticket to Microchip's tech support, and after a few days, they found that

 #pragma psect <default_section>=<new_section>


would work for constants just like it's supposed to. They've made a note of the problem and said they'd fix it in the next release so either that or __section("new_section") will also work for constants.

I don't like the #pragma because you have to know the default_section (can be found by compiling successfully without the directive and searching the map file) and because it affects the entire source file, while __section() only affects the one item that it's used with. But for my application, it works.

This stackoverflow question Declare a specific address for a string in MPLAB XC8 Microchip complier contains an answer:

Rather than tell the linker, for example -L-pappnfo=0x78E0

There is syntax to directly specify the location of a variable, for example:

const unsigned char _app_nfo[31] @ 0x78E0 = {"V0.0 No        - 05/12/12"};


However, this doesn't sound like what you want to do. You say:

I'd rather not specify the address of every constant directly in the source code because the complete project has a lot of them and they can all change size and contents from one version to the next.

Section "3.4.3.3 HOW DO I PLACE VARIABLES IN PROGRAM MEMORY?" of the MPLAB® XC8 C Compiler User’s Guide says:

The const qualifier implies that the qualified variable is read only. As a consequence of this, any variables (except for auto variables or function parameters) qualified const are placed in program memory, thus freeing valuable data RAM

So it looks like all const variables are put in program space automatically, which I think is what you want.

• So far, so good, but I want to put them between 1200h and 1FFDh in program space, not just anywhere in program space. That's the part that doesn't work. Sep 18, 2014 at 0:45
• Okay, sorry. I find PIC's heavy going, and the XC8 compiler manual is a bit weird. I am much more familiar with AVR, ARM, Freescale, ... Sep 18, 2014 at 1:22