Interrupts - ISRRX Glitches

Coding and general discussion relating to user created compiler modules

Moderators: David Barker, Jerry Messina

Post Reply
TonyR
Posts: 75
Joined: Fri Jan 14, 2011 11:49 pm
Location: Sydney
Contact:

Interrupts - ISRRX Glitches

Post by TonyR » Wed Nov 16, 2016 7:42 pm

I've had great success with SF many times but one place that often comes unstuck is the ISRRX ISR. Despite trying save and restore of everything that moves.

Usually Ive had a main program doing something and the ISR takes chars from a serial port with ISRRX and concatenates a command string that then does something such as return data back out the serial port based on that command string from the main program.

But invariably the ISRRX trashes some part of the main program. Sometimes severely and sometimes hardly ever. While trying to trace the problem even if the On Interrupt function has no code the glitches can still happen. I read once a comment from David that this can happen when using numbers built from multiple bytes like ints and floats and the glitch happens because the ISRRX interrupt occurs at the exact time the bytes are getting converted to 16bit etc. So I guess that would also include strings using indexes internal to SF that are bigger than a byte.

So my questions to those wiser and with more experience than me with SF are:

If I keep my code to byte level only will save restore likely solve the problem? I tried this and sometimes found I could get the ISRRX and main running for hours and hours without a glitch. But doing that removes a lot of the nice SF features especially string handling.

Is there a definitive list anywhere of every single register to save/restore that would make ISRRX calls bullet proof, in that it couldn't trash main code? Is it possible to pause ISRRX at times that might glitch the main program?

Thanks!

Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Interrupts - ISRRX Glitches

Post by Jerry Messina » Thu Nov 17, 2016 12:36 pm

I've used a version of ISRRX in dozens of programs without issue.

The trick? Don't do anything in the ISR that isn't absolutely necessary. Basically that means leave ISRRX to do nothing more than buffer up characters for you, and handle getting the chars from ISRRX in your main routine. It can be surprisingly tricky to get all the context saving right if you try to do otherwise. Things that appear simple may not be, and if you start doing things like calling subroutines or library code things can get very sticky very fast.

That's pretty much true of any ISR... do the absolute minimum required to handle what the interrupt requires you to do, and put off anything else until later. Keep the ISR as simple and straight-forward as possible.

Some folks take that to the extreme and just set a flag in the ISR to say "hey, I got an interrupt", but that's a complete waste of time. You'd be better off just polling the peripheral IF flag in the main loop.

The issue with multi-byte variables is pretty much the same in any language. Accessing a variable in both the ISR context and the main context will cause problems unless you really think about what's going on at the lower level and take steps to prevent the problems.

User avatar
David Barker
Swordfish Developer
Posts: 1214
Joined: Tue Oct 03, 2006 7:01 pm
Location: Saltburn by the Sea, UK
Contact:

Re: Interrupts - ISRRX Glitches

Post by David Barker » Thu Nov 17, 2016 9:23 pm

I know it's not really offering anything new, but I must endorse what Jerry has said. I have many commercial programs running with interrupts without any problems - because I keep anything in an ISR to the bare minimum.

When using an 8 bit PIC MCU you need to think about the problem differently from say a PC program. For example, I have seen many code examples from users that call various subroutines when a timeout interrupt occurs. You will have one hell of a job debugging that! In this example, simply use an interrupt to increment a simple counter every 1ms or so. Then, in your main program, use a state model to move between states based on a timeout value.

Even then, you must be careful! - incrementing a 2 or four byte variable in an ISR and then attempting a read in you main program in not safe - you may have to halt the ISR before reading a multibyte value.

In the case of buffered serial - do just that. Buffer the incoming data so no nothing is missed - but process outside of the ISR...

TonyR
Posts: 75
Joined: Fri Jan 14, 2011 11:49 pm
Location: Sydney
Contact:

Re: Interrupts - ISRRX Glitches

Post by TonyR » Fri Nov 18, 2016 1:35 am

Thanks David and Jerry.

This bit of code has given me the most grief. Even if I have no code at all in the On Interrupt Sub the value of "total" in the code glitches to an erroneous value maybe one in every 200 readings. The faster the rate of data coming in the worse it is. But if I disable the On Interrupt bingo total is calculated perfectly every time. I resorted often to polling the USART instead of using interrupts.

What I want to do is have a main program running doing things and get the data out at random times with ISRRX. One design I did used ADS1100 16 bit I2C ADCs instead of the PIC ADCs. It never ever glitched. I guessed maybe compiling the 12bit reading from ADCRESL + ADCRESH is impossible to do in the presence of interrupts?

Suggestions as to how I could do it better would be appreciated.

Code: Select all

Public Function GetVolts()
'
' Average 100 readings
'
For x = 0 To 99
    ADCON0 = ADCON0 Or %00000011      ' trigger a reading
    While ADCON0.1 = 1
    Wend            
    ADCReading = ADRESH << 8
    ADCReading = ADCReading Or ADRESL    
  total = total + ADCReading
Next
ADCReading = (total / 100)   
GetVolts =  (ADCReading*gain) - offset
End Function 


Jerry Messina
Swordfish Developer
Posts: 1469
Joined: Fri Jan 30, 2009 6:27 pm
Location: US

Re: Interrupts - ISRRX Glitches

Post by Jerry Messina » Fri Nov 18, 2016 10:33 am

Even if I have no code at all in the On Interrupt Sub...
But if I disable the On Interrupt bingo total is calculated perfectly every time...
When you say the 'On Interrupt sub' are you talking about the 'FOnDataEvent' or the ISRRX interrupt itself?

Where is 'GetVolts()' being called from?
What I want to do is have a main program running doing things and get the data out at random times with ISRRX
I don't quite follow you there. What does data coming in from the serial port have to do with reading the ADC?

Do you mean you want to process some serial command in ISRRX, call GetVolts() and send back a result, all inside the 'FOnDataEvent'? If so, that's exactly the kind of thing that's going to cause you a world of grief.

Maybe you could describe what you want to do a little clearer? It's early here...

Post Reply