I wrote my bootloader and used __reentrant and fixed address for shared functions but I can't call them.
I used some strange pointers and even asm("goto 0xABC") and asm("call 0xABC"). Pointers are compiler but have no effect. Inline assemblies stop normal code execution but still not working.
I checked map file. All functions are placed where I set.
I explained this with a lot of detail (and disassembly outputs), but the f*u*c*k*i*n*g forum ruined all my text with an access denied message (normally I copy it before posting, but not this timemad:
), so, I'll resume it:
This is where you define the address and function prototype.
#define SHARED_FOO_ADDRESS 0xDD0
__reentrant extern int sharedFoo(int value) __at(SHARED_FOO_ADDRESS);
#endif /* FOO_H */
No need to use function pointers, this works for me, it calls address 0xDD0:
if(sharedFoo(11) == 13)
This also works:
int (* pSharedFoo)(int) = sharedFoo;
if(pSharedFoo(10) == 12)
Look at the dissasembly and simulate them in MPLABX and you'll see both examples work.
IMHO this should work, but does not, as you've already seen (anyway as we all know casting numbers to pointers is not the best practice), we are in an undefined behavior field:
int (* pSharedFoo)(int) = (int (*)(int))(SHARED_FOO_ADDRESS);
ONE MORE IMPORTANT TRAP FOR YOUNG PLAYERS:
Functions that use the reentrant model will pass values back to the calling function via
btemp variables, provided the value is 4 bytes or less in size. The W register will be
used to return byte-sized values for enhanced mid-range device functions that are not
variadic. For objects larger than 4 bytes in size, they are returned on the stack.
Reentrant PIC18 functions that return a bit do so using bit #0 in btemp0; other
devices use the carry bit in the STATUS register.
- No problems with parameters.
- Potential problems with return values smaller than 5 bytes, because as far as I know btemp address is not guaranteed to be always at the same address. So use global variables with absolute addresses or variables > 4 bytes.