High/low priortiy interrupts question (again)

General discussion relating to the library modules supplied with the compiler

Moderators: David Barker, Jerry Messina

Post Reply
Gordon_h
Posts: 55
Joined: Fri Apr 06, 2007 8:55 pm
Location: Boulder, Colorado

High/low priortiy interrupts question (again)

Post by Gordon_h » Sun May 31, 2009 10:26 pm

I have a slave I2C processor using 4 interrupts, where the I2C is set as high priority, and the others as low- RX USART, TX USART, TIMER1. It is all working, but not with priority. When the USART is very busy, the (high priority) I2C stuff stops working. This can be seen on a scope.

I have
IPEN=1
SSPIF=1
RCIF=0
TXIF=0
TImer1IP=0

(some of these are in other modules)

I thought that the high priority interrupt would take precedence over the low priority, but it looks to be completely the opposite here- the low priority stuff cranks along, and the high priority never gets a look-in. Anybody see what I am missing?

Code: Select all

Module HPInts

Const
  ipLow = 1,
  ipHigh = 2

Include "aSetupUSART.bas"
Include "aISRTXRX.bas"
Include "aTimer.bas"
Include "aPins.bas"
Include "aINTI2Cs.bas"                                     ' Interrupt driven I2C slave code

Dim 
  GIE As INTCON.7,
  Timer1IP As IPR1.0,
  IPEN As RCON.7


'****************************************************************************
'* Name    : hiISR                                                            *
'* Purpose : High priority interrupt service routine                        *
'*         : Checks enables, flags, and triggers events                     *
'****************************************************************************
Interrupt hiISR(ipHigh)                                    ' High Priority ISR code
  If (SSPIF=1) And (SSPIE=1) Then
    High(oSpare2)                                          ' Scop trigger
    intI2Cs.FOnI2CEvent()                                    ' Trigger event
  EndIf
End Interrupt     

'****************************************************************************
'* Name    : loISR                                                          *
'* Purpose : low priority interrupt service routine                         *
'*         : Checks enables, flags, and triggers events                     *
'****************************************************************************
Interrupt loISR(ipLow)                                      ' Low Priority ISR code
  Save(PRODL,PRODH)

  If (Timer1IF=1) And (Timer1IE=1) And (Timer1On=1) Then   ' TIMER 1 interrupt code
    Timer1 = Word(TimerValue)                              ' Force integer arithmetic
    Timer.FOnTimerEvent()
    Timer1IF = 0
  EndIf

  If (TXIE=1) And (TXIF=1) And (TxBufIsEmpty=false) Then   ' USART transmit interrupt
    aISRTXRX.FOnTxEvent()
  EndIf
  
  If (RCIE=1) And (RCIF=1) Then                            ' USART receive interrupt code
    aISRTXRX.FOnRxEvent()
  EndIf
  
{  If (INT1IF=1) And (INT1IE=1) Then                        ' RB1 interrupt code
    MC_PortB.FOnInt1Event()
    INT1IF=0
  EndIf
}  
  Restore
End Interrupt     

'****************************************************************************
'* Name    : Initialize                                                     *
'* Purpose :                         *
'*         :                      *
'****************************************************************************
Public Sub Initialize()
   intI2Cs.i2cInit()                                       ' Initialize MSSP for I2C slave
   Timer.ActivateTimer()                                   ' Timer 1 1msec timer
   Timer1IP=0
   IPEN=1 
'   MC_PortB.ActivateInt1()                                  ' Activate key-sense interrupt (RB1) 
   aISRTXRX.ActivateISRTXRX()                              ' Activate interrupt TX/RX module
   Enable(hiISR)                                           ' Inable interrupt service routine
   Enable(loISR)                                           ' Inable interrupt service routine
   GIE=1 
End Sub


User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Sun May 31, 2009 10:52 pm

Is the PEIE bit enabled to enable peripheral interrupts? I wouldn't expect the USART interrupt to work if it wasn't but I've seen weirder things with interrupts......

-Tom

Gordon_h
Posts: 55
Joined: Fri Apr 06, 2007 8:55 pm
Location: Boulder, Colorado

Post by Gordon_h » Mon Jun 01, 2009 3:31 pm

Yes, it is set to 1 in one of the other modules, at initialization. Just to be clear, the I2C works great, but is completely stops while the USART is busy. Fortunately, for this particular project, the serial data is only used for debug, so it is not going to hold it up- but it would be nice to know for the future.

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

