Page 1 of 1

Interrupts - ISRRX Glitches

Posted: Wed Nov 16, 2016 7:42 pm
by TonyR
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!

Re: Interrupts - ISRRX Glitches

Posted: Thu Nov 17, 2016 12:36 pm
by Jerry Messina
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.

Re: Interrupts - ISRRX Glitches

Posted: Thu Nov 17, 2016 9:23 pm
by David Barker
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...

Re: Interrupts - ISRRX Glitches

Posted: Fri Nov 18, 2016 1:35 am
by TonyR
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 


Re: Interrupts - ISRRX Glitches

Posted: Fri Nov 18, 2016 10:33 am
by Jerry Messina
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...