Context Saving

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Context Saving

Post by Steven » Thu Sep 04, 2008 6:42 pm

Hello All,

I am working on a GPS receiving routine, based on the NMEA module written by Dave on the wiki. However, I've modified it significantly and am now having problems with the interrupt. At intervals, text on my GLCD gets corrupted and I'm assuming that it is because I have not context-saved someting in the interrupt. I've tried all things I can think of and looked through the ASM, but cannot spot what I've missed. I would be extremely grateful if anyone else could help. I'm using a 18F4620.

Basic code:

Code: Select all

Interrupt OnNMEAData()
   Dim Data As Char
   Dim WREGHold, BSRHold As Byte

   // If a byte receive has triggered the interrupt, then context save
   // FSR0, FSR1, INF0, INDF1 and process the data byte...
   BSRHold = BSR
   WREGHold = WREG
   Save(0, INDF0, INDF1, STATUS, PRODL, PRODH, TABLEPTR, TABLAT)
   
   
   If PIR1.5 = 1 Then
                                        
      PIE1.5 = 0
      Data = RCREG 

         // start reading a sentence
         If Data = "$" Then
            FReadingSentence = True
            FIndexIn = 0            
         EndIf

         // are we reading a sentence? if so, set the buffer data...   
         If FReadingSentence Then 
            If false Then'(FIndexIn = 3 And Data <> "G") Or (FIndexIn = 4 And Data <> "G") Or (FIndexIn = 5 And Data <> "A") Then
               FReadingSentence = False
            Else
               If Data < " " Then
               // if end-of-sentence <CR><LF> - terminate sentence reading...
                  FReadingSentence = False
                  If Not SentenceLocked Then
                     // copy the NMEA line stored in the buffer into Sentence
                     FSR0 = @Sentence
                     FSR1 = @FBuffer
                     While FIndexIn > 0
                        POSTINC0 = POSTINC1
                        Dec(FIndexIn)   
                     Wend 
                     INDF0 = 0   // add end of string terminator
                     NewSentence = True
                  EndIf
               Else
                  // set buffer data    
                  If FIndexIn < NMEABufferSize Then
                     FSR0 = @FBuffer
                     Inc(FSR0, FIndexIn)
                     INDF0 = Data 
                     Inc(FIndexIn)
                  Else
                     FReadingSentence = False                       
                  EndIf   
               EndIf
            EndIf                 
         EndIf   
      
      PIE1.5 = 1
   EndIf
   
   Restore
   WREG = WREGHold
   BSR = BSRHold 
      
End Interrupt
ASM:

Code: Select all

ISR_ONNMEADATA_0
        MOVLB 0
?I002486_F022_000079_P000472 ; L#MK BSRHOLD = BSR
        MOVFF BSR,F684_U08
?I002487_F022_000080_P000472 ; L#MK WREGHOLD = WREG
        MOVLB 2
        MOVWF F683_U08
        MOVFF INDF0,F685_U08
        MOVFF INDF1,F686_U08
        MOVFF STATUS,F687_U08
        MOVFF PRODL,F688_U08
        MOVFF PRODH,F689_U08
        MOVFF _TBLPTRL#M0_U16H,F690_U16H
        MOVFF _TBLPTRL#M0_U16,F690_U16
        MOVFF TABLAT,F692_U08
        MOVFF FSR0L,F693_U08
        MOVFF FSR0H,F694_U08
        MOVFF FSR1L,F695_U08
        MOVFF FSR1H,F696_U08
        LFSR 0,F697_U200
        CLRF FSR1L,0
        CLRF FSR1H,0
        MOVLW 25
        MOVFF POSTINC1,POSTINC0
        DECFSZ WREG,1,0
        BRA $ - 6
?I002488_F022_000084_P000472 ; L#MK IF PIR1.5 = 1 THEN
        MOVLB 0
        BTFSS PIR1,5,0
        BRA ENDIF_275
