EmbeddedRelated.com
Forums

LPC2148 UART ISR issue with reception

Started by pritam March 26, 2013
Hello,

I am running modbus server on LPC2148 at a baud rate of 19200. When a modbus client is continuously polling(send a request) at a rate of 1Sec, I see delay in reception of the commands. If i stop the polling and just issue single commands at random time i dont see any delay in processing those commands.

Delay in execution of the commands happens only when other end is polling continuously.

My UART setup is as follows:

SetupUart()
{
U0LCR = 0x83;
U0DLM = 0x00;
U0DLL = 0xC0;
U0FCR = 0x87;
U0LCR = 0x03;
enableIRQ();
VICIntSelect &= ~0x00000040;
VICIntEnable |= 0x00000040;
VICVectCntl2 = 0x26;
VICVectAddr2 = (unsigned int)UART0ISR_2;
U0IER = 0X01;
}

UART ISR is as follows
void UART0ISR_2(void) // Latest working
{
unsigned char temp = 0;
unsigned char index = 0;

temp = U0RBR;

if(temp == SLAVE_ADDR)
{
get_frame = 1;
}
if(get_frame)
{
for(index = 0; index < MOD_BUS_INCOMMING_FRAME_SIZE; index ++)
{
if(temp == PRESET_SINGLE_REGISTER)
{
StatPort0(1,ON); //For debugging i switch on an led.
}
if(stUart0_Buf.RX_in1 < RX_BUF_SAFE_LIMIT)
{
stUart0_Buf.RX_array1[stUart0_Buf.RX_in1] = temp;
stUart0_Buf.RX_in1++;
frame_indx++; // increment the frame index.
}
else if(stUart0_Buf.RX_in1 >= RX_BUF_SAFE_LIMIT)
{
stUart0_Buf.RX_in1 = 0;
stUart0_Buf.RX_array1[stUart0_Buf.RX_in1] = temp;
stUart0_Buf.RX_in1++;
frame_indx++; // increment the frame index.
}

if(frame_indx == MOD_BUS_INCOMMING_FRAME_SIZE)
{
stUart0_Buf.ProcessCmnds = 1; // Indicate to process the commands
stUart0_Buf.NumberOf_frames++; //number of frames in the buffer
stUart0_Buf.RX_in1++;
get_frame = 0;
frame_indx= 0;
U0FCR |= 0x02;//Reset the RXFIFO
}
temp = U0RBR;
}
}

temp = U0IIR; // have to read this to clear the interrupt

VICVectAddr = 0;
}

void putstring_serial0 (unsigned char *string, unsigned char bufflen)
{
char ch;
char index = 0;
U0IER = 0x00; //Disble the UART reception while transmitting

U0FCR |= 0x06;//Reset the TX FIFO

while (index < bufflen)
{
putchar_serial0(string[index]);
index++;
}

U0IER = 0x01; //Enable UART reception interrupt
}
My main loop is doing nothing but just taking ADC reading and waiting for "stUart0_Buf.ProcessCmnds" flag to process commands.

Once I get a command i send a response back and while transmitting i disable any reception.

When client is polling i see a lot of delay in getting the command itself. To debug this i switch on a led and i noticed around 1-2 secs delay. I can't figure out why there is a delay in ISR and the mod bus command is only 8bytes long.

Is there something wrong with UART setup or ISR?

can some one please share some view on this.
Thanks

An Engineer's Guide to the LPC2100 Series

You need to look at your ISR routine. It is wrong I think.

what value is MOD_BUS_INCOMMING_FRAME_SIZE ?
If greater than 1 you are looping that many times filling your buffer with temp, which is read once outside the loop.

I would always be a little wary of a for loop inside an ISR routine that is processing 1 byte !