Post by Jerry Messina » Mon Jun 01, 2009 3:42 pm

When you have the priority mechanism enabled(IPEN=1), the PEIE bit becomes GIEL, so that's not the problem.

Gordon -
On the surface, what you have looks fine. Since there's some code not shown, I'd check:
- make sure that you've got the other IPRx priority bits set properly
- verify that you're actually setting the IE bits
- from the description, I take it you have the intr handlers declared as type event, and not sub?
Make sure you're initializing the event "pointers" to point to the proper event.
- in the event handlers, make sure you reset the IF bit, unless the peripheral does this for you (like the usart receive)
- you're not calling disable() anywhere, are you?

I take it you're not getting the scope trigger in the hiISR routine?

PS - you can get rid of the "GIE=1" statement at the end of Initialize()...
that's what "Enable(hiISR)" does

Jerry

Gordon_h
Posts: 55
Joined: Fri Apr 06, 2007 8:55 pm
Location: Boulder, Colorado

Post by Gordon_h » Tue Jun 02, 2009 1:48 am

Jerry,

I believe I have covered all of those. Again, ALL the interrupts are working well MOST of the time, it is just the priority order which is not. I think if I were not resetting the IF or something, that interrupt would not work correctly. Once the USART traffic is handled, the I2C picks right up and continues. And yes, the scope trigger is never seen- in fact both I2C lines are dead.

The one thing I have not teased out is whether the TX and RX USART routines have the same effect. I believe it is the TX one that does most of it, but it would be instructive to know if they are both having the same effect. And, likewise, the timer- although I have it set to 1 msec, and so it does not take very long.

It is odd- I never see the I2C failing in the middle of its operation- it always completes- I am sending/receiving about 20 bytes. So the effect is that the first I2C interrupt (which occurs on an address match) never happens. I have never caught a "long" I2C exchange, they seem to either be 100% good and complete in a normal time, or not there at all.

I have searched for a disable(), but have not found it- I would use GIE=0 or similar in the code, I never want the interrupts off.

If I had to wildly guess, I would say that the chip has a problem such that USART use interferes with one of the SSP resgisters, causing the I2C to stop.

Thanks for the suggestions, like flying it is good to have someone go over your pre-flight checklist!

Gordon

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

Post by Jerry Messina » Tue Jun 02, 2009 9:31 am

Your original reply came through right as I posted mine (of course), so you answered 99% of my questions there when you said that everything works normally.

If you've got GIEH set and the SSPIE enabled, then I don't see what else could be going on. Since the I2C is the only high priority intr, this should work fine. The 4525 has a pretty healthy list of errata, so maybe there is some issue there. The only other thing I can think of is that somewhere you're mistakenly masking SSPIE. If you goofed up GIEH, then that would shutdown the serial intr as well, so that shouldn't be the issue.

If you ever find out the cause, do me a favor and update this thread. I use almost the exact same interrupt handling code, so I'd be curious to see what the issue was.

Jerry

Gordon_h
Posts: 55
Joined: Fri Apr 06, 2007 8:55 pm
Location: Boulder, Colorado

SOLVED!

Post by Gordon_h » Wed Jun 03, 2009 2:03 am

Jerry,

Turns out it was "cockpit error". I forgot that on this version of the board, I brought TxD to what I thought was an unused pin on a connector going back to the Master. That pin actually goes to MCLR :oops: . So every time there was data going out, the Master was being reset- since I was using a scope, I did not pick up on this right away. If I had looked at its' serial output, I would have seen a string of sign-on messages!

I guess this was inadvertently a very stringent test of the system, since it recovered from this every time.

Thank you for backing me up on this- it made me not doubt and keep on looking for the root cause. I think your code should be okay.

Gordon

User avatar
RadioT
Registered User
Registered User
Posts: 157
Joined: Tue Nov 27, 2007 12:50 pm
Location: Winnipeg, Canada

Post by RadioT » Tue Aug 11, 2009 9:06 pm

That's engineering. One wrong obscure bit set or rogue line can bring a grown man to his knees. For days. Unlike law and sales, we can't talk our way out of such conundrums.

Well, I suppose you could say the system operated exactly as expected for the set up!

73's,

de Tom

Post Reply