?I002489_F022_000086_P000472 ; L#MK PIE1.5 = 0
        BCF PIE1,5,0
?I002490_F022_000087_P000472 ; L#MK DATA = RCREG
        MOVFF RCREG,F682_U08
?I002491_F022_000090_P000472 ; L#MK IF DATA = "$" THEN
        MOVLW 36
        MOVLB 2
        SUBWF F682_U08,0
        MOVLB 0
        BNZ ENDIF_276
?I002492_F022_000091_P000472 ; L#MK FREADINGSENTENCE = TRUE
        MOVLB 5
        BSF M716_U01,0
?I002493_F022_000092_P000472 ; L#MK FINDEXIN = 0
        MOVLB 6
        CLRF M797_U08
ENDIF_276
        MOVLB 0
?I002494_F022_000096_P000472 ; L#MK IF FREADINGSENTENCE THEN
        BCF STATUS,3,0
        MOVLB 5
        BTFSS M716_U01,0
        BSF STATUS,3,0
        MOVLB 0
        BOV ENDIF_277
?I002495_F022_000100_P000472 ; L#MK IF DATA < " " THEN
        MOVLW 32
        MOVLB 2
        SUBWF F682_U08,0
        MOVLB 0
        BC FALSE_168
?I002496_F022_000102_P000472 ; L#MK FREADINGSENTENCE = FALSE
        MOVLB 5
        BCF M716_U01,0
?I002497_F022_000103_P000472 ; L#MK IF NOT SENTENCELOCKED THEN
        BCF STATUS,3,0
        BTFSC M716_U01,3
        BSF STATUS,3,0
        MOVLB 0
        BOV ENDIF_280
?I002498_F022_000105_P000472 ; L#MK FSR0 = @SENTENCE
        LFSR 0,M811_U648
?I002499_F022_000106_P000472 ; L#MK FSR1 = @FBUFFER
        LFSR 1,M717_U640
?I002500_F022_000107_P000472 ; L#MK WHILE FINDEXIN > 0
WHILE_25
        MOVLB 6
        MOVF M797_U08,1
        MOVLB 0
        BZ FALSE_169
?I002501_F022_000108_P000472 ; L#MK POSTINC0 = POSTINC1
        MOVFF POSTINC1,POSTINC0
?I002502_F022_000109_P000472 ; L#MK DEC(FINDEXIN)
        MOVLB 6
        DECF M797_U08,1
        MOVLB 0
        BRA WHILE_25
FALSE_169
?I002503_F022_000111_P000472 ; L#MK INDF0 = 0   // ADD END OF STRING TERMINATOR
        CLRF INDF0,0
?I002504_F022_000112_P000472 ; L#MK NEWSENTENCE = TRUE
        MOVLB 5
        BSF M716_U01,4
ENDIF_280
        MOVLB 0
        BRA ENDIF_279
FALSE_168
?I002505_F022_000116_P000472 ; L#MK IF FINDEXIN < NMEABUFFERSIZE THEN
        MOVLW 80
        MOVLB 6
        SUBWF M797_U08,0
        MOVLB 0
        BC FALSE_170
?I002506_F022_000117_P000472 ; L#MK FSR0 = @FBUFFER
        LFSR 0,M717_U640
?I002507_F022_000118_P000472 ; L#MK INC(FSR0, FINDEXIN)
        MOVLB 6
        MOVF M797_U08,0
        ADDWF _FSR0L#M0_U16,1,0
        MOVLW 0
        ADDWFC _FSR0L#M0_U16H,1,0
?I002508_F022_000119_P000472 ; L#MK INDF0 = DATA
        MOVFF F682_U08,INDF0
?I002509_F022_000120_P000472 ; L#MK INC(FINDEXIN)
        INCF M797_U08,1
        MOVLB 0
        BRA ENDIF_281
