Hi,
I'm working with a Toshiba TMP91 series MCU that doesn't seem to have
any UART control/status bits to check for empty data register, rx/tx
ready, etc, but does have interrupt vectors for serial tx and rx, which
is why I think I have to use interrupt driven UART rather than polling
it.
I have functions that expect to receive and send a single byte by
calling receivebyte and sendbyte functions. However, since it's
interrupt based, receivebyte seems to be pretty redundant. What I have
now is a UART receive ISR that first does error checking, then copies
the rx buffer to a global rx byte variable, and setting a global
rx_ready flag to 1. Then my receivebyte function does nothing until the
rx ready flag is set, after which it just clears it. Does this make
sense?
Reply by Ico●October 12, 20062006-10-12
goister@gmail.com <goister@gmail.com> wrote:
> Hi,
> I'm working with a Toshiba TMP91 series MCU that doesn't seem to have
> any UART control/status bits to check for empty data register, rx/tx
> ready, etc, but does have interrupt vectors for serial tx and rx, which
> is why I think I have to use interrupt driven UART rather than polling
> it.
>
> I have functions that expect to receive and send a single byte by
> calling receivebyte and sendbyte functions. However, since it's
> interrupt based, receivebyte seems to be pretty redundant. What I have
> now is a UART receive ISR that first does error checking, then copies
> the rx buffer to a global rx byte variable, and setting a global
> rx_ready flag to 1. Then my receivebyte function does nothing until the
> rx ready flag is set, after which it just clears it. Does this make
> sense?
This might work, but imagine what would happen if a byte is received on the
uart while your code happens to be doing something else then calling the
uart_receive function ? Instead of having only one 'global rx variable',
consider using a ringbuffer aka 'circular buffer' aka fifo for this. The RX
interrupt stores incoming bytes into the buffer and updates the head and tail
pointers, while your uart_receive function reads one byte from the buffer, or -
if the buffer is empty - waits until new data comes available.
--
:wq
^X^Cy^K^X^C^C^C^C
Reply by gois...@gmail.com●October 12, 20062006-10-12
Ico wrote:
> goister@gmail.com <goister@gmail.com> wrote:
> > Hi,
> > I'm working with a Toshiba TMP91 series MCU that doesn't seem to have
> > any UART control/status bits to check for empty data register, rx/tx
> > ready, etc, but does have interrupt vectors for serial tx and rx, which
> > is why I think I have to use interrupt driven UART rather than polling
> > it.
> >
> > I have functions that expect to receive and send a single byte by
> > calling receivebyte and sendbyte functions. However, since it's
> > interrupt based, receivebyte seems to be pretty redundant. What I have
> > now is a UART receive ISR that first does error checking, then copies
> > the rx buffer to a global rx byte variable, and setting a global
> > rx_ready flag to 1. Then my receivebyte function does nothing until the
> > rx ready flag is set, after which it just clears it. Does this make
> > sense?
>
> This might work, but imagine what would happen if a byte is received on the
> uart while your code happens to be doing something else then calling the
> uart_receive function ? Instead of having only one 'global rx variable',
> consider using a ringbuffer aka 'circular buffer' aka fifo for this. The RX
> interrupt stores incoming bytes into the buffer and updates the head and tail
> pointers, while your uart_receive function reads one byte from the buffer, or -
> if the buffer is empty - waits until new data comes available.
>
Thanks. I hadn't thought of that case since I'm only running the UART
at 9600bps, but I guess better safe than sorry. To implement the fifo,
wouldn't I need to either make a linked list and malloc/free in the
ISR, or use a fixed array but with compression? Either way it seems
like a lot of clock cycles will be taken up in the ISR trying to manage
the FIFO, and I'm concerned with the timing of things due to these
clock cycles used.
Reply by gois...@gmail.com●October 12, 20062006-10-12
Ico wrote:
> goister@gmail.com <goister@gmail.com> wrote:
> > Hi,
> > I'm working with a Toshiba TMP91 series MCU that doesn't seem to have
> > any UART control/status bits to check for empty data register, rx/tx
> > ready, etc, but does have interrupt vectors for serial tx and rx, which
> > is why I think I have to use interrupt driven UART rather than polling
> > it.
> >
> > I have functions that expect to receive and send a single byte by
> > calling receivebyte and sendbyte functions. However, since it's
> > interrupt based, receivebyte seems to be pretty redundant. What I have
> > now is a UART receive ISR that first does error checking, then copies
> > the rx buffer to a global rx byte variable, and setting a global
> > rx_ready flag to 1. Then my receivebyte function does nothing until the
> > rx ready flag is set, after which it just clears it. Does this make
> > sense?
>
> This might work, but imagine what would happen if a byte is received on the
> uart while your code happens to be doing something else then calling the
> uart_receive function ? Instead of having only one 'global rx variable',
> consider using a ringbuffer aka 'circular buffer' aka fifo for this. The RX
> interrupt stores incoming bytes into the buffer and updates the head and tail
> pointers, while your uart_receive function reads one byte from the buffer, or -
> if the buffer is empty - waits until new data comes available.
>
>
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?
Reply by CBFalconer●October 12, 20062006-10-12
Ico wrote:
> goister@gmail.com <goister@gmail.com> wrote:
>
>> I'm working with a Toshiba TMP91 series MCU that doesn't seem to
>> have any UART control/status bits to check for empty data
>> register, rx/tx ready, etc, but does have interrupt vectors for
>> serial tx and rx, which is why I think I have to use interrupt
>> driven UART rather than polling it.
>>
>> I have functions that expect to receive and send a single byte by
>> calling receivebyte and sendbyte functions. However, since it's
>> interrupt based, receivebyte seems to be pretty redundant. What I
>> have now is a UART receive ISR that first does error checking,
>> then copies the rx buffer to a global rx byte variable, and
>> setting a global rx_ready flag to 1. Then my receivebyte function
>> does nothing until the rx ready flag is set, after which it just
>> clears it. Does this make sense?
>
> This might work, but imagine what would happen if a byte is received
> on the uart while your code happens to be doing something else then
> calling the uart_receive function ? Instead of having only one
> 'global rx variable', consider using a ringbuffer aka 'circular
> buffer' aka fifo for this. The RX interrupt stores incoming bytes
> into the buffer and updates the head and tail pointers, while your
> uart_receive function reads one byte from the buffer, or - if the
> buffer is empty - waits until new data comes available.
Reply by gois...@gmail.com●October 12, 20062006-10-12
goister@gmail.com 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;
}
Reply by gois...@gmail.com●October 12, 20062006-10-12
CBFalconer wrote:
> Ico wrote:
> > goister@gmail.com <goister@gmail.com> wrote:
> >
> >> I'm working with a Toshiba TMP91 series MCU that doesn't seem to
> >> have any UART control/status bits to check for empty data
> >> register, rx/tx ready, etc, but does have interrupt vectors for
> >> serial tx and rx, which is why I think I have to use interrupt
> >> driven UART rather than polling it.
> >>
> >> I have functions that expect to receive and send a single byte by
> >> calling receivebyte and sendbyte functions. However, since it's
> >> interrupt based, receivebyte seems to be pretty redundant. What I
> >> have now is a UART receive ISR that first does error checking,
> >> then copies the rx buffer to a global rx byte variable, and
> >> setting a global rx_ready flag to 1. Then my receivebyte function
> >> does nothing until the rx ready flag is set, after which it just
> >> clears it. Does this make sense?
> >
> > This might work, but imagine what would happen if a byte is received
> > on the uart while your code happens to be doing something else then
> > calling the uart_receive function ? Instead of having only one
> > 'global rx variable', consider using a ringbuffer aka 'circular
> > buffer' aka fifo for this. The RX interrupt stores incoming bytes
> > into the buffer and updates the head and tail pointers, while your
> > uart_receive function reads one byte from the buffer, or - if the
> > buffer is empty - waits until new data comes available.
>
> The OP will also need to implement some sort of critical section in
> either case. I imagine this will be most easily implmented by
> controlling the interrupt enable.
>
> Lacking the data ready signal he will not be able to handle a data
> overrun during buffer emptying. Lack of those signals sounds
> ridiculous, maybe he should look again in his data sheets.
>
> --
The receiving buffer is double buffered. According to the datasheet,
when the last received bit is stored in buffer1, the stored data is
transferred to buffer2(which is CPU accessible), and this causes the rx
interrupt to be generated, and I'm using this rx interrupt to call my
receive isr. Also, if buffer2 is not read before all bits of the next
data are received by buffer1 and overrun error occurs and the overrun
status bit is set. buffer1 will then be lost, but buffer2 will be
preserved. Seems to me like buffer1 is just a temp buffer while buffer2
is the one that I read. The checking of overrun and tx/rx ready seems
to be done automatically and only accessible via interrupts rather than
having specific CPU accessible status register bits, so that's what I
mean in my original post, i.e. a polling based UART doesn't seem
possible.
Reply by CBFalconer●October 12, 20062006-10-12
"goister@gmail.com" wrote:
> goister@gmail.com 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.
--
Some informative links:
<news:news.announce.newusers
<http://www.geocities.com/nnqweb/>
<http://www.catb.org/~esr/faqs/smart-questions.html>
<http://www.caliburn.nl/topposting.html>
<http://www.netmeister.org/news/learn2quote.html>
<http://cfaj.freeshell.org/google/>
Reply by Paul Keinanen●October 12, 20062006-10-12
On Thu, 12 Oct 2006 04:53:04 -0400, CBFalconer <cbfalconer@yahoo.com>
wrote:
>The OP will also need to implement some sort of critical section in
>either case. I imagine this will be most easily implmented by
>controlling the interrupt enable.
Not really.
The two error situations with a ring buffer without critical section
is that you get a premature "buffer full" when writing to the buffer,
when there actually was one free byte in buffer (=extend the buffer by
one byte) or you get "buffer empty", when actually one more byte would
be available (=in a polling system read the byte at next poll).
This is valid for buffers less than 256 bytes for 8 bit data bus
systems and 64 KiB buffers in 16 bit data bus systems.
Paul
Reply by Mark Borgerson●October 12, 20062006-10-12
In article <1160642892.522507.50970@c28g2000cwb.googlegroups.com>,
goister@gmail.com says...
>
> Ico wrote:
> > goister@gmail.com <goister@gmail.com> wrote:
> > > Hi,
> > > I'm working with a Toshiba TMP91 series MCU that doesn't seem to have
> > > any UART control/status bits to check for empty data register, rx/tx
> > > ready, etc, but does have interrupt vectors for serial tx and rx, which
> > > is why I think I have to use interrupt driven UART rather than polling
> > > it.
> > >
> > > I have functions that expect to receive and send a single byte by
> > > calling receivebyte and sendbyte functions. However, since it's
> > > interrupt based, receivebyte seems to be pretty redundant. What I have
> > > now is a UART receive ISR that first does error checking, then copies
> > > the rx buffer to a global rx byte variable, and setting a global
> > > rx_ready flag to 1. Then my receivebyte function does nothing until the
> > > rx ready flag is set, after which it just clears it. Does this make
> > > sense?
> >
> > This might work, but imagine what would happen if a byte is received on the
> > uart while your code happens to be doing something else then calling the
> > uart_receive function ? Instead of having only one 'global rx variable',
> > consider using a ringbuffer aka 'circular buffer' aka fifo for this. The RX
> > interrupt stores incoming bytes into the buffer and updates the head and tail
> > pointers, while your uart_receive function reads one byte from the buffer, or -
> > if the buffer is empty - waits until new data comes available.
> >
> >
> 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?
>
>
That's the general scheme. There are a few details to consider:
1. why not keep a counter of the bytes in the queue rather than
a simple flag. That way, if your main application goes away
for a long time, it can note that there are many byte in the
buffer, rather than just an indication that one or more
bytes are available.
2. You may need to keep track of the possibility of queue
overflow.
3. An oft-used trick for circular buffers is to make the
buffer length an exact power of two. Then you can
skip the wraparound test and simply mask the index with
an appropriate value to accomplish the wraparound.
#define BUFFERLENGTH 64
unsigned char buffer[BUFFERLENGTH];
short bufInputIndex, bufInputAvailable;
//
// add character to buffer and wrap as required
buffer[bufInputIndex++] = ch;
bufInputAvailable++;
bufInputIndex &= (BUFFERLENGTH-1); // masking handles wrap
You can find the source code for a ring buffer, interrupt
driven, serial handler at www.oes.to. Look for the
U4SCFX library link. The code is for an M68K system, but
the source is pretty generic C.
Mark Borgerson
Signal Processing Engineer Seeking a DSP Engineer to tackle complex technical challenges. Requires expertise in DSP algorithms, EW, anti-jam, and datalink vulnerability. Qualifications: Bachelor's degree, Secret Clearance, and proficiency in waveform modulation, LPD waveforms, signal detection, MATLAB, algorithm development, RF, data links, and EW systems. The position is on-site in Huntsville, AL and can support candidates at 3+ or 10+ years of experience.