Loss of Interrupts

Hi, I’m stuck trying to figure out why I’m losing bytes with a UART ISR. I send and receive packets of data and rarely I’m missing a byte on the receive side. (CRC causes the message to fail.) This happens on 2 different Microchip PICs, PIC32MX460F512L and PIC32MX470F512L. I’ve gone through the PIC documenation inside and out and haven’t found any problems there. So just to be sure, I want to ask about FreeRTOS (v8.1.2). I’ve inserted the following code into port_asm.s: ~~~ .extern U2InterruptWrapper //////////////////////////////////////////////////////////////////////////////// // // UART interrupt service routine // //////////////////////////////////////////////////////////////////////////////// .set nomips16 .set noreorder .ent U2InterruptWrapper // interrupt entry point U2InterruptWrapper:
// save the current task context
portSAVE_CONTEXT

// call the C function to handle the interrupt
jal U2InterruptHandler
nop

// restore the context of the next task to execute
portRESTORE_CONTEXT
.end U2InterruptWrapper ~~~ My priority is 3, which I believe is the highest priority in the system. My PICs have 8 byte FIFOs and I’m using 115,200 BAUD which is about 83 usec per byte. With a 12.5 nsec clock time in the PIC, there should be plenty of time to read all the bytes from the FIFO. Is there something I’m missing that might cause this to lose bytes? Thanks for the new sets of eyes. Dave

Loss of Interrupts

Can’t tell from the code you posted. Please show the U2InterruptHandler code too. I remember there was some discussion on the PIC32 UART interrupts some years back. As I recall (?) it resulted from a change in the way interrupts were handled between different PIC32 part numbers. You mind find something in the forum on this.

Loss of Interrupts

Here is the receive side… ~~~ void U2InterruptHandler( void) { U8 c; static BaseType_t YieldRequired;
// look for receive interrupt
if(IFS1bits.U2RXIF)
{
    // look for more receive data
    while(U2STAbits.URXDA)
    {
        c = U2RXREG;
        *RxBufEnd = c;
        if(++RxBufEnd == (RxBuffer + BUF_SIZE))
            RxBufEnd = RxBuffer;

        // for every FS, increment the semaphore
        if(c == FS)
            // increment the task semaphore
            xSemaphoreGiveFromISR(UartRxSemaphore, &YieldRequired);

        if(U2STAbits.OERR)
            // clear overrun errors
            U2STAbits.OERR = FALSE;
    }

    // clear the receive interrupt flag
    IFS1bits.U2RXIF = FALSE;
}

... <transmit side>
} ~~~ I will search the archives. Thanks for the advice. Dave

Loss of Interrupts

Double check where the interrupt is being cleared – I think on some devices it needs to be first in the ISR, and on others last. Perhaps look at the drivers provided by Microchip for the device you are using as a reference.

Loss of Interrupts

Yes, thanks. Been there, done that. I conform to the Microchip usage. BTW, I forgot the end of the ISR function I posted above. After the transmit side at the end of the function is: ~~~
// context switch if necessary
portEND_SWITCHING_ISR(YieldRequired);
~~~ I never fully understood what this is doing. I just followed the FreeRTOS examples. The only place this is used is on the RX side when passing the (counting) semaphore from the ISR to the task. Does this make sense? Thanks again. Dave

Loss of Interrupts

I’m still having no luck tracking this down. I looked at the ISR vector table and everything appears to be normal with one thing I don’t understand. The CS0 interrupt vector is set to vPortYieldISR. I have no idea what that is, and I mentioned above that I didn’t know what the portENDSWITCHINGISR(YiedlRequired); code does. I would guess these 2 are related, but I don’t know. Is this a required part of the ISR processing? (See post above.) Thanks, Dave

Loss of Interrupts

portENDSWITCHINGISR() performs or schedules a task switch if needed (based on the YieldRequired parameter). If an ISR does not use this at the end, then if it woke up a task tthat is now the highest priority, it won’t start to execute until something else cause a task switch (like possibly the time tick). One some processors, this is performed by software triggering a lowest priority interrupt which forces the scheduler to run.

Loss of Interrupts

Hi Richard, Sorry for being dense… I’m guessing that when I do the GiveFromISR that the YieldRequired variable is loaded inside that routine. Then before I exit the ISR, the portENDSWITCHINGISR decides from the contents of YieldRequired whether or not to task switch. But also, looking the the reference manual, I see a different function portYIELDFROMISR(). Basically, I’m just looking for confirmation I’ve implemented this right and that is not the reason for missing interrupts. Thanks! Dave

Loss of Interrupts

The various ‘FromISR’ rooutines will set the value of the flag true if they wake up a higher priority task, and thus need to signal you to trigger a scheduler activation. As to the way you use the variable, from what I have seen, different ports define the mechanism in different ways. (I suspect in part based on how old they are), and some have slightly different rules for how to use these functions.

Loss of Interrupts

Thanks for the guidelines. Dave