FALSE_170
?I002510_F022_000122_P000472 ; L#MK FREADINGSENTENCE = FALSE
        MOVLB 5
        BCF M716_U01,0
ENDIF_281
        MOVLB 0
ENDIF_279
ENDIF_277
?I002511_F022_000128_P000472 ; L#MK PIE1.5 = 1
        BSF PIE1,5,0
ENDIF_275
        CLRF FSR0L,0
        CLRF FSR0H,0
        LFSR 1,F697_U200
        MOVLW 25
        MOVFF POSTINC1,POSTINC0
        DECFSZ WREG,1,0
        BRA $ - 6
        MOVFF F696_U08,FSR1H
        MOVFF F695_U08,FSR1L
        MOVFF F694_U08,FSR0H
        MOVFF F693_U08,FSR0L
        MOVFF F692_U08,TABLAT
        MOVFF F690_U16H,_TBLPTRL#M0_U16H
        MOVFF F690_U16,_TBLPTRL#M0_U16
        MOVFF F689_U08,PRODH
        MOVFF F688_U08,PRODL
        MOVFF F687_U08,STATUS
        MOVFF F686_U08,INDF1
        MOVFF F685_U08,INDF0
?I002512_F022_000132_P000472 ; L#MK WREG = WREGHOLD
        MOVLB 2
        MOVF F683_U08,0
?I002513_F022_000133_P000472 ; L#MK BSR = BSRHOLD
        MOVFF F684_U08,BSR
?I002514_F022_000135_P000472 ; L#MK END INTERRUPT
        RETFIE 1
Many thanks for any help,

Steve

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Fri Sep 05, 2008 8:50 am

Hi Steve

Not looked enough at the asm to see what the issue is with your code but this is mine for Proton

It uses only FSR0 as long as the regs are global

I'm only interested in collecting 3 sentences though

Code: Select all

'-------------------------------------------------------------------------------------------
'
' USART INTERRUPT
' Loads in the required GPS strings
'
'-------------------------------------------------------------------------------------------
GPS_RECEIVE:
    RESET_BANK
          
    If OERR = 1 Then GoTo USART_ERR 	                        ' Check for usart overrun
    If RCIF = 0 Then GoTo USART_RECEIVE_EXIT2                   ' Check this is a Usart in interrupt
    
    HiIntFSRSave = FSR_0                                        ' Save the FRS Reg
    IntData = RCREG                                             ' Make a working copy of the data

    If IntData = "$" Then                                       ' When we see the $ were starting a new packet
        NewGPSSentance = True
        SentanceCompare = 0                                     ' Clear our comparison variable
        IntArrayIndex = 0                                       ' Clear the array pointer
        GoTo USART_RECEIVE_EXIT        
    EndIf
    
    If IntData = "*" Then
        EndOfSentanceCount = 255-2                              ; Put it 2 places off the end of the sentance
    EndIf
    
    Inc EndOfSentanceCount  
    
    If NewGPSSentance = True Then
       SentanceCompare = SentanceCompare << 8                   ' Shift the previous byte left 
       SentanceCompare.BYTE0 = IntData                          ' Put the value into the compare DWord
    EndIf
        
    Select SentanceCompare
    
    Case GPRMC 
        NewGPSSentance = False                                  ' We have valid data so do no more on SentanceCompare var
        GPS_RMCRaw[IntArrayIndex] = IntData 
        If IntArrayIndex < GPS_RMCRaw_Bounds Then               ' keep the pointer in the bounds of the array
            Inc IntArrayIndex
        EndIf
        If EndOfSentanceCount = 0 Then
            NewGPRMCPacket = True
        EndIf
        
    Case GPVTG 
        NewGPSSentance = False                                  ' We have valid data so do no more on SentanceCompare var
        GPS_VTGRaw[IntArrayIndex] = IntData       
        If IntArrayIndex < GPS_VTGRaw_Bounds Then               ' keep the pointer in the bounds of the array
            Inc IntArrayIndex
        EndIf
        If EndOfSentanceCount = 0 Then
            NewGPVTGPacket = True
            GPSModuleWorkingTimer = GpsModuleTmrReload              ' reload our hardware watch timer
        EndIf    
                   
    Case GPGGA 
        NewGPSSentance = False                                  ' We have valid data so do no more on SentanceCompare var
        GPS_GGARaw[IntArrayIndex] = IntData       
        If IntArrayIndex < GPS_GGARaw_Bounds Then               ' keep the pointer in the bounds of the array
            Inc IntArrayIndex
        EndIf
        If EndOfSentanceCount = 0 Then
            NewGPGGAPacket = True
        EndIf 
    EndSelect
    
