• AVR Freaks

AnsweredHot!PIC32MZ interrupts won't trigger

Author
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
2019/01/28 11:00:06 (permalink)
0

PIC32MZ interrupts won't trigger

Hello,
 
I'm trying to implement a Timer2 interrupt, following Examples 14-8 and 14-9 in the PIC32 Family Reference Manual.  The code compiles and runs fine, but while the interrupt flag (T2IF) does get set, a debugger breakpoint at the ISR never gets triggered.  Can anyone see what the problem might be?
 
#include <stdio.h>
#include <stdlib.h>
#include <xc.h>
#include <proc/p32mz1024efg064.h>
#include <sys/attribs.h>

// Global Variable Definition:
volatile uint16_t count2 = 0x0;

/* Timer2 interrupt is IRQ #9 (header file defines _TIMER_2_VECTOR = 9)
 * linker puts the Vector offset in OFF009<17:1>
 * header file defines _INT_BASE_ADDRESS = 0xBF810000 */
void __ISR_AT_VECTOR(_TIMER_2_VECTOR, IPL3SRS) Timer2_Handler(void) {
 count2++;
 LATESET = 64;                     // turn on LED
 IFS0CLR = 0x00000200;             // clear Timer2 interrupt flag (IFS0<9>)
}

int main(int argc, char** argv) {
 int count;

 // configure Peripheral Bus #3 (Timers):
   SYSKEY = 0x0;
   SYSKEY = 0xAA996655;          // unlock the SFR registers
   SYSKEY = 0x556699AA;
 while (!PB3DIVbits.PBDIVRDY);   // wait until you can write a new Peripheral Bus #3 (Timers/ICs, ADC) Clock Divisor.
  PB3DIVbits.PBDIV = 2;
   SYSKEY = 0x0000;              // re-lock the SFR registers.
 
 // configure LED pin:
   ANSELE = 0x0;                 // PORTE pins have digital functions
   LATE = 0x0;                   // initialize LED "Off"
   TRISE = 0xFF81;

 // configure Interrupt registers:
 INTCON = 0x00001000;           // multi-vectored mode (MVEC = 1), disable Interrupt Proximity timer (TPC = 0)
 PRISS = 0x76543210;            // configure each Interrupt Priority Level to the same-numbered Shadow Register
 
 // Timer2 configuration:
 T2CON = 0x0;                   // stop timer, set prescaler 1:1, internal clock source (PBCLK3)
 TMR2 = 0x0;                    // clear timer register
 PR2 = 0xFFFF;                  // load period register
 IPC2SET = 0x0000000D;          // set priority level (IPC2<12:10>) = 3, sub-priority (IPC2<9:8>) = 1
 IFS0CLR = 0x00000200;          // clear Timer2 interrupt flag (IFS0<9>)
 IEC0SET = 0x00000200;          // enable Timer2 interrupts (IEC0<9>)
 T2CONSET = 0x8000;             // start Timer2

   while (1) {                  // main loop
  count++;                      // wait for Timer2 interrupt
  count++;
  count++;
 }
}

 
At a different breakpoint in the main loop, the debugger shows the following:
 - "count" increments, but "count2" remains at zero.
 - INTCON = 0x00005000, even though I only wrote 0x00001000 to it.  The data sheet says Bit 15 is an Unimplemented bit.
 - the Timer2_Handler address is 0x9D0005E0 (value is 0x415DE800).
 - OFF009 was initialized with 0x00000200 (other vector Offsets with 0x0000028C), so it looks like the linker is populating the Timer2 Offset register (OFF009<17:1>) okay.
 
This is my first experience with 32MZ interrupts.  Am I missing something with configuring this one?
 
 
#1
davekw7x
Entropy++
  • Total Posts : 1716
  • Reward points : 0
  • Joined: 2012/01/16 12:01:07
  • Location: Left Coast, USA
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/28 12:05:26 (permalink)
0
DougD
... Can anyone see what the problem might be?

 
Haven't checked everything, but One Thing that jumps off of the page at me:
 
    IPC2SET = 0x0000000D;  // set priority level (IPC2<12:10>) = 3, sub-priority (IPC2<9:8>) = 1

 
Point number 1: Kudos for meaningful comment.
Point number 2: It would be much less error prone if you used struct bit definitions:
    IPC2bits.T2IP = 3;
    IPC2bits.T2IS = 1;

 
Or you could use ever-so-slightly more efficient but harder-to-read, and harder-to-verify (In my Opinion), logical combinations of _MASK, _POSITION definitions and shift operators.
 
 
 
Regards,

Dave
post edited by davekw7x - 2019/01/28 12:17:53

Sometimes I just can't help myself...
#2
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/28 12:23:54 (permalink)
0
Thanks Dave.  I actually started out using struct bit definitions, but Example 14-8 uses SET and CLR instructions, and I wanted to be consistent with that to minimize the risk of error.  I checked the bit definitions pretty carefully though, so I think they're right.
 
