Hot!PIC32MM0064GPL036 UART Rx Interrupt will not clear

Author
awolfe
Starting Member
  • Total Posts : 76
  • Reward points : 0
  • Joined: 2009/08/20 09:52:07
  • Location: Ashland, OH
  • Status: offline
2018/08/01 09:47:40 (permalink)
0

PIC32MM0064GPL036 UART Rx Interrupt will not clear

I know what you are thinking... "just remove the condition before clearing the interrupt!", right? I believe that I am. Here is the test code that I am using. Just FYI, the Print functions sends data out on the UART1 Tx for debugging.


void __ISR(_UART2_RX_VECTOR, ipl4AUTO) U2RxISR(void)
{
if (U2STAbits.PERR || U2STAbits.FERR) {
PrintString("PERR:");
PrintDecimal(U2STAbits.PERR);
PrintString(" FERR:");
PrintDecimal(U2STAbits.FERR);
PrintString("\r\n");
}

while (U2STAbits.URXDA == 1) { // Data waiting to be read
U8 dataIn = UART2_Read();
PrintString("Data:");
PrintDecimal(dataIn);
PrintString("\r\n");
}

if (U2STAbits.URXDA || U2STAbits.OERR) {
PrintDecimal(U2STAbits.URXDA);
PrintString(" ");
PrintDecimal(U2STAbits.OERR);
PrintString("\r\n");
U2STAbits.OERR = 0;
}
IFS1bits.U2RXIF = 0;
}



Once I get a UART2 interrupt my main() stops running. The interrupt never clears. In general data is not coming in that fast. I should only occasionally get data after verifying the buffer is empty, before trying to clear the interrupt. Here is U2 setup:

#define Init_U2_SLPEN 0b0 // Initialization for UART run during sleep enable
#define Init_U2_CLKSEL 0b10 // Initialization for clock source selection
#define Init_U2_OVFDIS 0b1 // Initialization for run during overflow condition mode
#define Init_U2_ON 0b1 // Initialization for UART enable
#define Init_U2_SIDL 0b1 // Initialization for Stop in Idle mode
#define Init_U2_IREN 0b0 // Initialization for IrDA Encoder/Decoder enable
#define Init_U2_RTSMD 0b1 // Initialization for request to send mode selection
#define Init_U2_WAKE 0b1 // Initialization for wake up on start bit enable
#define Init_U2_LPBACK 0b0 // Initialization for loop back mode enable
#define Init_U2_ABAUD 0b0 // Initialization for Auto-baud enable, sync on next char
#define Init_U2_RXINV 0b0 // Initialization for receive polarity inversion bit
#define Init_U2_BRGH 0b1 // Initialization for 16x(0) or 4x(1) baud clock
#define Init_U2_PDSEL 0b00 // Initialization for Parity and Data length (8bit, no parity)
#define Init_U2_STSEL 0b0 // Initialization for Stop selection bit (1 stop bit)
#define Init_U2MODE (Init_U2_SLPEN << 23 | Init_U2_CLKSEL << 17 | Init_U2_OVFDIS << 16 | Init_U2_ON << 15 | Init_U2_SIDL << 13 | Init_U2_IREN << 12 | Init_U2_RTSMD << 11 | Init_U2_WAKE << 7 | Init_U2_LPBACK << 6 | Init_U2_ABAUD << 5 | Init_U2_RXINV << 4 | Init_U2_BRGH << 3 | Init_U2_PDSEL << 1 | Init_U2_STSEL)
#define Init_U2_MASK 0 // Address Match Mask bits (8bit), Enables address match on selected bits
#define Init_U2_ADDR 0 // Automatic Address Mask bits (8bit), defines the address to use for automatic address detection
#define Init_U2_UTXISEL 0b00 // Initialization for Transmit Interrupt Mode, 00 = Interrupt is generated while the transmit buffer contains at least one empty space
#define Init_U2_UTXINV 0b0 // Initialization for transmit polarity inversion bit
#define Init_U2_URXEN 0b1 // Initialization for UART receiver enable bit
#define Init_U2_UTXBRK 0b0 // Initialization for Transmit Break bit
#define Init_U2_UTXEN 0b1 // Initialization for UART transmit enable bit
#define Init_U2_URXISEL 0b00 // Initialization for Receive Interrupt Mode, 00 = Interrupt flag bit is asserted while receive buffer is not empty
#define Init_U2_ADDEN 0b0 // Initialization for Address character detect mode enable (9-bit mode only, defined in PDSEL)
#define Init_U2STA (Init_U2_MASK << 24 | Init_U2_ADDR << 16 | Init_U2_UTXISEL << 14 | Init_U2_UTXINV << 13 | Init_U2_URXEN << 12 | Init_U2_UTXBRK << 11 | Init_U2_UTXEN << 10 | Init_U2_URXISEL << 6 | Init_U2_ADDEN << 5)
#define Init_U2BRG 16 // Initializtion for Baud Rate = (8MHz / (4 * 115.2k)) - 1, Gives actual rate of 117,647 (+2.1%). "4" in equation is from BRGH setting.
#define Init_PPS_U2_Rx 5 // Initialize the Input for U2 receive pin selection (5 = RP5 is the selected pin for the U2Rx function)
#define Init_PPS_RP6_Tx 1 // Initialize the RP6 pin to be for U2 transmit (1 = U2Tx is the selected function for the RP6 pin)


