Forum Discussion

Altera_Forum's avatar
Altera_Forum
Icon for Honored Contributor rankHonored Contributor
12 years ago

ISR driven UART is missing characters (even at 9600bps... same prob at 230400)

Any ideas on what I'm missing here that is causing me to miss characters?

I'm interfacing to a device that shoots out RS232 packets (up to 200 per second if the bps can handle itI can select the BPS, but it is always N-8-1). Right now, I have the device running (and the UART) at 9600bps and locked to 5 packets per second... although, this problem happens at 115200, 230400, and is terrible at 460800bps(which is where I need to get).

The UART seems to be missing characters, especially towards the end of the 'packets' which are around 100bytes in length. towards the front of the packet I seem to get everything and towards the 'rear' it starts to miss them... the 'ISR' itself generally takes 500ns to execute, but that doesn't include the call latency... but I can't see that being a problem at 9600bps... Also the ring-buffer is 4k in size. I have set a breakpoint so that I can debug after it gets 1024 characters and the ring-buffer is missing them... so it can't be a wrapping/overflow problem.... grrrr.

Here's how I'm setting up my code in main to test this problem:

alt_irq_init (ALT_IRQ_BASE);

alt_sys_init();

unsigned char ch;

unsigned int baudrate=9600;

UsartInit(baudrate);

UsartInit_2(baudrate);

//register the ISR handler for UART 0)

alt_ic_isr_register(UART0_IRQ_INTERRUPT_CONTROLLER_ID,

UART0_IRQ,

IsrUsart,0,0);

//register the ISR handler for UART 1

alt_ic_isr_register(UART1_IRQ_INTERRUPT_CONTROLLER_ID,

UART1_IRQ,

IsrUsart_2,0,0);

//enable Interrupts for UART 0

alt_ic_irq_enable(UART0_IRQ_INTERRUPT_CONTROLLER_ID,

UART0_IRQ);

//enable Interrupts for UART 1

alt_ic_irq_enable(UART1_IRQ_INTERRUPT_CONTROLLER_ID,

UART1_IRQ);

There there's the big 'while(1)'in main():

while (1)

{ //update heartbeat on JP5 header

jp5tracker ^= 0x01;//D0 on L.A.

IOWR_ALTERA_AVALON_PIO_DATA(JP5_BASE, jp5tracker);

while(!UsartIsEmpty_2())

{ //toggle LEDG1 when characters are processed from VN100 plugged into the HSMC-ICB

greenLEDtracker ^= 0x02;

IOWR_ALTERA_AVALON_PIO_DATA ( GLED_BASE , greenLEDtracker );

ch=GetUsart_2();

jp5tracker ^= 0x02;//D1 on L.A.

IOWR_ALTERA_AVALON_PIO_DATA(JP5_BASE, jp5tracker);

i++;//counter to set a breakpoint with

}

here's the ISR handler and some helpers for the ring buffer.

void UsartInit_2(unsigned int BaudRate_2)

{

unsigned int divisor_2;

divisor_2 = (ALT_CPU_FREQ/BaudRate_2)+1;

IOWR_ALTERA_AVALON_UART_DIVISOR(UART1_BASE, divisor_2);

IOWR_ALTERA_AVALON_UART_CONTROL(UART1_BASE, ALTERA_AVALON_UART_CONTROL_RRDY_MSK);

}

void IsrUsart_2(void* context_2, unsigned int id_2)

{

IOWR_ALTERA_AVALON_PIO_DATA(JP5_BASE, 0xFF);//inserted to time/track this routine

//grab data byte and save it

USART_RX_buffer_2[USART_RX_hd_2++] = IORD_ALTERA_AVALON_UART_RXDATA(UART1_BASE);

//move/wrap buffer pointer

if (USART_RX_buffer_2 == '*')

z_2==1;

if (USART_RX_hd_2 == USART_BUFFER_SIZE_2) USART_RX_hd_2 = 0;

USART_RX_full_2 = (USART_RX_hd_2==USART_RX_tl_2);

IOWR_ALTERA_AVALON_PIO_DATA(JP5_BASE, 0x00);//inserted to time/track this routine

}

unsigned char UsartIsEmpty_2()

{

return ((!USART_RX_full_2) && (USART_RX_hd_2==USART_RX_tl_2));

}

//this grabs a single character from the RX circular buffer.

unsigned char GetUsart_2(void)

{

unsigned char rxChar_2;

//should never call this w/o checkign status, but it may happen. this keeps

//the ring buffer sane during that sort of abuse.

if (((!USART_RX_full_2) && (USART_RX_hd_2==USART_RX_tl_2)))

return 0x00;

else

{

rxChar_2=USART_RX_buffer_2[USART_RX_tl_2++];

if (USART_RX_tl_2 == (USART_BUFFER_SIZE_2))

USART_RX_tl_2=0;

USART_RX_full_2=0;

return rxChar_2;

}

}

Anyway... if I write some debug code on a PC to send data... as long as I insert some 'sleeps' in it between characters... never misses a character... Also, I can watch the ISR's debug 'flip' of JP5 and the ISR does get called, and the circular buffer does get populated... it is just missing characters. I have verified (with a PC's serial port) that the packets are being sent properly and contain all the data.

Here's what I'm using:

DE2-115 development board(cyclone IV) with HSMC-ICB (Altera's INK)

Quartus13.0 SP1 with EDS, the UART is:

UART (RS-232 Serial Port)

Name altera_avalon_uart

Version 13.0.1.99.2

Some BSP settings:

enable_small_c_library-'checked'.... 'nocheck' for enable_gprof, enable_reduced_device_drivers, or enable_sim_optimize

'none' for sys_clk_timer, and timestamp_timer

13 Replies