--- In l..., "pritam" wrote:
>
> Hello,
>
> I am running modbus server on LPC2148 at a baud rate of 19200. When a modbus client is continuously polling(send a request) at a rate of 1Sec, I see delay in reception of the commands. If i stop the polling and just issue single commands at random time i dont see any delay in processing those commands.
>
> Delay in execution of the commands happens only when other end is polling continuously.
>
> My UART setup is as follows:
>
> SetupUart()
> {
> U0LCR = 0x83;
> U0DLM = 0x00;
> U0DLL = 0xC0;
> U0FCR = 0x87;
> U0LCR = 0x03;
> enableIRQ();
> VICIntSelect &= ~0x00000040;
> VICIntEnable |= 0x00000040;
> VICVectCntl2 = 0x26;
> VICVectAddr2 = (unsigned int)UART0ISR_2;
> U0IER = 0X01;
> }
>
> UART ISR is as follows
> void UART0ISR_2(void) // Latest working
> {
> unsigned char temp = 0;
> unsigned char index = 0;
>
> temp = U0RBR;
>
> if(temp == SLAVE_ADDR)
> {
> get_frame = 1;
> }
> if(get_frame)
> {
> for(index = 0; index < MOD_BUS_INCOMMING_FRAME_SIZE; index ++)
> {
> if(temp == PRESET_SINGLE_REGISTER)
> {
> StatPort0(1,ON); //For debugging i switch on an led.
> }
> if(stUart0_Buf.RX_in1 < RX_BUF_SAFE_LIMIT)
> {
> stUart0_Buf.RX_array1[stUart0_Buf.RX_in1] = temp;
> stUart0_Buf.RX_in1++;
> frame_indx++; // increment the frame index.
> }
> else if(stUart0_Buf.RX_in1 >= RX_BUF_SAFE_LIMIT)
> {
> stUart0_Buf.RX_in1 = 0;
> stUart0_Buf.RX_array1[stUart0_Buf.RX_in1] = temp;
> stUart0_Buf.RX_in1++;
> frame_indx++; // increment the frame index.
> }
>
> if(frame_indx == MOD_BUS_INCOMMING_FRAME_SIZE)
> {
> stUart0_Buf.ProcessCmnds = 1; // Indicate to process the commands
> stUart0_Buf.NumberOf_frames++; //number of frames in the buffer
> stUart0_Buf.RX_in1++;
> get_frame = 0;
> frame_indx= 0;
> U0FCR |= 0x02;//Reset the RXFIFO
> }
> temp = U0RBR;
> }
> }
>
> temp = U0IIR; // have to read this to clear the interrupt
>
> VICVectAddr = 0;
> }
>
> void putstring_serial0 (unsigned char *string, unsigned char bufflen)
> {
> char ch;
> char index = 0;
> U0IER = 0x00; //Disble the UART reception while transmitting
>
> U0FCR |= 0x06;//Reset the TX FIFO
>
> while (index < bufflen)
> {
> putchar_serial0(string[index]);
> index++;
> }
>
> U0IER = 0x01; //Enable UART reception interrupt
> }
> My main loop is doing nothing but just taking ADC reading and waiting for "stUart0_Buf.ProcessCmnds" flag to process commands.
>
> Once I get a command i send a response back and while transmitting i disable any reception.
>
> When client is polling i see a lot of delay in getting the command itself. To debug this i switch on a led and i noticed around 1-2 secs delay. I can't figure out why there is a delay in ISR and the mod bus command is only 8bytes long.
>
> Is there something wrong with UART setup or ISR?
>
> can some one please share some view on this.
> Thanks
>

On 26.03.2013 06:13, pritam wrote:
> ... Is there something wrong with UART setup or ISR?

I think there is. I suggest you should think for example what happens
when one byte arrives. You get an interrupt and there is just one byte
in the UART for reading. What happens in your ISR? If I follow your code
right, the outcome would not be what you probably expect.

--

Timo

> U0FCR |= 0x02;//Reset the RXFIFO

One thing that is probably wrong, is the above.
An |= operator basically performs a read, an OR and a write.

U0FCR is a write-only register according to the datasheet.
I think you should just do U0FCR = 0x02;

Kind regards,
Bertrik

Thanks for your comments.

The value of MOD_BUS_INCOMMING_FRAME_SIZE is 8, and I have set the RX trigger level for ISR as 8 characters U0FCR = 0x87. Thats why i have a for loop in the ISR. So when 8 characters are received (in this case mod bus command) I start the for loop for storing those 8 characters.