USART_RECEIVE_EXIT:
     FSR_0 = HiIntFSRSave 
USART_RECEIVE_EXIT2:
     Inc WatchDogTimer
     If WatchDogTimer > 250 Then 
         Restart
     EndIf
     retfie fast
   
USART_ERR:
     WREG = RCREG
     CREN = 0
     CREN = 1 
     GoTo USART_RECEIVE_EXIT
'---------------------------

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Fri Sep 05, 2008 9:52 am

Hi Steve looking at your code I have a question

When you get the problem with the screen being corrupted are accessing the data from the array used in the interrupt?

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Fri Sep 05, 2008 3:12 pm

Hi Tim, thanks very much for your replies. I'll have a look at your Proton code (thanks very much for that) shortly, but in reply to your second post, yes, quite possibly. I am constantly polling to see if a new sentence has been received, at the point where it corrupts.

TimB
Posts: 262
Joined: Wed Oct 04, 2006 7:25 am
Location: London UK

Post by TimB » Fri Sep 05, 2008 3:24 pm

It all depends on how your using the data.

From experience I would wait until all the string is in then set a flag.

You then have 1 sec + to process the data.

I'm not saying that is the issue here but in cases like yours its either corrupting system vars or the data changing as your working on it.
Looking at the asm you do not seem to be using any system vars.

In fact I would say you are being very over cautious in your var saving.

The first thing to try is disabling interrupts while you make a copy of the array to work on it.

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Fri Sep 05, 2008 4:33 pm

OK, thanks Tim. I've looked through your code very carefully - really helpful thanks and some useful ideas. I've context saved everything I could think might help! I'll continue to look at my code and let you know if I get further.

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Fri Sep 05, 2008 4:58 pm

I know that Tim loves interrupts, but I had trouble with the NMEA module and use this function below instead. I can use this and your file system to record data at 5Hz without a problem!

The function is called using:

Code: Select all

GPRMC_STR = NMEA_SENTENCE("$GPRMC")

Code: Select all

//******************************************************************************
Function NMEA_SENTENCE(pHEADER As String) As String * 100
    Dim GPS_CHAR As Char
    Dim GPS_CHARPOS As Byte
    Dim GPS_RXBUFFER_LENGTH As Byte
    GPS_RXBUFFER_LENGTH = 100
    
    WaitForStr(pHEADER)
    GPS_CHARPOS = 0
    While True										' Create a loop to receive the serial string
        GPS_CHAR = USART.ReadByte()                 ' Receive a character serially
        RESULT(GPS_CHARPOS) = GPS_CHAR              ' Store Character
        Inc(GPS_CHARPOS)                            ' Increment the index

        If GPS_CHAR = #13 Or GPS_CHAR = #10 Then 
            Break				' Exit the loop if the string reaches the end
        EndIf
        
        If GPS_CHAR = "*" Then 
            GPS_RXBUFFER_LENGTH = GPS_CHARPOS + 1   ' Set Test to get 2 more characters
        EndIf
        
        If GPS_CHARPOS > GPS_RXBUFFER_LENGTH Then   ' Terminate reading
            RESULT(GPS_CHARPOS) = NULL
            Break      ' Repeat the loop until the buffer runs out
        EndIf                
    Wend
    
    RESULT = pHEADER + RESULT
