Home arrow Support arrow Forums

Luminary Micro Forums

<< Start < Prev 1 2 Next > End >>

ChristopherNeufelt

Senior Boarder

2008/11/19 04:07

Interrupt Service Routine UART, Burst of data

Hallo
I need a solution to this problem, since I have already cover MY options.

Problem Environment:
The software is written in C, using the software driver library.
A device (slave) sends data to another device (master) and then to a personal computer (host). Both master and slave devices are the LM3S1968 evaluation boards connected with UART 0. Host connects with UART 1.
Problem definition:
Each UART has two FIFOS (Tx, Rx), each 16 byte deep. By sending continuously data to Rx FIFO, its filled up quickly and data sended remain unavailable.

There are two strategies to cope with the problem:
1. Arrange the FEN (FIFO ENABLE) bit 4 of UART Line control register (UARTLCRH) to 0 so that FIFO's are disabled and perform the interrupt routine
in a byte oriented way. This method failed to work properly.

2. A simpler strategy was to implement burst of data, with sufficient idle time between the bursts. In other words: If a device sends 100 chars, I need a method to receive them. Note: The interrupt routine sometimes needs two activations in order to operate. Any idea to optimize it?

Lets show my code:
/*******************************************************************************/
Global variables:

char StrMessage[100]; /*Temporary location for each burst of data*/
int ExitState = 0; /*This is the state of interrupt: 0 if no interrupt serviced*/
/*Structure for holding data of each burst*/
struct AcquiredData
{
char Data[100];
} Channel[18];


/*******************************************************************************/
Routines:

/*Interrupt service routine: once activated, will sample the input burst.
Limitations: Sometimes will trigger, on the second burst*/
void FunctionUARTIntHandler(void)
{
unsigned long Status;
int Index = 0;
/*Check if there is interrupt*/
Status = UARTIntStatus(UART0_BASE, UART_INT_RX | UART_INT_RT);
/*Disactivate interrupt*/
UARTIntClear(UART0_BASE, Status);
/*Loop while there are characters in the receive FIFO.*/
while(UARTCharsAvail(UART0_BASE))
{
// Read the next character from the UART and write it back to the UART.
StrMessage[Index++] = UARTCharGetNonBlocking(UART0_BASE);
}
ExitState = 1; /*Interrupt Serviced*/
return;
}

/*Routine for reception of data*/
void FunctionReceiveData(void)
{
int Index = 0; /*Counts the Channels*/
int minorIndex; /*Delay*/
FunctionEnableStatusLed(1);
UARTCharPut(UART0_BASE, 'D'); /*Trigger Slave to send burst of data*/
do
{
while(ExitState == 0)
{
if(ExitState == 1)
{
strcpy(Channel[Index].Data, StrMessage);
break;
}
}
ExitState = 0; /*Disactivate interrupt flag*/
Index++; /*point to the next element with index*/
} while(Index<18);

for(Index = 0; Index<18; Index++)
{
FunctionSendStringToMaster(Channel[Index].Data, UART1_BASE);
/*A delay in order to flush properly the TxFIFO*/
for(minorIndex = 0; minorIndex<10000; minorIndex++);
UARTCharPutNonBlocking(UART1_BASE, 0x86); /*burst separator*/
}
UARTCharPutNonBlocking(UART1_BASE, 0xA7); /*end stream seperator*/
FunctionEnableStatusLed(0);
return;
}

Thanks for any effort.
Chris

There is always light at the end of a Tunnel. Or a Train
--Anonymous

login or register to reply

slandrum

Gold Boarder

2008/11/19 15:35

Re:Interrupt Service Routine UART, Burst of data

Instead of calling UARTCharPutNonBlocking() which will not send the byte if there's no room in the UART, you can instead call UARTCharPut(), which will put the byte in the UART if there's room in the FIFO, or wait until there's room.

It seems a much better solution than putting busy-waits in your code.

Alternatively, you can check the TX FIFO status yourself before sending bytes.

login or register to reply

ChristopherNeufelt

Senior Boarder

2008/11/20 04:13

Re:Interrupt Service Routine UART, Burst of data

Any suggestion on receiving the stream of 100 bytes?

login or register to reply

slandrum

Gold Boarder

2008/11/20 11:51

Re:Interrupt Service Routine UART, Burst of data

I guess I don't understand what the problem receiving bytes is.

You can do it with interrupts, triggering on RX FIFO and RX timeout, pulling out characters from the receive FIFO when they are there.

Or you can write a loop that polls the status register and pulls bytes out whenever they are there.

I saw big problems with your tranmsit code, and large busy-waits so that you wouldn't overrun the transmit FIFO.

The thing is that you won't get all the bytes at the same time. They will come in serially, so you have to accumulate them as they come in until you've received your entire packet. If you have the FIFO interrupt level set for 8 characters (1/2 full), and enable receive FIFO and receive timeout interrupts, it will generally take about 13 interrupts for you to be able to receive all 100 bytes of the transmission.

You can set the FIFO interrupt to interrupt on receive FIFO being more full, so the total number of interrupts you process will be fewer. But you aren't ever going to be able to receive 100 bytes in one interrupt, the hardware FIFO isn't that big.

However, your CPU runs plenty fast enough to handle the queueing up of the received data in the interrupt.

Your code looks pretty confused, by the way.

login or register to reply

slandrum

Gold Boarder

2008/11/20 13:02

Re:Interrupt Service Routine UART, Burst of data

There are a bunch of problems with the code you've shown.

If you have variables that you check or set both inside and outside of interrupts, they should be declared as volatile. Otherwise, code optimizers will feel free to remove references when it looks like the variable can't change.

Additionally, in the following code:

while(ExitState == 0)
{
if(ExitState == 1)
{
strcpy(Channel[Index].Data, StrMessage);
break;
}
}
ExitState = 0; /*Disactivate interrupt flag*/


You have a loop that's only executed as long as ExitState is zero. So checking ExitState for 1 inside that loop won't do what you want.

I'm pretty sure this isn't what you want to do.

login or register to reply

ChristopherNeufelt

Senior Boarder

2008/11/21 08:36

Re:Interrupt Service Routine UART, Burst of data

Hallo to everyone!
The idea that I had for the loop
while(ExitState == 0)
{

}
is that inside the loop the interrupt will happen. When the interrupt will occur then the ExisState variable will become 1 and then will break the loop. Any solution of making this code better is always welcomed.

About volatile variables, this is something that I forgot:
The volatile modifier is used to tell the compiler that a variable may have its contents altered in ways not explicitly defined by the program (Herbert Schildt, Teach yourself C).
Since I made this terrible error I should have known that a volatile character array cannot pass as a source argument to the string copy (strcpy) function because is not a constant character pointer.

Again, I will point that I have not (but still working) found the solution to the problem, and if someone has something to offer I will be glad.

Sincerelly
Chris

login or register to reply
<< Start < Prev 1 2 Next > End >>