UART3 interrupt handler is not receiving the complete string There is a string of 43bytes send to UART3 of ARM LPC2378 UART3 handler is Rxing only first 16bytes properly and immediately afterwords it reads last 5bytes of the string. Rest of the (middle)characters are not read. Why is not reading all the 43characters in order.
char UART3_init(void) { PCONP |= 0x03401000; PINSEL0 |= 0x0000000A; /* Enable TxD3 RxD3 P0.0 & P0.1 Respectively */ U3IER = 0;
U3FDR = 0; U3LCR = 0x83; U3DLL = 78; U3DLM = 0x00; U3LCR = 0x03; U3FCR = 0x07;
if ( install_irq( UART3_INT, (void *)UART3Handler, SEC_PRIORITY ) == FALSE ) { return (FALSE); }
U3IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART3 interrupt */ return (TRUE); }
Here are some tips:
Use the PRE tags when posting code so it's readable.
Provide ALL the code related to the question, like the interrupt handler code, and the code sending the string.
char UART3_init(void) { PCONP |= 0x03401000; PINSEL0 |= 0x0000000A; /* Enable TxD3 RxD3 P0.0 & P0.1 Respectively */ U3IER = 0; U3FDR = 0; U3LCR = 0x83; U3DLL = 78; U3DLM = 0x00; U3LCR = 0x03; U3FCR = 0x07; if ( install_irq( UART3_INT, (void *)UART3Handler, SEC_PRIORITY ) == FALSE ) { return (FALSE); } U3IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART3 interrupt */ return (TRUE); }
If I remember correctly, without locating the datasheet, the UART has a 16-character receive FIFO. Your code most react fast enough and eat out data from the receive FIFO before it overflows or you will lose characters.
In that case UART0 is working fine which is connected to PC , it is able to Rx data of more than 20 bytes correctly, UART0 IRQ handler and UART3 IRQ handler are same, then why UART3 is missing the some data. Is there something related to U3FCR which im not clearing at the right location in the code. becoz i have cleared the FIFO (U3FCR |= 0x02) but it doesn't work. UART3 work fine if the data is less than 20 bytes but it doesnot work if the data string is more than 40 bytes as posted earlier.
Well, no one can really know much about your issue since you haven't felt a need to post any source code of your ISR. And you haven't given any information why you think your ISR is fast enough and takes care of all required work, leaving the UART ready to accept more data.
UART3 hanndler IRQ
void main() { UART3_init(); while(1) { if(flag.EOL_PC == 1) // flag.EOL_PC is defined volatile bit field { int i; for(i=0;i<47;i++) { printf("U3Rx[%d]%c",i,UART3_Slave_Buffer[i]); } flag.EOL_PC = 0; } } } char UART3_init(void) { PCONP |= 0x03401000; PINSEL0 |= 0x0000000A; /* Enable TxD3 RxD3 P0.0 & P0.1 Respectively */ U3IER = 0; U3FDR = 0; U3LCR = 0x83; U3DLL = 78; U3DLM = 0x00; U3LCR = 0x03; U3FCR = 0x07; if ( install_irq( UART3_INT, (void *)UART3Handler, SEC_PRIORITY ) == FALSE ) { return (FALSE); } U3IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART3 interrupt */ return (TRUE); } void UART3Handler (void) __irq { volatile unsigned char IIRValue,LSRValue; while (((IIRValue = U3IIR) & 0x01) == 0) // Repeat while there is at least one interrupt source. { switch (IIRValue & 0x0E) { case 0x06: LSRValue = U3LSR; if(LSRValue & (LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI)) { VICVectAddr = 0; return; } if(LSRValue & LSR_RDR) { UART3_Slave_Buffer[UART3_RXD_Data_Counter] = U3RBR } break; case 0x04: // Receive Data Available case 0x0C: // Character Time-Out UART3_Slave_Buffer[UART3_RXD_Data_Counter] = U3RBR; break; default: break; } if(UART3_Slave_Buffer[UART3_RXD_Data_Counter] == 'U') { UART3_RXD_Data_Counter = 0; UART3_Slave_Buffer[UART3_RXD_Data_Counter] = 'U'; U3IER = IER_RBR | IER_RLS; // Re-enable receive interrupt } */ if(UART3_Slave_Buffer[0] == ':') { UART3_RXD_Data_Counter++; if(UART3_Slave_Buffer[UART3_RXD_Data_Counter-1] == '.') { flag.EOL_PC = 1; UART3_RXD_Data_Counter = 0; U3IER = IER_RBR | IER_RLS; // Re-enable receive interrupt } if( UART3_RXD_Data_Counter == MAX_BUFF ) UART3_RXD_Data_Counter = 0; } } VICVectAddr = 0; // Acknowledge Interrupt }//End of serial interrupt UART3
when i printf U3RX[] buffer after setting the bit, it prints first 16bytes and last 5 bytes of the 43bytes string. Rest of the (middle)characters are not read. String has total 43 bytes.
void main() { UART3_init(); while(1) { if(flag.EOL_PC == 1) // flag.EOL_PC is defined volatile bit field { int i; for(i=0;i<47;i++) { printf("U3Rx[%d]%c",i,UART3_Slave_Buffer[i]); } flag.EOL_PC = 0; } } } char UART3_init(void) { PCONP |= 0x03401000; PINSEL0 |= 0x0000000A; /* Enable TxD3 RxD3 P0.0 & P0.1 Respectively */ U3IER = 0; U3FDR = 0; U3LCR = 0x83; U3DLL = 78; U3DLM = 0x00; U3LCR = 0x03; U3FCR = 0x07; if ( install_irq( UART3_INT, (void *)UART3Handler, SEC_PRIORITY ) == FALSE ) { return (FALSE); } U3IER = IER_RBR | IER_THRE | IER_RLS; /* Enable UART3 interrupt */ return (TRUE); } void UART3Handler (void) __irq { volatile unsigned char IIRValue,LSRValue; while(((IIRValue = U3IIR) & 0x01) == 0)// Repeat while there is at least one interrupt src { switch (IIRValue & 0x0E) { case 0x06: LSRValue = U3LSR; if(LSRValue &(LSR_OE|LSR_PE|LSR_FE|LSR_RXFE|LSR_BI)) { VICVectAddr = 0; return ; } if(LSRValue & LSR_RDR) { UART3_Slave_Buffer[UART3_RXD_Data_Counter] = U3RBR; } break; case 0x04: // Receive Data Available case 0x0C: // Character Time-Out UART3_Slave_Buffer[UART3_RXD_Data_Counter] = U3RBR; break; default: break; } if(UART3_Slave_Buffer[UART3_RXD_Data_Counter] == 'U') { UART3_RXD_Data_Counter = 0; UART3_Slave_Buffer[UART3_RXD_Data_Counter] = 'U'; U3IER = IER_RBR | IER_RLS; // Re-enable receive interrupt } */ else if(UART3_Slave_Buffer[0] == ':') { UART3_RXD_Data_Counter++; if(UART3_Slave_Buffer[UART3_RXD_Data_Counter-1] == '.') { flag.EOL_PC = 1; UART3_RXD_Data_Counter = 0; U3IER = IER_RBR | IER_RLS; // Re-enable receive interrupt } if( UART3_RXD_Data_Counter == MAX_BUFF ) UART3_RXD_Data_Counter = 0; } } VICVectAddr = 0; // Acknowledge Interrupt }//End of serial interrupt UART3
1) Don't you like comments? You think it is good with magical values in the code? It is only 0x04 and 0x0C you seem to have documented - and these two comments seems to be a copy/paste from reference code.
2) You have problems with buffer overruns - or at least with lost characters. But you still don't care about the OE (Overrun Error) bit in the LSR (Line Status Register). Aren't you interested if this bit is set or not? You think it would give you too much hints what is wrong if you find this bit set?
3) If your receive buffer goes full for some reason, you just zero the character counter without somehow setting any flag or in any other way inform your program that this have happened. Why not? Don't like debug help like that?
4) You have a "default" in your switch statement that doesn't do anything - but the code after the switch statement is written based on the assumption that you always have received a character. Remember that your init code did turn on IER_THRE which mean the processor wants to create an interrupt to full the UART with outgoing data too - something your interrupt handler doesn't support.
5) You have code like:
U3IER = IER_RBR | IER_RLS; // Re-enable receive interrupt
So are there other code sections somewhere that disables the receive interrupt?
6) You have a main loop containing:
for(i=0;i<47;i++)
But where have you maked sure that the received message really has that size? Do you just assume it, just because you assume that is the size the sending side would send? Anyone ever told you assumptions are bad, and tends to hurt?
7) I don't see that you have any code in your ISR that tries to count how many characters you manage to pick up in a single interrupt - which would have been interesting information given that the receive FIFO have a limited size and debuging of your code should show that you are always way faster reading out data than what data comes in.
8) You have local variables inside your ISR that is declared volatile - why? You understand the meaning of the volatile keyword? So then tell me why you think you need it for your local variables.
9) How can you be sure that the UART doesn't receive the first characters of the next message before your main loop have had time to print the full set of characters from the previous message? Your ISR doesn't look at the flag.EOL_PC flag to verify if the buffer is free to be filled with new data.
There are probably other issues hidden there too, but above should be enough for you to start actually doing a bit of debugging.