End Function
Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Fri Sep 05, 2008 5:16 pm

Thanks Ryan - that's also helpful. I don't know that I can easily move away from using interupts as I have other jobs that need doing, but it's very tempting...

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

SOLVED: Silicon errata - use software context saving!

Post by Steven » Sat Sep 06, 2008 11:07 am

OK, I think I have solved this one. Having reduced the ISR to the very bare minimum of:

Code: Select all

Interrupt OnNMEAData()
Dim Data As Char
      Data = RCREG
End Interrupt
and still getting the problem of corruption of the GLCD display, I decided that it wasn't my ISR causing the problem as such. However, disabling the ISR did stop the problem. So... off to the silicon errata for the 18F4620...

"If an interrupt occurs during a two-cycle instruction that modifies the STATUS, BSR or WREG register, the unmodified value of the register will be saved to the corresponding Fast Return (Shadow) register and upon a fast return from the interrupt, the unmodified value will be restored to the STATUS, BSR or WREG register."

The solution seems to be to force software context saving using the compilers useful feature:

"You can force the compiler to perform software context saving in software for both high and low interrupts, rather than using hardware shadow registers. This is achieved by using the ISR_SHADOW option. For example,

#option ISR_SHADOW = false

disables all hardware shadow register context saving."

Now I can move on! Many thanks for the help and suggestions.

Steve

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Sat Sep 06, 2008 12:25 pm

Steven, if this is working for you can you post your GPS ISR routine and the supporting functions? I wouldn't mind stepping up to 10 and 20 Hz gps engines in the future.
Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Sat Sep 06, 2008 11:17 pm

Yes, I'll definitely post - a little more work and a little tidying up is needed, then I'll post as a module on the wiki.

User avatar
leisryan
Posts: 1
Joined: Fri Sep 05, 2008 10:54 pm
Location: Philippines

Interrupt

Post by leisryan » Fri Oct 24, 2008 3:32 am

Steven wrote:Yes, I'll definitely post - a little more work and a little tidying up is needed, then I'll post as a module on the wiki.
Sir:
Good day I'm from picbasic pro i've been using interrupts based on darrel taylor and it's a breeze but right now i'm trying out swordfish and porting some of my interrupt driven projects, i'd like to ask if you have workaround the problem you've encountered? I'd be very grateful if you could share what exactly went wrong both on the compiler and hardware point of view. Thanks in advance
-slyrye-

User avatar
Steven
BETA Tester
Posts: 406
Joined: Tue Oct 03, 2006 8:32 pm
Location: Cumbria, UK

Post by Steven » Fri Oct 24, 2008 6:25 am

Hello. Yes, I solved the problem in the end - the solution is in the post 4 above this one. I was getting corruption of a GLCD display. In the end, disabling hardware shadow registers for context saving and forcing software context saving was the answer.

P.S. Welcome to the Swordfish forum.

User avatar
Jason
Posts: 50
Joined: Mon Mar 10, 2008 1:10 pm
Location: Australia

Post by Jason » Thu Nov 06, 2008 1:00 pm

extremely interesting guys, I've been trying to get my head around interupts lately and this post has been good to explain the shadow registers software/hardware.. Swordfish is gaining momentum I think...

User avatar
ohararp
Posts: 194
Joined: Tue Oct 03, 2006 11:29 pm
Location: Dayton, OH USA
Contact:

Post by ohararp » Thu Jan 22, 2009 8:51 pm

Steven, thanks for posting this about the ISR_SHADOW option. I have been trying to get a hardware interrupt on a serial line working correctly. Everything seems fine and then the interrupt goes totally buggy. I am hoping this will solve the problem since I am using the 18F2620.

#option ISR_SHADOW = false
Thanks Ryan
$25 SMT Stencils!!!
www.ohararp.com/Stencils.html

Post Reply