U2BRG = Init_U2BRG;
U2STA = Init_U2STA;
U2MODE = Init_U2MODE;
RPINR9bits.U2RXR = Init_PPS_U2_Rx;
RPOR1bits.RP6R = Init_PPS_RP6_Tx;




Any ideas on what to try?

A Wolfe
#1

10 Replies Related Threads

    awolfe
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2009/08/20 09:52:07
    • Location: Ashland, OH
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/08/02 05:47:02 (permalink)
    0
    Looks like I should put in a support ticket?  I am taking no response as everything looks like it should work.  I can create a work around with polling using a timer interrupt.  Just wondering why this isn't in the errata at this point if it does not work.  Can anyone else get U2Rx interrupt to clear on this chip?

    A Wolfe
    #2
    davekw7x
    Entropy++
    • Total Posts : 1571
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Left Coast, USA
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/08/03 16:54:07 (permalink)
    3.33 (3)
    Your problem is not about clearing the U2RXIF flag; it is about conflicts with other stuff.  In other words, the problem is not necessarily with the stuff you showed us.  It is in the stuff that you didn't show.  I'll give my take on it in a minute.
     
    But...
     
    First of all, as just about everyone will advise: In a "Real" program you wouldn't have a bunch of print stuff in an ISR.  But for testing, it just might be instructive.
     
    Secondly, and more important for purposes of testing: You enable the Tx interrupt but you don't show us a U2TxISR.  Also, and this is just as important: you don't  show us how your print routines interact with the U2TxISR.
     
    OK.  Let's go!
     
    So here's the first suggestion:  While learning a new chip (or a new peripheral) don't enable interrupts.  You indicated that you had some success when polling, but I'll show how I might proceed with testing the code you showed:  I made a main loop that puts the stuff from your RxISR inline:

        // In main()

        // Enable clock, timers, UART, etc...

        // Make sure there are no interrupts to confuse us mere humans
        __builtin_disable_interrupts();
        while (1) {
            if (IFS1bits.U2RXIF) {
                LED1_Toggle(); // Show some action for each received character
                if (U2STAbits.PERR || U2STAbits.FERR) {
                    printf("PERR: %u, FERR: %u\r\n",
                            U2STAbits.PERR, U2STAbits.FERR);
                }

                while (U2STAbits.URXDA == 1) { // Data waiting to be read
                    uint8_t dataIn = U2RXREG;
                    printf("Data: %c (0x%02X)\r\n", dataIn, dataIn);
                    // If you want to see the effects of overrun, implement
                    // a delay routine of some several hundres milliseconds
                    // and uncomment the following
                    //delay();
                }

                if (U2STAbits.URXDA || U2STAbits.OERR) {
                    printf("RRXDA: %u, OERR: %u\r\n",
                            U2STAbits.URXDA, U2STAbits.OERR);
                    U2STAbits.OERR = 0;
                }
                IFS1bits.U2RXIF = 0;
            } // End of routine to handle rx data
        } // End of main loop



    Note that with XC32, all you have to do is initialize UART2 to be able to use printf.  That uses the vendor-supplied write() function applied to UART2.  I hate to repeat myself, but make sure you don't have Tx interrupts enabled!  (Or, when you get some experience, you might want to implement your own version of write().)
     
    Output as I casually type a few characters: The quick brown fox
    Data: T (0x54)
    Data: h (0x68)
    Data: e (0x65)
    Data:   (0x20)
    Data: q (0x71)
    Data: u (0x75)
    Data: i (0x69)
    Data: c (0x63)
    Data: k (0x6B)
    Data:   (0x20)
    Data: b (0x62)
    Data: r (0x72)
    Data: o (0x6F)
    Data: w (0x77)
    Data: n (0x6E)
    Data:   (0x20)
    Data: f (0x66)
    Data: o (0x6F)
    Data: x (0x78)


    Next, I uncomment the delay() statement so that, if I type fast enough, it can show the effect of an overrun.
     
    I typed The quick brown fox jumps over the lazy dog as fast as I could.
    It gave the OERR message, and then I typed what the?  to show that it recovers after the overrun.  See footnote.
     
    Data: T (0x54)
    Data: h (0x68)
    Data: e (0x65)
    Data:   (0x20)
    Data: q (0x71)
    Data: u (0x75)
    Data: i (0x69)
    Data: c (0x63)
    Data: k (0x6B)
    Data:   (0x20)
    Data: b (0x62)
    RRXDA: 0, OERR: 1
    Data: w (0x77)
    Data: h (0x68)
    Data: a (0x61)
    Data: t (0x74)
    Data:   (0x20)
    Data: t (0x74)
    Data: h (0x68)
    Data: e (0x65)
    Data: ? (0x3F)


    If you can't type as fast as I can, just hold a key down (most setups repeat the character every couple of hundred milliseconds), so, with a delay of something like a second, the overrun occurs after 9 or 10 seconds.  After the overrun, release the key and start typing again.
     
    The next step is to enable the Rx interrupt (but not the Tx interrupt) in your initialization routine enable global interrupts, and put the Rx handler stuff back into the U2RxISR.  Make an empty main loop so that all of the action is in the ISR. Try it.  I got results congruent with my expectations.
     
    Bottom line: The U2RXIF flag works as it should (at least it does for me).  Both in main-line code and in an ISR.
     
    Now: How the heck are you going to use interrupts in a "Real" program?  Having an interrupt hat handles one character at a time is kind of silly (to my way of thinking).  "Real" applications use Rx interrupts to place characters in a buffer and the main program fetches from that buffer, and handles the characters appropriately.
     
    If you want to implement TxISR, that's well and good, but I really, really (really) that you don't try to use interrupt driven Tx output from inside the RxISR.
     
    Regards,
     
    Dave
     
    Footnote: unlike XC8 and XC16, XC32 does not supply any delay functions.  I usually use the CP0 timer delays, but instead of getting into that topic, I have found, heuristically, that for an 8 MHz system clock (as I perceive you are running), the following gives a delay of a little more than a second:

    // For an 8 MHz system clock, XC16 version 2.10 with optimization
    // level set to 1 gives a delay of something like 1.1 seconds
    void delay()
    {
        volatile int i, j;
        for (i = 0; i < 1000; i++) {
            for (j = 0; j < 1000; j++) {

            }
        }
    }


    Sometimes I just can't help myself...
    #3
    awolfe
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2009/08/20 09:52:07
    • Location: Ashland, OH
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/08/06 14:52:43 (permalink)
    0
    Dave,
     
    Thanks for the reply.  I am not using the Tx interrupt.  I am sending the data on UART1 Tx just for debugging.  It blocks if the buffer is full.  I know perfectly well that it would not be acceptable in a "Real" program.  The main loop is doing nothing right now and I am just focusing on the Rx interrupt.  I put the print statements in there just to debug trying to figure out why the Int Flag was not clearing.  In the application I am wanting to use the Rx interrupt to dequeue the Rx buffer, prevent overrun and process it later.
     
    Just to clarify, you got your Rx interrupt flag to clear on the exact same chip I am using?
     
    You are making a few too many assumptions!  But thanks for your time trying to help me out.

    A Wolfe
    #4
    cvm
    Super Member
    • Total Posts : 186
    • Reward points : 0
    • Joined: 2011/09/16 05:16:15
    • Location: 0
    • Status: online
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/08/06 19:58:02 (permalink)
    4 (2)
    Do you have a debugger? pickit3/icd3/etc
    put a break point in the isr, send one char, step through and watch registers of interest
     
    just an fyi for future use-
    IFS1bits.U2RXIF = 0;
    you will want to use the CLR register-
    IFS1CLR = _IFS1_U2RXIF_MASK;
    I'm sure there are many threads here that will point out why
     
    If you want help with your code, its best to submit minimal code that will reproduce your problem. There is a lot of code that cannot be seen, for example- UART2_Read() -we cannot see what that is and if incorrect for some reason, you will never get out of that isr as you will not be removing the persistent rx irq condition. We don't even know if anything gets out to the debug print.
    #5
    davekw7x
    Entropy++
    • Total Posts : 1571
    • Reward points : 0
    • Joined: 2012/01/16 12:01:07
    • Location: Left Coast, USA
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/08/07 09:45:15 (permalink)
    3.5 (2)
    awolfe
    ...
    Just to clarify, you got your Rx interrupt flag to clear on the exact same chip I am using?
     

    Actually I tested with a 32MM0064GPL028.  I can't imagine that this particular functionality would be different on the '036..
     
    Did you try your code in a loop in main() with interrupts disabled, as I showed?  That proves (to me) that the Rx interrupt flag works as it should.  Characters are echoed one at a time.
     
    If none of this helps, maybe you could post an entire program so that someone might be able to help get to the bottom of things.
     
    Bottom line: Quite often, what people don't show is more important (regarding helping us help them) than what they show.
     
    [Edit]
    You might also give us some details about how you are testing:
    Are you dumping "a few" characters from a file to a terminal emulator on your workstation and expecting each to be echoed?
        or
    Are you typing a character at a time and expecting an echo?
     
    Or what?
    [/Edit]
     
     
    Regards,
     
    Dave
     
    post edited by davekw7x - 2018/08/07 11:40:47

    Sometimes I just can't help myself...
    #6
    awolfe
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2009/08/20 09:52:07
    • Location: Ashland, OH
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/09/07 12:45:42 (permalink)
    0
    I have been gone from this for a while and have been getting by using a polling timer interrupt which checks the data ready bit.  I have come back to it now as I need the UART to interrupt and wake up the processor in sleep.
     
    We have paired this all the way down.  Nothing at all is running except the UART. No timers, no ISR's enabled, nothing.
     
    This is running in the main line:
        while (true) {
            if (IFS1bits.U2RXIF) {
                LATBbits.LATB7 = 1; // Toggle test pin
                LATBbits.LATB7 = 0;
                if (U2STAbits.URXDA) {
                    while (U2STAbits.URXDA) { // Data waiting to be read
                        if (U2STAbits.OERR == 1) {
                            U2STAbits.OERR = 0;
                        }
                        U8 dataIn = U2RXREG;
                    }
                }
               IFS1CLR = _IFS1_U2RXIF_MASK; //Clear interrupt status flag
            }
     
            WDTCONbits.WDTCLRKEY = 0x5743;
        }

     
    I am not allowed to attach and image, but the logic analyzer is toggling Port B7 continually once the first received data comes in on the UART.  There is a slight timing shift in the frequency of the toggling whenever a byte of data is received on the UART, indicating that it is servicing the data as it comes in.
     
    The initialization has not changed from the first post except the UART ISR is disabled.
     
    Finally I will mention that I tried the same thing on UART1 and it had the same behavior.

    A Wolfe
    #7
    awolfe
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2009/08/20 09:52:07
    • Location: Ashland, OH
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/09/07 13:09:08 (permalink)
    0
    Playing with it a little more...  The interrupt flag is getting cleared, but it is getting set again just a few microseconds later.  With this code it is still toggling (it does not get stuck in the last while loop):
     

            if (IFS0bits.U1RXIF) {

                Test_Point_1 = 1;

                LATBbits.LATB7 = 1;

                LATBbits.LATB7 = 0;

                if (U1STAbits.URXDA) {

                    while (U1STAbits.URXDA) { // Data waiting to be read

                        if (U1STAbits.OERR == 1) {

                            U1STAbits.OERR = 0;

                        }

                        U8 dataIn = U1RXREG;

                    }

                }

                while (IFS0bits.U1RXIF) {

                    IFS0CLR = _IFS0_U1RXIF_MASK; //Clear interrupt status flag

                }

                Test_Point_1 = 0;

            }


     
    Here is a link to the image... I can't guarantee I will leave this on my dropbox forever, but maybe someone who is allowed to will repost it in this thread.
    https://www.dropbox.com/s...l2/Logic_UART.png?dl=0

    A Wolfe
    #8
    awolfe
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2009/08/20 09:52:07
    • Location: Ashland, OH
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/09/07 13:21:07 (permalink)
    0
    Here is another interesting observation... The interrupt flag is getting set as soon as the Rx line goes low, not when the first byte is in the buffer.
     
    https://www.dropbox.com/s...oggleSetsFlag.png?dl=0

    A Wolfe
    #9
    andersm
    Super Member
    • Total Posts : 2478
    • Reward points : 0
    • Joined: 2012/10/07 14:57:44
    • Location: 0
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/09/10 14:43:27 (permalink)
    0
    Note that writing to UxSTA using bitfields (or any kind of RMW sequence) is a bad idea, since the register contains bit that are changed by both hardware and software (UTXBRK, OERR).
    #10
    awolfe
    Starting Member
    • Total Posts : 76
    • Reward points : 0
    • Joined: 2009/08/20 09:52:07
    • Location: Ashland, OH
    • Status: offline
    Re: PIC32MM0064GPL036 UART Rx Interrupt will not clear 2018/09/14 05:51:39 (permalink)
    0
    Another update: The UART settings bit WAKE, "wake up on start bit enable", was mistakenly set during start-up.  We have cleared this and it appears in the test code to have fixed the problem.  There is not a lot of documentation that I could find on the WAKE bit, but it appears that if you want to used that, you set it just before sleeping and clear it as soon as you wake up.  If you don't clear is you get a constant UART interrupt once the Rx line goes low the first time even if there is no subsequent data on the Rx line.  It was originally set without understanding how it worked.

    A Wolfe
    #11
    Jump to:
    © 2018 APG vNext Commercial Version 4.5