cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Visitor
Visitor
694 Views
Registered: ‎12-10-2018

Zynq PS UART Driver in Interrupt Mode - Overrun Errors

Jump to solution

Hello All, 

I have been implementing the Xilinx UART Driver (Interrupt Mode) on Zynq 7010 platform and have started to see Overrun Errors in the Handler (under high-load serial transfers). The design is based closely on the SDK examples. However, I am a little uncertain on the best way to "begin reading again" once the data has been read. Usually the process would be as simple as clearing the approprite Interrupt register bits and reading data from the FIFO, but it seems the driver already handles this during a XUartPs_Recv(). My question is... is there a more lightweight method of performing this functionality, without conflicting with the operation of the driver? Some details of the configuration:

  • Baud Rate = 921600
  • FIFO Trigger Threshold = 60 Bytes
  • Timeout Value = 25 
  • Running freeRTOS.

I feel like calling XUartPs_Recv() after data has been read is not the best approach, but I'm struggling to find an alternative without altering the driver or writing our own lightweight version.

The Interrupt Handler:

Interrupt_Handler( void *CallBackRef, u32 Event, unsigned int EventData ){

       switch (Event) {

       case XUARTPS_EVENT_RECV_DATA:          /* FULL FIFO Buffer of data has been received */


             if ( rx_isr_fptr_data ){                                                                     
                    (*rx_isr_fptr_data)( &RxBuff[TxCount], EventData );              //Execute Rx Callback function (with data).
             }

             //Rx FIFO Empty, Start Receiving More Bytes
             XUartPs_Recv( pXUart_Periph_Driver, &RxBuff[0], trigger_threshold_isr );

             #ifdef __DEBUG_TRACE_UART_COMMS__
             xil_printf("UART_IRQ. FIFO FULL: Event Data = %d, TxCount = %d, Passed to Parser = %d \r\n", EventData, TxCount, (EventData - TxCount));
             #endif
             break;

       case XUARTPS_EVENT_RECV_TOUT:          /* Data was received, triggered By Timeout, Less than a Full Buffer    */


             if ( rx_isr_fptr_data ){                                                                     
                    ( *rx_isr_fptr_data )( &RxBuff[TxCount], EventData );                    //Execute Rx Callback function (with data)
             }

             //Rx FIFO Empty, Start Receiving More Bytes
             XUartPs_Recv( pXUart_Periph_Driver, &RxBuff[0], trigger_threshold_isr );


             #ifdef __DEBUG_TRACE_UART_COMMS__
             xil_printf("UART_IRQ. TIMEOUT: Event Data = %d, TxCount = %d, Passed To Parser = %d \r\n", EventData, TxCount, (EventData - TxCount));
             #endif
             break;

       case XUARTPS_EVENT_RECV_ERROR:         /* Data was received with an error, keep the data but determine what kind of errors occurred */

             #ifdef __DEBUG_TRACE_UART_COMMS_ERROR__
             xil_printf("============= UART_0 RX ERROR - TBC..., nBytes = %d \r\n", EventData);
             #endif
             break;
}

I should also mention that I still get the same errors when the callback function is removed (decoupling the Interrupt Handler from the rest of my system).

Any pointers greatly appreciated, 

Thanks,

Tom

0 Kudos
1 Solution

Accepted Solutions
Highlighted
Moderator
Moderator
525 Views
Registered: ‎10-06-2016

Re: Zynq PS UART Driver in Interrupt Mode - Overrun Errors

Jump to solution

Hi @tom.wilson 

I guess you can write your own cache flush function without disabling interrupts if you are confident enought that nobody will be overwriting/reading from the address range while being interrupted. In general the recommended approach would be to disable interrupts in the way we do in the standalone driver.

Regards


Ibai
Don’t forget to reply, kudo, and accept as solution.

View solution in original post

3 Replies
Highlighted
Moderator
Moderator
622 Views
Registered: ‎10-06-2016

Re: Zynq PS UART Driver in Interrupt Mode - Overrun Errors

Jump to solution

Hi @tom.wilson 

I'm not sure if I understood your approach, you mentioned that you don't want to modify the UART PS driver but then you are not using the interrupt mode example provided in the drivers. The driver already implements handlers for RX and TX operations and for RX it copies the incoming data to a buffer provided to the drivers instance.

There is no need to use XUartPs_Recv in your handler (user code) and actually XUartPs_Recv should not be used never in a interrupt handler. If you take a look to the ReceiveDataHandler function, the XUartPs_ReceiveBuffer is being used.

Regards


Ibai
Don’t forget to reply, kudo, and accept as solution.
Highlighted
Visitor
Visitor
548 Views
Registered: ‎12-10-2018

Re: Zynq PS UART Driver in Interrupt Mode - Overrun Errors

Jump to solution

Hi @ibaie ,

Finally tracked down the source of the UART Overrun errors. A call to Xil_DCacheFlushRange(INTPTR adr, u32 len) elsewhere in the system (flushing a frame buffer to a shared memory space) was entering a critical section (interrupts disabled) for too long and preventing the UART from being serviced quickly enough to empty the hard FIFO before overrunning (64 Bytes @ 921600baud = 694uS maximum service time).  

Is there any recommended way of flushing data cache without disabling interrupts? The address range for flushed memory is dedicated to the frame buffer, so no concurrent access/modify should occur. The chosen solution is to break up the cache flush into smaller blocks, but it feels like there might be a more elegant way of handling this.

I have also followed your advice and removed calls to XUartPS_Recv() from within the Handler.

Many Thanks,

Tom 

0 Kudos
Highlighted
Moderator
Moderator
526 Views
Registered: ‎10-06-2016

Re: Zynq PS UART Driver in Interrupt Mode - Overrun Errors

Jump to solution

Hi @tom.wilson 

I guess you can write your own cache flush function without disabling interrupts if you are confident enought that nobody will be overwriting/reading from the address range while being interrupted. In general the recommended approach would be to disable interrupts in the way we do in the standalone driver.

Regards


Ibai
Don’t forget to reply, kudo, and accept as solution.

View solution in original post