• AVR Freaks

AnsweredHot!choose custom address for an object

Page: < 12 Showing page 2 of 2
Author
Antipodean
Super Member
  • Total Posts : 1876
  • Reward points : 0
  • Joined: 2008/12/09 10:19:08
  • Location: Didcot, United Kingdom
  • Status: offline
Re: choose custom address for an object 2020/07/30 06:57:29 (permalink)
+2 (2)
crosland
As I've said before, it was very easy in C18. I used function pointers at a known addresses. If the bootloader or the app were modified then everything still worked as the function pointers remained at their known addresses.

Ah, yes, the good old jump table as used in CP/M bios and OS modules. Smile: Smile

Do not use my alias in your message body when replying, your message will disappear ...

Alan
#21
visenri
Starting Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2017/10/25 15:30:29
  • Location: 0
  • Status: offline
Re: choose custom address for an object 2020/07/30 16:38:27 (permalink)
+1 (1)
pajuhesh80
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: mad), so, I'll resume it:
 
This is where you define the address and function prototype.
#ifndef FOO_H
#define FOO_H

#include <xc.h>
#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:
#include <xc.h>
#include "foo.h"

void main(void) 
{
    if(sharedFoo(11) == 13)
    {
        NOP();
    }
    while(1){}
}

 
This also works:
#include <xc.h>
#include "foo.h"

void main(void) 
{
    int (* pSharedFoo)(int) = sharedFoo;
    if(pSharedFoo(10) == 12)
    {
        NOP();
    }
    while(1){}
}

 
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.
 
 
#22
Page: < 12 Showing page 2 of 2
Jump to:
© 2020 APG vNext Commercial Version 4.5