Is there any problem with using Multi Vector (MVEC=1) interrupts like this?  Assuming I can get the Timer2 interrupt to work, I'll need to add more interrupts and would prefer having a separate ISR for each, rather than using a Single Vector (MVEC=0) for all interrupts.
 
With the __ISR_AT_VECTOR attribute, it's a great feature that the compiler and linker initialize the Vector Offset registers based on the size of the ISR code--that lets you put the entire ISR at the (variable offset) interrupt vector, without having to jump to a separate ISR.
#3
davekw7x
Entropy++
  • Total Posts : 1716
  • Reward points : 0
  • Joined: 2012/01/16 12:01:07
  • Location: Left Coast, USA
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/28 13:16:18 (permalink) ☼ Best Answerby DougD 2019/01/28 13:42:54
5 (1)
DougD
Thanks Dave.  I actually started out using struct bit definitions, but Example 14-8 uses SET and CLR instructions, and I wanted to be consistent with that to minimize the risk of error.  I checked the bit definitions pretty carefully though, so I think they're right

Really?  I mean...
 
0x0000000D has bits 0, 3, and 4 set, not the bits that your comment (as well as the data sheet) indicates that are required to do the deed!.
 
DougD
Is there any problem with using Multi Vector (MVEC=1) interrupts like this? 

No.  Here's some code from my project (uses priority 3 for Timer 2 interrupt, not priority 2):
// Millisecond timer: Period is 100 MHz divided by 32 divided by 1000
void init_timer2(void)
{
    IPC2bits.T2IP = 3;
    IPC2bits.T2IS = 1;
    T2CON = 0;
    T2CONbits.TCKPS = 0b101; // Divide-by-32
    PR2 = (PBCLK+16000) / 32000 - 1;
    IFS0bits.T2IF = 0;
    IEC0bits.T2IE = 1;
    T2CONbits.TON = 1;
}

 
and here's stuff that uses the interrupt
static volatile uint32_t milliscount;

uint32_t millis(void)
{
    return milliscount;
}

void __ISR(_TIMER_2_VECTOR, IPL3SRS) T2Interrupt(void)
{
    LED2_Toggle(); // Sets the LED2 bit in the LED2 LATINV register
    IFS0CLR = _IFS0_T2IF_MASK;
    ++milliscount;
}



From my init_system function (executed BEFORE the timer and other initialization functions):
...
 
    // Will use multi-vector interrupt service routines
    INTCONbits.MVEC = 1;
...

 
Now, if these "gentle" hints aren't enough to get your stuff running, then I suggest you post complete code (including configuration pragmas and any initialization code you are using.  (Or anything else you haven't shown.)
 
Regards,
 
Dave
post edited by davekw7x - 2019/01/28 13:24:52

Sometimes I just can't help myself...
#4
andersm
Super Member
  • Total Posts : 2576
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: online
Re: PIC32MZ interrupts won't trigger 2019/01/28 13:26:30 (permalink) ☄ Helpfulby DougD 2019/01/28 14:00:30
5 (1)
You still need to set the "Interrupt Enable" bit in the coprocessor 0 Status register. The easiest way to do this is by eg. calling the __builtin_enable_interrupts() function.
#5
andersm
Super Member
  • Total Posts : 2576
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: online
Re: PIC32MZ interrupts won't trigger 2019/01/28 13:28:38 (permalink)
0
davekw7x
// Millisecond timer: Period is 100 MHz divided by 32 divided by 1000
void init_timer2(void)
{
    IPC2bits.T2IP = 3;
    IPC2bits.T2IS = 1;
    T2CON = 0;
    T2CONbits.TCKPS = 0b101; // Divide-by-32
    PR2 = (PBCLK+16000) / 32000 - 1;
    IFS0bits.T2IF = 0;
    IEC0bits.T2IE = 1;
    T2CONbits.TON = 1;
}

Using bit fields to access self-modifying registers (like IFSx) still isn't safe.
#6
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/28 13:57:03 (permalink)
0
Dave,
 
You're absolutely right!  Example 14-8 in the PIC32 Family Reference Manual is incorrect.  They show IP2SET = 0x0000000D, when it should be 0x00000D00.
 
I had looked at the bit positions needed to set this field in the IPCx Interrupt Priority Control Register bit map (Register 7-7) several times, and made the same mistake each time--I kept overlooking the bottom row of bits.
 
When I changed it to 0x000000D00, and added the "__builtin_enable_interrupts();" line that Anders commented, the interrupt worked like a charm!
 
Thanks very much for saving me untold agony.  I'll submit a documentation error report to Microchip about the this.
 
Doug
#7
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/28 14:10:32 (permalink)
0
Anders, you were right.  I didn't know about the need to enable global interrupts with the __builtin_enable_interrupts() function.
 
