1

I came across this problem twice in my project and the last time I used a kind of dirty solution.

Platform: PIC18F87J60, XC8 v1.12

I'm trying to use function pointers to point to functions that possibly reside in the upper halve of my ROM (>= 0x10000). This means that the pointer itself needs to be 17-bits or bigger (up to 20) to be able to address such a function.

This is the relevant code snippet (simplyfied):

void test(void) @ 0x1C000
{
    printf("function pointer called!\r\n");
}

void main(void) {
    void (*testPointer) (void) = &test;
    //Now testPointer contains 0x0C000
    (*testPointer)(); //Doesn't call test. Instead it jumps to 0x0C000
}

What happens is that test never actually gets called. When I use the debugger (PICKIT 3) I can see that the value in testPointer is 0x0C000. It just seems that the address in the pointer is rounded down to just 16-bits max and this always happens. But when I place test() somewhere below 0x10000 everything works fine because then the pointer just needs to be max 16 bits.

When I read back the program from the device test() really is placed at 0x1C000 so that is not the problem, the code is there.

The last time I solved the situation by casting a literal long to a pointer and that worked but its dirty and now I want to avoid it.

Does anyone recognize the problem? Is this a compiler bug? If so, does Microchip already know about this? Any clean work-arounds? Does the XC8 compiler support 20-bit const pointers at all?

Edit: fixed typo in code above &testPointer(); --> (*testPointer()); (no, this was not causing my problem)

Jupiter
  • 1,421
  • 2
  • 12
  • 31
  • 1
    That pic has 20-bit addressing. How much memory is wired-up to it? – trojanfoe Aug 13 '13 at 14:12
  • @trojanfoe woops, 20 is what I mean. For clarity: I am talking about the address range 0-1FFFF. No external memory chips, I using only the built-in ROM. Edited it. – Jupiter Aug 13 '13 at 14:21
  • And how large is the memory? – trojanfoe Aug 13 '13 at 14:23
  • 1
    Have you tried declaring your pointer as `far rom void (*testPointer) (void) = &test;` ? – Michael Aug 13 '13 at 14:23
  • its 16K of ROM. Last address is 0x1FFFF. – Jupiter Aug 13 '13 at 14:24
  • @Michael Adding the keyword far solved the problem. rom isn't recognized by XC8, I'd have to use const for that but the compiler is smart enough that it doesn't need const (apparently). Add an answer formally and I'll mark it. Thanks for all the suggestions guys. – Jupiter Aug 13 '13 at 15:00

1 Answers1

2

The MPLAB C18 Compiler User's Guide lists a few extra storage qualifiers that appear to be relevant to your use-case:

near/far Program Memory Objects
The far qualifier is used to denote that a variable that is located in program memory can be found anywhere in program memory, or, if a pointer, that it can access up to and beyond 64K of program memory space.

ram/rom Qualifiers
The rom qualifier denotes that the object is located in program memory, whereas the ram qualifier denotes that the object is located in data memory.

Later on, the manual shows an example of creating "a function pointer that can access up to a beyond 64K of program memory space":

far rom void (*fp) (void);

The XC8 manual is less clear about the function of the far qualifier, but still lists it, which strongly suggests that it still is recognized by the newer compilers.

Michael
  • 57,169
  • 9
  • 80
  • 125
  • I am not sure if I am correct, but AFAIR the use of `far` pointers is not unproblematic. There might be a need to adjust the highest byte of some pointer register if the proncipal compilation happened with `near`. But as it is 3 years ago that I worked with PIC, I may be wrong. – glglgl Aug 13 '13 at 17:09