|
|
View previous topic :: View next topic |
Author |
Message |
Oliver Guest
|
Compiler shares memory in isr and normal function calls |
Posted: Tue May 01, 2007 4:08 am |
|
|
We have been using the CCS C compiler for some time now (versions 3.x and just recently upgraded to 4.033). For some time now we have been struggling with a bug that the compiler seems to introduce, which we hoped would be fixed with the latest release. But not so.
The problem is as follows:
The compiler assumes that a variable exists for the duration of a procedure call (auto type qualifier). This works in a single threaded environment, assuming that nothing can happen in parallel. The compiler will automatically reuse memory locations, if e.g. two functions can never appear on the same calling stack. There seems to be one instance where this is not the case and which the compiler seems to miss – interrupt service routines. If an interrupt uses some ram (often even just a scratch area for a function it calls), then it seems that the compiler will randomly re-use that memory in a different context; even though the interrupt can be called at any time and pre-empt any process that may be using the “shared” memory.
We can show that this seems to be what is happening by looking at the symbol file for our application. E.g. here just a snippet:
710 ricerle_buffer_put.nY
710 ProcMain.nSuccess
nY is a parameter passed into the ricerle_buffer_put function, where nSuccess is a variable in the function ProcMain; the ricerle_buffer_put function is called from a timer interrupt service routine and ProcMain is on the normal calling stack. It is possible for the ProcMain function to be running, and then be interrupted by the timer which will change the value in address 710 to whatever nY needs to be and returns with nSuccess suddenly being something else.
Is there any way we can prevent the compiler from doing this? Is there a type qualifier missing, a compiler option that we should or shouldn’t be using. This seems to be a fundamental problem and I would be surprised if it hasn’t reared its head already.
I can use #locate to prevent variable used within isr from being shared - a bit tedious though. I'm not sure how to do this for parameters that are passed into functions that an isr may call (declaring a function as static or external seems to make no difference).
Typical build flags we use are:
+P +FH -D -J -Z +M -A -T +LYLST +STDOUT I+
Devices are exclusively PIC 18Fs.
Thank you in advance for any light you can shed on this matter. |
|
|
Guest
|
|
Posted: Tue May 01, 2007 6:59 am |
|
|
Just maybe . . .
Using HIGH_INTS with no high-priority interrupt can cause this.
I lost a lot of sleep over this one, until the guys at CCS found it for me.
I had copied a piece of code from another project (the HIGH_INTS part), but had not have any high-priority isr :(
Hope this helps
Ken |
|
|
Oliver Guest
|
not quite there yet |
Posted: Tue May 01, 2007 7:30 am |
|
|
Cheers Ken. unfortunatly, HIGH_INTs isn't declared in my case.
Here is something I'm trying though and would be great to get some feedback from someone in the know. Adding these two lines will give me a reserved area, but declare a qualifier that can be allocated into that area - the first part may not be required though:
#reserve 0x100:0x1FF
addressmod( isr_volatile,,,0x100,0x1FF );
I can then declare all my variables that are used in the isrs to be within this range (e.g. int8 isr_volatile nMyVar;). This seems to work (though can't check it easily as the symbol file doesn't output this range). It doesn't work for parameters passed to a function which is called in an ISR as the compiler, though given the small number of paramters that are actually in our app, I can easily just removed them. This still leaves the @SCRATCH areas and I'm not sure how dangerous they are if they overlap, or how I could allocate them to an un-shared memory region.
Any thoughts still very welcome. |
|
|
ljbeng
Joined: 10 Feb 2004 Posts: 205
|
|
Posted: Tue May 01, 2007 8:49 am |
|
|
I had a situation where the interrupt was doing some operations and going back to the main loop where my lcd would display a funny number for no reason. If I disabled the interrupt, the funny number went away. I ended up making the interrupt just a bit set and then exited and the functions I wanted occur in interrupt where just a subroutine called from the main loop
Code: | #int_TIMER0
TIMER0_isr(){
set_timer0(57203);// 1/300 baud interrupts
t1int = 1;
}
void t1_call(void){
//do t1 operations here
t1int = 0;
}
main(){
while(1){
if (t1int) t1_call();
}
} |
|
|
|
CCS
Joined: 31 Oct 2005 Posts: 8
|
CCS Technical Support |
Posted: Tue May 01, 2007 9:11 am |
|
|
Oliver,
CCS does not monitor this forum on a regular basis. Please do not post bug reports on the forum. All bug reports should be emailed directly to [email protected], in order for a CCS engineer to look into and resolve the issue in a future update. Please take a moment and email CCS Technical Support if you have not done so already. Thank you.
_________________ Custom Computer Services, Inc.
262-522-6500
PO Box 2452
Brookfield, WI 53008 |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|