It's funny how I didn't see this mentioned in either the Data sheet or the Interrupts section of the Family Reference Manual.  In fact, the only place I see it mentioned anywhere is in Section 14.9 of the XC32 Compiler User's Guide, and I had missed that.
 
The Family Reference Manual does present Example 8-3, Variable Offset Mode Initialization, and I'm still puzzled about whether or not people need to implement that code to be able to use Variable Offset Mode.
 
Thanks very much for your help.
 
Doug
#8
andersm
Super Member
  • Total Posts : 2576
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: online
Re: PIC32MZ interrupts won't trigger 2019/01/28 16:01:21 (permalink)
0
DougDYou're absolutely right!  Example 14-8 in the PIC32 Family Reference Manual is incorrect.  They show IP2SET = 0x0000000D, when it should be 0x00000D00.

The example is not wrong, it is just written for another device. The FRM is general, covering the whole family. You always have to check the details against the device-specific data sheet.
 
The startup code initializes the interrupt controller for VS mode, and initializes the offset registers, but it does not enable multivector mode. The source for the startup code is included in the pic32m-libs.zip archive installed with the compiler.
#9
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/28 16:46:44 (permalink)
0
The PIC32MZ INTCON register doesn't have any VS (Vector Spacing) bits.  I'd like to use multi-vectored mode, rather than single-vectored mode.  Is setting INTCON.MVEC=1 sufficient to tell the PIC32MZ to use multiple interrupt vectors, or do I have to also use the startup code you referenced?
 
#10
andersm
Super Member
  • Total Posts : 2576
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: online
Re: PIC32MZ interrupts won't trigger 2019/01/29 14:23:43 (permalink)
0
The runtime startup code is automatically used, unless you've explicitly disabled it, in which case you'd know about it.
#11
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/29 18:01:09 (permalink)
0
Thanks Anders, it's good to know I won't have to deal with that too.
#12
Mysil
Super Member
  • Total Posts : 3321
  • Reward points : 0
  • Joined: 2012/07/01 04:19:50
  • Location: Norway
  • Status: online
Re: PIC32MZ interrupts won't trigger 2019/01/29 22:36:39 (permalink)
0
Hi,
The PIC32MZ INTCON register doesn't have any VS (Vector Spacing) bits.

This is because MZ and MK have variable vector spacing with a separate SFR register with offset to ISR code for every interrupt.
It still have MVEC bit in INTCON register.
Make ISR specification like this:
#if defined __PIC32MZ__
void __attribute__((interrupt(IPL2SRS), at_vector(_CORE_TIMER_VECTOR), aligned(16), no_fpu))
        CoreTimerHandler(void)
#elif defined __PIC32MX__
void __ISR(_CORE_TIMER_VECTOR, IPL2SOFT) CoreTimerHandler(void)
#endif
{   ...  

Startup code will load offset address of each ISR into registers.
 
Remember to set   PRISS   register to suitable value, e.g:
    PRISS = 0x76543210ul;    /* MZ devices have 8 register sets. 7 priority levels may have a Shadow each. */   

 
    Mysil
post edited by Mysil - 2019/01/29 22:44:51
#13
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/30 13:38:41 (permalink)
0
Mysil,
 
Thanks for your comment.  I'm glad I don't have to include special CPU code in order to use the 32MZ's multi-vector interrupts.
 
If I specify that the MZ is to use multi-vector interrupts with a variable vector spacing (i.e. by setting INTCONbits.MVEC=1), what is the advantage of specifying the "aligned(16)" ISR attribute?  Would it result in faster jumps?  I think the OFFx (Interrupt Vector Address Offset Register) is already even-byte aligned.
 
It didn't occur to me to use the "no_fpu" attribute in the ISRs.  My main functions will need the fpu.  If I use the "no_fpu" attribute in an ISR (say, one that doesn't need the fpu), and that ISR is preempted by a higher-priority interrupt (one that _does_ need the fpu), would that cause a problem?
 
Doug
#14
qhb
Superb Member
  • Total Posts : 9919
  • Reward points : 0
  • Joined: 2016/06/05 14:55:32
  • Location: One step ahead...
  • Status: online
Re: PIC32MZ interrupts won't trigger 2019/01/30 14:27:14 (permalink)
0
DougD
...
  If I use the "no_fpu" attribute in an ISR (say, one that doesn't need the fpu), and that ISR is preempted by a higher-priority interrupt (one that _does_ need the fpu), would that cause a problem?

No, because THAT ISR should preserve the FPU status.
#15
DougD
Junior Member
  • Total Posts : 75
  • Reward points : 0
  • Joined: 2012/12/24 10:12:06
  • Location: 0
  • Status: offline
Re: PIC32MZ interrupts won't trigger 2019/01/31 09:44:33 (permalink)
0
Thanks, that makes sense.
#16
Jump to:
© 2019 APG vNext Commercial Version 4.5