Near Disaster with Interrupt Handling ISRRX

Coding and general discussion relating to the compiler

Moderators: David Barker, Jerry Messina

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

Near Disaster with Interrupt Handling ISRRX

Post by TonyR » Mon Sep 12, 2016 4:52 am

I designed a great battery test system using PIC18F87K22 driving Power Op Amps, capable of charge, discharge up to 12V 1A of battery under test. After the long development of that I then added the last part, the RS485 link that was meant to monitor and control it (many of them in fact) from a distance.

At that point I found that no matter how I tried to rearrange the interrupt call (ISRRX.bas and OnData() as per example in manual), which was doing simple string concatenation to determine a command, it would randomly crash the ADC part of the battery loop. I tried every kind of save/restore I could think of. Then I read Davids comment "dont use interrupt function for very much" but it was too late. In the end I rewrote the entire software and the host PC software using polling and no interrupt function at all.

I traced the problem to my GetVolts function where I combine ADRESH and and ADRESL from the PIC ADC, then scale into a floating point number.

Code: Select all

      
 ADCReading = ADRESH << 8
 ADCReading = ADCReading Or ADRESL
 GetVolts =  (ADCReading*gain) + zero
If the interrupt is not called this function returns the processed ADC reading into GetVolts reliably for hours, if the interrupt is called I get occasional random values in the ADCReading (word). I had same problem with a device reading NEMA data at 4800BD using ISRRX and Ondata(). My boat navigation system randomly crashed due to the interrupt occasionally reading the incoming NMEA data and solved it them same way, I went to polling and no interrupt.

The interrupt is a really good valuable feature, is there an easy way to guarantee it can be used without crashing the loop its interrupting? Maybe a list of every single register to save, even if its a long list!?

Advice appreciated!

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

Re: Near Disaster with Interrupt Handling ISRRX

Post by Jerry Messina » Tue Sep 13, 2016 11:21 am

no matter how I tried to rearrange the interrupt call which was doing simple string concatenation to determine a command
"Simple string concatenation" isn't necessarily so simple. There tends to be a lot involved when using strings... they typically use lots of stack frame variables as things get copied about.
I don't normally use them in an isr because of this (plus they're slow).

I like to keep the isr handler for a uart short and sweet... collect incoming bytes into a queue and check for errors. That's about it... everything else is processed later on in the main loop.
is there an easy way to guarantee it can be used without crashing the loop its interrupting? Maybe a list of every single register to save, even if its a long list!?
Easy? Not really. Interrupts require careful attention to what's going on. It's not normally the registers that cause grief, it's all the stack frame variables that get reused from routine to routine.
A lot of this goes on behind the scenes, so something that looks simple at the source code level isn't. It's best to look at the ASM output.

What exactly was the isr doing?

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

Re: Near Disaster with Interrupt Handling ISRRX

Post by Jerry Messina » Tue Sep 13, 2016 11:55 am

One thing I've done in the past that can be helpful is to take all the code in the isr, put it into a subroutine, and add the subroutine name to the save list (along with '0'). That tends to get everything you need saved, plus it's easy to see from the increase in ram usage between 'save(0)' and 'save(0, mysub)' how much ram it's 'saving'.

Code: Select all

sub mysub()
   dim xxxx
   // all the code that used to be in the isr
end sub

interrupt isr()
    save(0, mysub)

    mysub()

    restore
end interrupt

Post Reply