Coding and general discussion relating to the compiler
Moderators: David Barker, Jerry Messina
-
Gordon_h
- Posts: 55
- Joined: Fri Apr 06, 2007 8:55 pm
- Location: Boulder, Colorado
Post
by Gordon_h » Tue Jun 16, 2009 4:14 pm
I have a prioritized interrupt system, and have been working on a USART receive routine. The trouble is that when I put the code in an event, when the program returns after the event, one of my variables has been changed. I assume this is due to not SAVEing something critical, but I am not sure what. If I do not use an EVENT, and put all the code in the interrupt service routine, it all runs fine. Here is the code, with everything in the ISR:
Code: Select all
If (RCIE=1) And (RCIF=1) Then ' USART receive interrupt code
' aISRTXRX.FOnRxEvent() ' commented out for test
High(oSpare3)
c=DataChar
newChar=c
serFlag=1 ' Invoke serial processor
If Overrun Then
CREN = 0 ' Disable continuous receive
CREN = 1 ' Enable continous receive
EndIf
If serFlag=1 Then
Toggle(oSpare3)
EndIf
RCIF=0
EndIf
If I move everything before the "If serFlag..." statement out and into the event, then I do not see my scope test point toggle. So it appears that even though serFlag is set to 1 in the event, by the time it gets back to the ISR, it has been reset to 0. This is a low priority interrupt, I have a high priority one runing as well as two other low priority ones. I am guessing that maybe I am not SAVEing something critical, and that another interrupt is messing with my variable. Question is, how to tell? I am saving 0,PRODL,PRODH in the low priority, and FSR0,PRODL in this high priority. The Help file says to look at the ASM listing to see what is being touched, this is a little vague, I am not really sure what to look for in there.
Any thoughts on what can go wrong returning from an event would be much appreciated. Otherwise, I guess I'll live without the event.
Gordon
-
Jerry Messina
- Swordfish Developer
- Posts: 1469
- Joined: Fri Jan 30, 2009 6:27 pm
- Location: US
Post
by Jerry Messina » Sat Jun 20, 2009 11:51 am
Gordon,
David has a discussion somewhere of the naming convention used,
but basically vars named "SB_" are the system vars, "Fn_" are on the stack-frame
(locals and temps), while "Mn_" are the module-level statics.
The Mn_ static vars are safe, but the Fn_ vars can be reused by the compiler
at any time (this is the stack frame recycling). The exception to this is
local variables declared in an event...they're named Fn_, but not reused,
as events get their own stack frame.
If you think things are getting hosed up, follow the flow through the isr, event, and any sub calls
paying attention to accesses to variables named Fn_ (look at the actual memory location used,
as Fn_ variables can overlay each other).
When everything's coded inline in the isr, SF does a good job of
tracking the usage of the Fn_ vars. Once you start using events
and subroutine calls, it's easy to get into trouble, especially if
the compiler has to use temp vars to evaluate a "complex" expression.
SAVEing doesn't help here. I use the same structure as you, and in
most cases I don't even bother using SAVE/RESTORE, it's usually
a lot less overhead to just make copies of what needs to be preserved,
but it does take a bit of investigation (and I'm very careful of how I code
what's in the routines called by the isr).
Good luck.
Jerry