--- In l..., "pritam" wrote:
>
> Hello,
>
> I am running modbus server on LPC2148 at a baud rate of 19200. When a modbus client is continuously polling(send a request) at a rate of 1Sec, I see delay in reception of the commands. If i stop the polling and just issue single commands at random time i dont see any delay in processing those commands.
>
> Delay in execution of the commands happens only when other end is polling continuously.
>
> My UART setup is as follows:
>
> SetupUart()
> {
> U0LCR = 0x83;
> U0DLM = 0x00;
> U0DLL = 0xC0;
> U0FCR = 0x87;
> U0LCR = 0x03;
> enableIRQ();
> VICIntSelect &= ~0x00000040;
> VICIntEnable |= 0x00000040;
> VICVectCntl2 = 0x26;
> VICVectAddr2 = (unsigned int)UART0ISR_2;
> U0IER = 0X01;
> }
>
> UART ISR is as follows
> void UART0ISR_2(void) // Latest working
> {
> unsigned char temp = 0;
> unsigned char index = 0;
>
> temp = U0RBR;
>
> if(temp == SLAVE_ADDR)
> {
> get_frame = 1;
> }
> if(get_frame)
> {
> for(index = 0; index < MOD_BUS_INCOMMING_FRAME_SIZE; index ++)
> {
> if(temp == PRESET_SINGLE_REGISTER)
> {
> StatPort0(1,ON); //For debugging i switch on an led.
> }
> if(stUart0_Buf.RX_in1 < RX_BUF_SAFE_LIMIT)
> {
> stUart0_Buf.RX_array1[stUart0_Buf.RX_in1] = temp;
> stUart0_Buf.RX_in1++;
> frame_indx++; // increment the frame index.
> }
> else if(stUart0_Buf.RX_in1 >= RX_BUF_SAFE_LIMIT)
> {
> stUart0_Buf.RX_in1 = 0;
> stUart0_Buf.RX_array1[stUart0_Buf.RX_in1] = temp;
> stUart0_Buf.RX_in1++;
> frame_indx++; // increment the frame index.
> }
>
> if(frame_indx == MOD_BUS_INCOMMING_FRAME_SIZE)
> {
> stUart0_Buf.ProcessCmnds = 1; // Indicate to process the commands
> stUart0_Buf.NumberOf_frames++; //number of frames in the buffer
> stUart0_Buf.RX_in1++;
> get_frame = 0;
> frame_indx= 0;
> U0FCR |= 0x02;//Reset the RXFIFO
> }
> temp = U0RBR;
> }
> }
>
> temp = U0IIR; // have to read this to clear the interrupt
>
> VICVectAddr = 0;
> }
>
> void putstring_serial0 (unsigned char *string, unsigned char bufflen)
> {
> char ch;
> char index = 0;
> U0IER = 0x00; //Disble the UART reception while transmitting
>
> U0FCR |= 0x06;//Reset the TX FIFO
>
> while (index < bufflen)
> {
> putchar_serial0(string[index]);
> index++;
> }
>
> U0IER = 0x01; //Enable UART reception interrupt
> }
> My main loop is doing nothing but just taking ADC reading and waiting for "stUart0_Buf.ProcessCmnds" flag to process commands.
>
> Once I get a command i send a response back and while transmitting i disable any reception.
>
> When client is polling i see a lot of delay in getting the command itself. To debug this i switch on a led and i noticed around 1-2 secs delay. I can't figure out why there is a delay in ISR and the mod bus command is only 8bytes long.
>
> Is there something wrong with UART setup or ISR?
>
> can some one please share some view on this.
> Thanks
>

On 26.03.2013 15:23, pritam wrote:
> The value of MOD_BUS_INCOMMING_FRAME_SIZE is 8, and I have set the RX
> trigger level for ISR as 8 characters U0FCR = 0x87. Thats why i have a
> for loop in the ISR. So when 8 characters are received (in this case mod
> bus command) I start the for loop for storing those 8 characters.

Ok, but then the other end must send the packets without too long delays
between bytes - otherwise you get character timeout interrupt and there
will be less than 8 bytes for reading in your ISR.

--

Timo

But as the RX trigger level is configured for 8 character. Then it should not fire the ISR on receiving single character right?

--- In l..., tike64@... wrote:
>
> On 26.03.2013 15:23, pritam wrote:
> > The value of MOD_BUS_INCOMMING_FRAME_SIZE is 8, and I have set the RX
> > trigger level for ISR as 8 characters U0FCR = 0x87. Thats why i have a
> > for loop in the ISR. So when 8 characters are received (in this case mod
> > bus command) I start the for loop for storing those 8 characters.
>
> Ok, but then the other end must send the packets without too long delays
> between bytes - otherwise you get character timeout interrupt and there
> will be less than 8 bytes for reading in your ISR.
>
> --
>
> Timo
>

On 27.03.2013 06:32, pritam wrote:
> But as the RX trigger level is configured for 8 character. Then it
> should not fire the ISR on receiving single character right?

Wrong. FIFO would then be virtually useless in any 'normal' situation.
Read about Interrupt Identification Register on User manual.

--

Timo