AnsweredChange Notification Interrupt triggered only for one time

Author
Eventhorizon.m
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2016/09/08 07:23:08
  • Location: 0
  • Status: offline
2019/01/12 14:55:06 (permalink)
0

Change Notification Interrupt triggered only for one time

Hi All
i am working on some project using PIC32MM0128GPM064 and this interrupt problem driving me crazy..
the interrupt just triggered for one time and what ever i do after that it will not fire again.
i double checked my hardware and the signal and every thing is seems OK, hear is my code:
void Setup_Interrupts(void)
{
    INTCONSET = _INTCON_MVEC_MASK; // Set Interrupt Controller for multi-vector mode.
 __builtin_enable_interrupts(); // set the CP0 status IE bit high to turn on interrupts globally.
 
 /**************************************************************************/
 INTCONbits.INT4EP = 0; // External Interrupt 4 Edge Polarity is Falling edge.
 
 IPC1bits.INT4IP = 4; // Set the interrupt priority
 IFS0bits.INT4IF = 0; // Clear External Interrupt 4 Flag.
 IEC0bits.INT4IE = 1; // Enable External Interrupt 4 (nFAULT_in).
 
 /**************************************************************************/
 CNEN0Abits.CNIE0A4 = 0; // Detects the negative transition (from ‘1’ to ‘0).
 CNEN1Abits.CNIE1A4 = 1; // Do NOT Detects the Positive transition (from ‘0’ to ‘1).
 CNCONAbits.CNSTYLE = 1; // Edge Style (detects edge transitions, CNFx bits are used for a Change Notice event)
 
 IPC2bits.CNAIP = 5; // Set the interrupt priority For Change Notification.
 IFS0bits.CNAIF = 0; // Clear CN Interrupt Flag. {Edited Comment}
 IEC0bits.CNAIE = 1; // Enable CN Interrupt (nSTALL_BEMFV_in). {Edited Comment}
 
 CNCONAbits.ON = 1; // CN is Enabled.
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/
void Setup_Ports(void)
{
 /****************************************************************************
     * Setting the Output Latch SFR(s)
     ***************************************************************************/
    LATA = 0x0000;
    LATB = 0x0000;
    LATC = 0x0000;
    LATD = 0x0000;
 
 CCP1CON2bits.OCAEN = 0; // OCM1A pin is controlled by the GPIO module.(Fixing Bug) [XXX] Bug
 //CCP2CON2Hbits.OCAEN = 0; // OCC2A pin is controlled by the GPIO module.(Fixing Bug) [XXX] Bug
 
    /****************************************************************************
     * Setting the GPIO Direction SFR(s)
     ***************************************************************************/
    TRISA = 0xFFFF; // Default all pins Inputs.
    TRISB = 0xFFFF; // Default all pins Inputs.
    TRISC = 0xFFFF; // Default all pins Inputs.
    TRISD = 0xFFFF; // Default all pins Inputs.
 
 TRISAbits.TRISA0 = 0; // Output nPWR_ON_out.
 TRISAbits.TRISA1 = 0; // Output nBRAKE_out.
 TRISAbits.TRISA7 = 0; // Output nR_LED_out.
 TRISAbits.TRISA15 = 0; // Output G_LED2_out.
 
// TRISBbits.TRISB5 = 0; // Output TP1_out.
 TRISBbits.TRISB5 = 0; // Output nSLEEP_out.
 TRISBbits.TRISB7 = 0; // Output GPO2_out.
 TRISBbits.TRISB8 = 0; // Output TP2_out.
 TRISBbits.TRISB13 = 0; // Output G_LED1_out.
 TRISBbits.TRISB14 = 0; // Output TP3_out.
 TRISBbits.TRISB15 = 0; // Output TP4_out.
 
 TRISCbits.TRISC3 = 0; // Output STEP_SRC_out.
 TRISCbits.TRISC4 = 0; // Output DIR_PWM2_out.
 TRISCbits.TRISC5 = 0; // Output STEP_PWM1_out.
 TRISCbits.TRISC6 = 0; // Output G_LED4_out.
 TRISCbits.TRISC7 = 0; // Output G_LED3_out.
 TRISCbits.TRISC9 = 0; // Output TP5_out.
 TRISCbits.TRISC10 = 0; // Output GPO1_out.
 TRISCbits.TRISC12 = 0; // Output TX_MCU_out.
 TRISCbits.TRISC13 = 0; // Output SCLK_out.
 TRISCbits.TRISC14 = 0; // Output PWM4_out.
 TRISCbits.TRISC15 = 0; // Output PWM3_out.
 
 TRISDbits.TRISD0 = 0; // Output MOSI_out.
 TRISDbits.TRISD1 = 0; // Output RESET_out.
 TRISDbits.TRISD2 = 0; // Output SCS_out.
 TRISDbits.TRISD3 = 0; // Output DIR_SCR_out.

    /****************************************************************************
     * Setting the Weak Pull Up and Weak Pull Down SFR(s)
     ***************************************************************************/
    CNPDA = 0x0000;
    CNPDB = 0x0000;
    CNPDC = 0x0000;
    CNPDD = 0x0000;
 
    CNPUA = 0x0000;
    CNPUB = 0x0000;
    CNPUC = 0x0000;
    CNPUD = 0x0000;
 
 CNPUAbits.CNPUA4 = 1; // Pullup nSTALL_BEMFV_in
 CNPUAbits.CNPUA9 = 1; // Pullup nFAULT_in
 CNPUAbits.CNPUA10 = 1; // Pullup nSWITCH_in
 CNPUCbits.CNPUC2 = 1; // Pullup nGPI4_in
 CNPUCbits.CNPUC11 = 1; // Pullup nGPI3_in
 CNPUDbits.CNPU4 = 1; // Pullup MISO_out [XXX] Bug CNPU4 must be CNPUD4.
 
    /****************************************************************************
     * Setting the Open Drain SFR(s)
     ***************************************************************************/
    ODCA = 0x0000;
    ODCB = 0x0000;
    ODCC = 0x0000;
    ODCD = 0x0000;
 
    /****************************************************************************
     * Setting the Analog/Digital Configuration SFR(s)
     ***************************************************************************/
 
 ANSELA = 0; // Default all pins to digital.
 ANSELB = 0; // Default all pins to digital.
 ANSELD = 0; // Default all pins to digital.
 
 ANSELAbits.ANSA11 = 1; // AN_IN.
 ANSELBbits.ANSB4 = 1; // AN_VDC_BUS.
 ANSELCbits.ANSC8 = 1; // AN_BEMF.
 
 /****************************************************************************
     * Remaping The I/O Pins
     ***************************************************************************/
 
 __builtin_disable_interrupts();
 SYSKEY = 0; // Force lock.
 SYSKEY = 0xAA996655; // Unlock sequence1.
 SYSKEY = 0x556699AA; // Unlock sequence2.

 RPINR1bits.INT4R = 0b11000; // RA9 Pin is an External Interrupt 4 Pin (As nFAULT_in).

 SYSKEY = 0; // relock.
 __builtin_enable_interrupts();
}

//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~/ Driver STALL_BEMFV pin asserting ISR. {Edited Comment}
void __ISR(_CHANGE_NOTICE_A_VECTOR) CN_Interrupts(void)
{
 IFS0bits.CNAIF = 0;
 AA_UL3++;
}

 
The Variable (AA_UL3) never goes above 1!
Did i miss something?
post edited by Eventhorizon.m - 2019/01/13 00:20:41
#1
andersm
Super Member
  • Total Posts : 2503
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/12 15:16:50 (permalink) ☼ Best Answerby Eventhorizon.m 2019/01/13 02:34:34
5 (1)
See section 10.7 of the datasheet.
CNFx bits must be cleared in software to get the next Change Notification interrupt.

Also, never use bit fields to write to registers that can be modified by the hardware (eg. IFS0bits). Instead, use the atomic SET/CLR/INV registers.
#2
Eventhorizon.m
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2016/09/08 07:23:08
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/12 22:13:57 (permalink)
0
Hi andersm
thanks for your appreciated advice, i did it but nothing changed, by the way, why i have to used the atomic SET/CLR/INV registers to write to a hardware changeable registers?
#3
cvm
Super Member
  • Total Posts : 215
  • Reward points : 0
  • Joined: 2011/09/16 05:16:15
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/13 01:10:43 (permalink) ☄ Helpfulby Eventhorizon.m 2019/01/13 02:34:40
5 (1)
Here is my quick test of change notification irq's on a pic32mm0256gpm064-
#include <cstdint>
#include "Pins.hpp"
#include "Osc.hpp"
#include "Irq.hpp"

struct Leds {
    void update(){
        for(auto& i : m_rgb) i.off();
        m_rgb[m_state++].on();
        if(m_state == 3) m_state = 0;
    }
    private:
    uint8_t m_state{0};
    Pins m_rgb[3]{
        {Pins::D1, Pins::OUT},
        {Pins::C3, Pins::OUT},
        {Pins::C15, Pins::OUT}
    };
};
Leds leds;
Pins sw3{ Pins::C4, Pins::INPU };

int main()
{
    //set osc to 24MHz
    Osc osc;
    osc.pll_set(osc.MUL12, osc.DIV4);
    //set sw3 to icn falling, and enable
    sw3.icn_falling();
    sw3.icn( true );
    //enable cn irq, and global
    Irq::init( Irq::CHANGE_NOTICE_C, 1, 0, true );
    Irq::global( true );
    //let irq do its work
    for(;;){ Osc::idle(); }
}

//pin C4 (sw3)
ISR( CHANGE_NOTICE_C ){
    Irq irq;
    irq.flag_clr( irq.CHANGE_NOTICE_C );
    sw3.icn_flagclr(); //<--need to clear this flag also
    leds.update();
}

Notice you need to clear the icn flag of the pin.
This code gets me the rgb lights changing with each sw3 press, so works.
This also shows the benefits of c++- this took very little time to test and it worked the first time (I'm not sure I have tested my cn code before this, but I guess it is correct)
#4
Eventhorizon.m
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2016/09/08 07:23:08
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/13 02:15:03 (permalink)
0
Thank you very much cvm your help is very appreciated...
The problem was that i didn't clear the event bit for this particular pin, i just added (CNFAbits.CNFA4 = 0;) to my ISR and everything works well, to clear two flags for one interrupt is some how confusing especially if you are awake for 20 hours!, you clear one flag and you think you did the jop sad: sad
 
By the way, your code is nice, i never coded in C++ before, do you find it much better than C, and where did you get the libraries you used in the example?, dose coding in C is better in performance or not?
#5
Eventhorizon.m
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2016/09/08 07:23:08
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/13 02:37:34 (permalink)
0
Very sorry andersm, your answer was right too, i was always reading CNFx in the datasheet and thinking it is the same as CNxIF Flag sad: sad what a stupid.
Thanks again.
#6
andersm
Super Member
  • Total Posts : 2503
  • Reward points : 0
  • Joined: 2012/10/07 14:57:44
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/13 03:54:46 (permalink) ☄ Helpfulby Eventhorizon.m 2019/01/13 03:56:59
5 (1)
Eventhorizon.mwhy i have to used the atomic SET/CLR/INV registers to write to a hardware changeable registers?

When you use bit fields, the compiler will generate code like this:
1. temp = hw_register;
2. temp &= ~mask;
3. hw_register = temp;

If the register changes after step 1 (eg. some other interrupt bit becomes set in IFSx), you will overwrite the new value with old data. When you use SET/CLR/INV, you will only modify the bits you specify.
#7
Eventhorizon.m
New Member
  • Total Posts : 11
  • Reward points : 0
  • Joined: 2016/09/08 07:23:08
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/13 03:58:41 (permalink)
0
Thanks a lot andersm, you are the best.
#8
cvm
Super Member
  • Total Posts : 215
  • Reward points : 0
  • Joined: 2011/09/16 05:16:15
  • Location: 0
  • Status: offline
Re: Change Notification Interrupt triggered only for one time 2019/01/13 10:40:10 (permalink)
0
By the way, your code is nice, i never coded in C++ before, do you find it much better than C, and where did you get the libraries you used in the example?, dose coding in C is better in performance or not?
I bought a Pic32MM USB Curiosity Board, and got out the datasheet. Wrote 'drivers' for every chapter in the datasheet (and did not use the xc header file)- everything in c++ because I wanted to see what it could do (or wanted to see if I could use it in a micro). Including usb. I also end up with almost exclusive use of the SET/CLR registers when dealing with hardware registers as a template takes care of dealing with setting/clearing bits.
 
 
My only previous experience in c++ was a few more or less simple pc type projects, including writing a linux graphics 'frambeuffer server' using the Anti-Grain Geometry library (its mostly templates- nothing like diving into the deep end right away). I started to see the benefits of c++ and I think my coding is better in c++. I end up thinking more clearly about the problem I want to solve, organize my code better, and just end up with code that usually works the first time (minus the punctuation errors which seem to happen 1 out of every 20 keys pressed).
 
Overall there is some cost to using c++ in terms of code size and ultimately a little speed, but these are not pic10's so for me any little size/speed penalty is totally worth it as I never find myself using any micro to its capacity anyway.
 
Here is my github code-
https://github.com/cv007/PIC32MM_Curiosity_CPP
I'm sure the whole thing could also be done in c, but I don't think the result would be half as good or readable- I think everything becomes a little awkward when trying to fit c++ style into c.
 
I should also add, I simply cannot use most manufacturers code as I end up going in circles trying to figure out what they are doing- jumping from header to header, trying to figure out what some define/macro is doing, etc. So I just end up doing everything myself, and the result is I usually have a good handle on what is happening under the hood. Mostly.
#9
Jump to:
© 2019 APG vNext Commercial Version 4.5