AnsweredHot!Strange Interrupts on PIC32MX150F128!

Author
SM6FIE
Starting Member
  • Total Posts : 41
  • Reward points : 0
  • Joined: 2007/06/12 12:10:28
  • Location: Sweden
  • Status: offline
2018/03/11 18:59:48 (permalink)
0

Strange Interrupts on PIC32MX150F128!

I have a peculiar problem. I have a PIC32MX150F128 running an application with the following setup. On INT1 I have a pulse train @ 1PPS. The leading edge of the pulse generates a priority 7 interrupt using shadow registers.
When an interrupt is received the interrupt routine stops TMR23 and then saves the result. TMR23 is clocked by the PBCLK. The expected number of pulses during one second is checked to be within a lower and upper counts (we have small variation due to temperature etc. of the PBCLK). TMR23 is cleared, the timer enabled again and the interrupt flag is cleared and the routine is exited.
The application also uses a multi timer setup based on the core timer. The core timer count register is read, a value is added to this, to give 1 mS. delay, and the result is stored in the compare register. Then CTIF is cleared.  When the Core timer interrupt is generated the multi timers are updated and the cycle restarts again. The Core Timer interrupts runs on priority level 6.
This works as expected for many hours (3-12 hours). Then suddenly the counts of TMR23 are out of bounds. Normally it should count 48 000 000 counts (the MCU runs @ 48 MHz) but now the counts are only 70 -150 counts (corresponding to about 1 uS).
When I get this error I stop the execution via a breakpoint. When I check the call stack it is always when doing a Core Timer interrupt. The Core Timer Interrupt is executing and been interrupted by the INT1 interrupt.
I have done a lot of test ad debugging approaches to solve this. But I can’t find a solution or a simple workaround. One interesting thing is the following:
I connect an oscilloscope to the 1 PPS signal, channel 1. Then I introduced a short debugging pulse in the INT1 interrupt service routine. This signal was feed to channel 2. I let the scope trigger on the debugging pulse. This works fine. I can see the flank of the 1 PPS INT1 signal and shortly thereafter the debugging pulse (< 1 uS delay). Exactly what is expected. Now if I set a breakpoint in my code when the TMR23 is out of bounds the oscilloscope screen will freeze with the last event.
And here comes the peculiar fact. I will always see two debug pulses on the scope. The INT1 interrupt has been generated two times. It is about 1.5 to 3 uS between the pulses. So in some strange way the hardware generates two interrupts, this should not happen! Why? Any ideas about this.
I’m now considering abandoning the Core Timer and using another timer for the task. But it is irritating to not understand what is happening!  
I’m using MPLAB 3.55 under windows. XC23 V1.44.
Regards
Bo, SM6FIE
#1
Mysil
Super Member
  • Total Posts : 2683
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: offline
Re: Strange Interrupts on PIC32MX150F128! 2018/03/11 20:42:46 (permalink) ☄ Helpfulby SM6FIE 2018/03/13 08:44:59
5 (1)
Hi,
As I understand, there are 2 interrupt driven activities that are asynchronous to each other.
External interrupt at priority 7,
and Core Timer interrupt at priority 6.
These will drift relative to each other, so some times Core Timer interrupt processing will be interrupted by the higher priority external INT1.
In this case it is important that any data or register that are accessed in both ISR procedures,
are handled by Atomic or Interrupt-safe/Thread-safe code.
In addition to any application data storage/update, this also apply to Interrupt Flag control registers,
where interrupt flag bits for Core Timer, External interrupt and Timers are all located in IFS0 register.
Updates to these flags must be done by IFS0CLR register operations. e.g.:
IFS0CLR = _IFS0_CTIF_MASK;
IFS0CLR = _IFS0_INT1IF_MASK;
Use of: IFS0bits.CTIF = 0;  IFS0bits.INT1IF = 0; // is a possible source of intermittent errors.
 
For any other possible bug, you must show a complete example program demonstrating the problem.
 
   Mysil
#2
aschen0866
Super Member
  • Total Posts : 4278
  • Reward points : 0
  • Joined: 2006/01/08 22:18:32
  • Location: San Diego
  • Status: offline
Re: Strange Interrupts on PIC32MX150F128! 2018/03/11 22:07:50 (permalink)
0
How does the Core Timer interrupt get updated for the next occurrence? If it is done by calling UpdateCoreTimer(), i.e., a PLIB call, then there is a potential problem. A Core Timer interrupt is generated when the Core Timer value matches the value in the CP0 COMPARE register. The UpdateCoreTimer() simply adds the desired value to the COMPARE register, setting up for the next interrupt. However, in a system with multiple interrupts, especially when the Core Timer interrupt priority remains low, by the time UpdateCoreTimer() is called, the actual value in the Core Timer may have already overshot (COMPARE + the desired value), this means the next Core Timer interrupt will not occur until the Core Timer has wrapped around. The fix is to provide your own UpdateCoreTimer() function that reads the current Core Timer, adds the desired value then writes it back to the COMPARE register. This approach solves the overshoot issue but makes the interrupt less precise. It is the decision you have to make.
post edited by aschen0866 - 2018/03/11 22:08:55
#3
andersm
Super Member
  • Total Posts : 2374
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: Strange Interrupts on PIC32MX150F128! 2018/03/11 22:48:35 (permalink) ☼ Best Answerby SM6FIE 2018/03/12 12:06:17
0
bagI have a PIC32MX150F128 running an application with the following setup. On INT1 I have a pulse train @ 1PPS. The leading edge of the pulse generates a priority 7 interrupt using shadow registers.

