RX_FIFO_RD_SILENT function not working?

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

Hi,


I am running the example application CE219656 for low-level UART w/ ISR.  The part has been changed to run on the PSOC6 WiFi board.

Non-modified code works as expected.  However, for my application, I am trying to see what the latest received byte is on the RX FIFO stack before performing a FIFO read, ie I want to 'peek' before I 'pop' the FIFO.

This should be achievable by reading the  RX_FIFO_RD_SILENT register instead of the RX_FIFO_RD register in the interrupt service routine.

However, when I add this line to the ISR code:

read_data = UART_HW->RX_FIFO_RD_SILENT 

before the call to 

read_data = Cy_SCB_UART_Get(UART_HW)

the data is corrupted; ie the incorrect characters are written to the terminal.

I would suspect that adding the 

read_data = UART_HW->RX_FIFO_RD_SILENT 

should not break the code.

Am I understanding this correctly?

Thank you,
Scott

0 Likes
1 Solution
ToddD_41
Employee
Employee
First like received

You also need to clear the NVIC in the ISR. As the FIFO not empty signal is level, and the NVIC gets triggered again.

Here is the code that works for me:

void ISR_UART(void)

{

    /* Check for "RX fifo not empty interrupt" */

    if((UART_HW->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk ) != 0)

{    

       

        read_data = UART_HW->RX_FIFO_RD_SILENT;

        /* Get the character from terminal */

read_data = Cy_SCB_UART_Get(UART_HW);

       

        /* Clear UART "RX fifo not empty interrupt" */

UART_HW->INTR_RX = UART_HW->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;

        NVIC_ClearPendingIRQ(UART_SCB_IRQ_cfg.intrSrc);

        /* Update data_received flag */

        data_received = 1;       

}  

    else

    {

        /* Error if any other interrupt occurs */

        uart_error = 1;

    }

}

View solution in original post

0 Likes
3 Replies
ToddD_41
Employee
Employee
First like received

I was just reviewing this code and noticed that there is a bug in the interrupt code. Your use case caused this bug to show up.

The bug is that the RX fifo not empty interrupt is cleared before data is read out of the FIFO. In the code example the FIFO was read directly after the interrupt was cleared which I believe was fast enough to not cause the interrupt to retrigger. In your case you inserted code between the interrupt clear and the actual read, which causes the interrupt to fire again. So the ISR gets entered again which causes it to read out of an empty fifo...

To fix the issue move the interrupt clear code below the read of the FIFO:

        read_data = UART_HW->RX_FIFO_RD_SILENT;

        /* Get the character from terminal */

read_data = Cy_SCB_UART_Get(UART_HW);

       

        /* Clear UART "RX fifo not empty interrupt" */

UART_HW->INTR_RX = UART_HW->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;  

However with this code there is still an issue which causes the interrupt to fire for a different reason I haven't debugged yet. So for your use case to fully work you need to change your ISR to look like:

void ISR_UART(void)

{

    /* Check for "RX fifo not empty interrupt" */

    if((UART_HW->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk ) != 0)

{    

       

        read_data = UART_HW->RX_FIFO_RD_SILENT;

        /* Get the character from terminal */

read_data = Cy_SCB_UART_Get(UART_HW);

       

        /* Clear UART "RX fifo not empty interrupt" */

UART_HW->INTR_RX = UART_HW->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;  

        /* Update data_received flag */

        data_received = 1;       

}  

    else

    {

        /* Error if any other interrupt occurs */

        //uart_error = 1;

    }

}

I'll post back when I figure how which interrupt is causing the error code to run. My guess is that it is underflow.

0 Likes
ToddD_41
Employee
Employee
First like received

You also need to clear the NVIC in the ISR. As the FIFO not empty signal is level, and the NVIC gets triggered again.

Here is the code that works for me:

void ISR_UART(void)

{

    /* Check for "RX fifo not empty interrupt" */

    if((UART_HW->INTR_RX_MASKED & SCB_INTR_RX_MASKED_NOT_EMPTY_Msk ) != 0)

{    

       

        read_data = UART_HW->RX_FIFO_RD_SILENT;

        /* Get the character from terminal */

read_data = Cy_SCB_UART_Get(UART_HW);

       

        /* Clear UART "RX fifo not empty interrupt" */

UART_HW->INTR_RX = UART_HW->INTR_RX & SCB_INTR_RX_NOT_EMPTY_Msk;

        NVIC_ClearPendingIRQ(UART_SCB_IRQ_cfg.intrSrc);

        /* Update data_received flag */

        data_received = 1;       

}  

    else

    {

        /* Error if any other interrupt occurs */

        uart_error = 1;

    }

}

0 Likes
Anonymous
Not applicable

Thank you for your fast and detailed response!

This is indeed working as expected.

Best regards,

Scott

0 Likes