Re: Interrupt driven UART




Mark Borgerson wrote:
In article <1160714459.737590.239920@xxxxxxxxxxxxxxxxxxxxxxxxxxx>,
goister@xxxxxxxxx says...

CBFalconer wrote:
"goister@xxxxxxxxx" wrote:
goister@xxxxxxxxx wrote:

Hmm disregard my previous message. I think I know what you mean. I
think I can implement the fifo with a fixed array size of n, and a head
and tail index rather than pointer(both initialized to 0). The rx isr
will move a byte from the rxbuffer to the fifo head, increment the
head(wrapping back to 0 when head == n) and set the global rx ready
flag, and the receivebyte function will simply wait for the rx ready
flag set by the ISR, then move a byte from the the fifo tail to a local
variable, and increment the tail(wrapping too). Makes sense?

arg, just realized after i hit the "post" button that this might not
work if an rx interrupt occurs between the time the receivebyte
function checks for the rx ready flag, and the time where it clears the
flag. if it happens the be the last byte received in that time period,
then the receivebyte will hang there since it has cleared the flag
while the fifo is still not empty. Instead, I think a better check
would be to compare the head and tail pointers, and if they're not the
same then there's something in the fifo. so the psuedo code looks
something like this

isr() {
fifo[tail++] = rxbuffer;
if (tail == buflen) tail = 0;
}

receivebyte()
while(head == tail);
byte = fifo[head++]
if (head == buflen) head = 0;
return byte;
}

This is probably not good enough, because you need to know both
when the buffer is non-empty and when the buffer is full. The full
condition is used to make a decision on how to proceed when an
interrupt occurs, which may be either to discard the oldest or to
discard the newest, while setting an overrun flag to signify data
lost. With read and write indices into a single buffer you can
decide this with modulo arithmetic, i.e. buffer empty corresponds
to indices equal, and buffer full corresponds to write index one
less than read index. With pointers the modulo arithmetic on the
difference becomes harder.


Hmm, error checking gets complicated though because the receive buffer
is structured as a double buffer. buffer1 gets pumped into buffer2 when
all 8bits are received, and this also generates the interrupt. A buffer
overrun occurs(and appropriate status bit set in status register) when
buffer2 isn't read by the isr before all 8 bits of buffer1 are
received. only buffer2 is accessible.

So there seems to be a couple of errors I have to take care of
1) buffer overrun
2) parity error
3) frame error
4) fifo overrun error

The first 3 I can check by cpu status bits, and the 4th one I can check
by comparing indices, but I'm not sure of the order to check them, how
to organize them, and how to handle them(discarding newest and
requesting for a retransmit?). Here's how I was doing it in my receive
isr:

fifo(tail++) = buffer2;
tail&= buflen - 1;
errFlag = statusregister & mask // check for framing/parity/overrun
error
if (errFlag != 0) { // error
// pulldown I/O line to signal error and request retransmission
}

I'm wondering how the retransmission will occur. Should I have a while
loop that keeps looping within the isr to wait for the retransmission
or should i exit the isr and reenter? And then there's the fifo overrun
error case, not sure how to integrate that in either.


I wouldn't wait inside the interrupt routine for the retransmission.
You don't know how long that will take. It will be at least one
character time, though. You probably don't want to wait in the
interrupt routine that long.


Mark Borgerson

So how about this pseudocode in my ISR then

if (tail+1 == head) { // fifo overflow!
overflow_flag = 1;
// disable UART RX here and handle retransmission
junk = (unsigned char) buffer2; // clears buffer2
// enable RX here
} else { // no fifo overflow!
// check parity error from status reg here
if (parity_error) {
// disable RX here and handle retransmission
junk = (unsigned char) buffer2; // clears buffer2
// enable RX here
} else {
fifo[Tail++] = (unsigned char) buffer2;
Tail &= BUFFLEN - 1; // handles wraparound
}
}

.



Relevant Pages

  • Re: Interrupt driven UART
    ... think I can implement the fifo with a fixed array size of n, ... and the receivebyte function will simply wait for the rx ready ... when the buffer is non-empty and when the buffer is full. ... I'm wondering how the retransmission will occur. ...
    (comp.arch.embedded)
  • Re: Interrupt driven UART
    ... think I can implement the fifo with a fixed array size of n, ... and the receivebyte function will simply wait for the rx ready ... when the buffer is non-empty and when the buffer is full. ... I'm wondering how the retransmission will occur. ...
    (comp.arch.embedded)
  • Re: Interrupt driven UART
    ... think I can implement the fifo with a fixed array size of n, ... and tail index rather than pointer. ... when the buffer is non-empty and when the buffer is full. ... I'm wondering how the retransmission will occur. ...
    (comp.arch.embedded)
  • Re: Interrupt driven UART
    ... think I can implement the fifo with a fixed array size of n, ... and the receivebyte function will simply wait for the rx ready ... when the buffer is non-empty and when the buffer is full. ... I'm wondering how the retransmission will occur. ...
    (comp.arch.embedded)
  • Re: Interrupt driven UART
    ... think I can implement the fifo with a fixed array size of n, ... The rx isr ... and the receivebyte function will simply wait for the rx ready ... when the buffer is non-empty and when the buffer is full. ...
    (comp.arch.embedded)