The PIC32MX1xx/2xx don't have shadow registers.
#4
SM6FIE
Starting Member
  • Total Posts : 41
  • Reward points : 0
  • Joined: 2007/06/12 12:10:28
  • Location: Sweden
  • Status: offline
Re: Strange Interrupts on PIC32MX150F128! 2018/03/12 12:07:18 (permalink)
0
That is correct. PIC32MX1xx/2xx dont have shadow registers. My misstake...
#5
SM6FIE
Starting Member
  • Total Posts : 41
  • Reward points : 0
  • Joined: 2007/06/12 12:10:28
  • Location: Sweden
  • Status: offline
Re: Strange Interrupts on PIC32MX150F128! 2018/03/13 11:54:31 (permalink)
0
Hi!
 
My Core Timer interrupt routine look like this:
 
// Core Timer INTERRUPT ROUTINE ***************************************************
// IsrCoreTmr, Core timer interrupt routine
// NOTE! This code can be commented when testing Core timers test frame work!!!
void __ISR(_CORE_TIMER_VECTOR, IPL6SOFT) IsrCoreTmr(void)
{
  xMultiTmrInterrupt();
  Nop();
  IFS0bits.CTIF = 0;
  // xOpenCoreTimer(MULTI_TMR_RES_COUNTS);
  xUpdateCoreTimerFromCount(MULTI_TMR_RES_COUNTS); // Make relativ update of core timer (from current value))
}

 
The core timer update routine look like this:
// xUpdateCoreTimerFromCount
// Function: Adds uiAddPeriod to the content of the count register
// and sets the compare register to the result
// uiAddPeriod: Updates the Compare register with the current value of the count
// register + uiAddPeriod
// Note: Clears the Core Timer Interrupt flag CTIF
// Example: xUpdateCoreTimerFromCount(0xFFX);
void xUpdateCoreTimerFromCount(unsigned int uiAddPeriod)
{
    unlint ulCount;
    asm volatile("mfc0 %0, $9" : "=r"(ulCount)); // Read Core timer count register
    uiAddPeriod = uiAddPeriod + ulCount; // Add new period to timer counts
    asm volatile("mtc0 %0,$11" : "+r"(uiAddPeriod)); // Set up the new period in the compare register
}

 
The INT1 interrupt code look like this:
// External INT1 INTERRUPT ROUTINE, GPS 1 PPS***********************************
// IsrInt1, Timer interrupt routine, priority #7
// Description: Increment GPS clock when we got an interrupt from the GPS 1PPS
// Note: This is a 24 UTC hour clock
// The value of the TMR2 32 bit counter is expected to be in the interval
// between iGrtcLowerCountLimit and iGrtcUpperCountLimit. If not GpsClkRec.ucErr
// is set t0 relevant error code (COUNTS_TO_LOWER_ERROR or COUNTS_TO_UPPER_ERROR)
void __ISR(_EXTERNAL_1_VECTOR, IPL7SOFT) Int1Handler(void)
{
  DbgPort1PinHigh();
  T2CONbits.ON = False;
  Nop(); // Let TMR stabilize
  GpsClkRec.uiLastTmrCount = TMR2;
  TMR2 = 0;
  Nop();
  T2CONbits.ON = True;

  // DEBUG
  iValueVek[iIdx] = GpsClkRec.uiLastTmrCount;
  iIdx++;
  if (iIdx > 100) {
    iIdx = 0;
  }
  DbgPort1PinLow();
  iGpsOneLapCount++;
  if (iGpsOneLapCount >= 3) {
    iGpsOneLapDone = True;
    if (GpsClkRec.uiLastTmrCount < iGpsLowCountLimit) {
      GpsClkRec.ucErr = GPS_COUNTS_TO_LOW_ERROR;
      iGpsClockError = GPS_COUNTS_TO_LOW_ERROR;
    }
    if (GpsClkRec.uiLastTmrCount > iGpsHighCountLimit) {
      GpsClkRec.ucErr = GPS_COUNTS_TO_HIGH_ERROR;
      iGpsClockError = GPS_COUNTS_TO_HIGH_ERROR;
    }
  }

DoInt1Calculations();
  mxINT1ClearIntFlag();
  Nop();
  return;
}

 
I have attached a photo of the oscilloscope graph when the error occurs. The yellow graph is the INT1 pin. And the blue is the DbgPort1 pin. As can be seen the interrupt INT1 is generated twice rapidly (within a micro second).
The  mxINT1ClearIntFlag(); is a macro that does: (IFS0CLR = _xIFS0_INT1IF_MASK)
 
The only thing I can see that I should change is the IFS0bits.CTIF = 0; statement. I should remove this due to the fact that updating the Core timer compare register by default clears the CTIF. Will see if this changes the behavior.
 
The multi timers interrupt uses the result of the TMR23 counter (INT1). But this should not interfere with the INT1 interrupts and generate spurious interrupts as in the photo.
 
Regards, Bo, SM6FIE
 

Attached Image(s)

#6
al_bin
Super Member
  • Total Posts : 154
  • Reward points : 0
  • Joined: 2011/02/11 06:28:47
  • Location: 0
  • Status: offline
Re: Strange Interrupts on PIC32MX150F128! 2018/03/13 13:33:09 (permalink)
0
try:
IFS0CLR = 1;
instead:
IFS0bits.CTIF = 0;

Albert
#7
Jump to:
© 2018 APG vNext Commercial Version 4.5