General discussion relating to the library modules supplied with the compiler
Moderators: David Barker, Jerry Messina
-
Gordon_h
- Posts: 55
- Joined: Fri Apr 06, 2007 8:55 pm
- Location: Boulder, Colorado
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
-
RadioT
- 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: 1473
- 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: 1473
- 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
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
. 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
-
RadioT
- 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