--- In l..., "viskr" wrote: >
>
> I think I've resolved the IAP problem and its due to a GCC "feature", > maybe a bug.
>
> Anyway if you call IAP the way it is specified in the doc's, it works > sometimes-
>
> #define iap_entry ((IAP) 0x7FFFFFF1) // IAP entry point
>
> ...
>
> iap.cmd = 50; // IAP Command:
> Prepare Sectors for Write
> iap.par[0] = GET_SECNUM(flash_addr);// start sector
> iap.par[1] = iap.par[0]; // end Sector
> iap_entry (&iap, results); // call IAP
This (recommended) syntax looks questionable to me.
Have you tried something like:
typedef void iap_call_type(int *args, int *results);
If it's done like this, the code that makes the call is always using
the correct type (pointer to a function): the forced typecast is
done when the address of that function is assigned.
Note that if "const" is used in declaring the function pointer,
there should be no RAM storage overhead for the pointer.
The alternative way (recommended by Philips) means the forced
typecast is doen at the location of the call. I'm not sure whether
the compiler's behaviour (in getting it "wrong") is "correct" or
not: you'd probably need the language definition in front of you to
figure that one out. I know we've used the syntax I've suggested on
several compilers (including GCC for ARM7) with no problems.
Brendan.
Reply by viskr●July 25, 20062006-07-25
I think I've resolved the IAP problem and its due to a GCC "feature",
maybe a bug.
Anyway if you call IAP the way it is specified in the doc's, it works
sometimes-
#define iap_entry ((IAP) 0x7FFFFFF1) // IAP entry point
...
iap.cmd = 50; // IAP Command:
Prepare Sectors for Write
iap.par[0] = GET_SECNUM(flash_addr);// start sector
iap.par[1] = iap.par[0]; // end Sector
iap_entry (&iap, results); // call IAP function
if (results[0]){
goto exit; // an error occured?
}
The problem is this works sometimes, depending on the compiler and the
phase of the moon.
GCC seems to arbitrarily choose registers to use to do this call AND
it assumes that iap_entry() will save those registers.
BUT as it is a vector to a Philips routine IAP, and it does not
guarantee registers to be saved. So sometimes it works and sometimes not.
the proper way to call it is
#define iap_entry ((IAP) 0x7FFFFFF1) // IAP entry point
void iap_call(int *iap, int *results) {
iap_entry (iap, results); // call IAP function
}
...
iap.cmd = 50; // IAP Command:
Prepare Sectors for Write
iap.par[0] = GET_SECNUM(flash_addr);// start sector
iap.par[1] = iap.par[0]; // end Sector
iap_call (&iap, results); // call IAP function
if (results[0]){
goto exit; // an error occured?
}