Discussion:
serial help ?
(too old to reply)
Alfred Perlstein
2007-04-19 21:10:21 UTC
Permalink
I'm working on some custom hardware and I'm getting garbled console
output.

I noticed that siocntxwait looks like this:

static void
siocntxwait(iobase)
Port_t iobase;
{
int timo;

/*
* Wait for any pending transmission to finish. Required to avoid
* the UART lockup bug when the speed is changed, and for normal
* transmits.
*/
timo = 100000;
while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
!= (LSR_TSRE | LSR_TXRDY) && --timo != 0)
;
}

Shouldn't there be some sort of DELAY in there?

My platform has an emulated serial device in hardware, so it
may be that the loop could run a LOT faster than transmit can
happen...

any ideas of what the DELAY should be?
--
- Alfred Perlstein
Sergey Babkin
2007-04-19 22:14:06 UTC
Permalink
Post by Alfred Perlstein
I'm working on some custom hardware and I'm getting garbled console
output.
static void
siocntxwait(iobase)
Port_t iobase;
{
int timo;
/*
* Wait for any pending transmission to finish. Required to avoid
* the UART lockup bug when the speed is changed, and for normal
* transmits.
*/
timo = 100000;
while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
!= (LSR_TSRE | LSR_TXRDY) && --timo != 0)
;
}
Shouldn't there be some sort of DELAY in there?
My platform has an emulated serial device in hardware, so it
may be that the loop could run a LOT faster than transmit can
happen...
any ideas of what the DELAY should be?
I would do something like delay(1) in the loop after
this one. The idea being that if the output buffer
is empty os nearly empty, the first loop will exit
quickly and skip the second one. Otherwise it would
go into the slow loop with delay().

Then for the 2nd loop count limit I guess take the size of the
hardware buffer, multiply by 10 (8 data bits + 2
start/stop), add a little for safety and divide the bit rate
by that, and then divide the length of delay(1) by that. Or however
long it takes for your device to transmit. If the
actual transmission happens faster, it will set the
TXRDY bit and the loop will complete faster.

-SB
M. Warner Losh
2007-04-22 05:42:53 UTC
Permalink
In message: <***@elvis.mu.org>
Alfred Perlstein <***@freebsd.org> writes:
:
: I'm working on some custom hardware and I'm getting garbled console
: output.
:
: I noticed that siocntxwait looks like this:
:
: static void
: siocntxwait(iobase)
: Port_t iobase;
: {
: int timo;
:
: /*
: * Wait for any pending transmission to finish. Required to avoid
: * the UART lockup bug when the speed is changed, and for normal
: * transmits.
: */
: timo = 100000;
: while ((inb(iobase + com_lsr) & (LSR_TSRE | LSR_TXRDY))
: != (LSR_TSRE | LSR_TXRDY) && --timo != 0)
: ;
: }
:
: Shouldn't there be some sort of DELAY in there?
:
: My platform has an emulated serial device in hardware, so it
: may be that the loop could run a LOT faster than transmit can
: happen...
:
: any ideas of what the DELAY should be?

The inb() is assumed to provide a delay of 1us, so this has a timeout
of 100ms. Even with newer PCI devices that run about 4-5 times
faster, the timeout is still on the order of 20ms, which is adequate
for most modern baudrates (9600 baud takes 1ms, 115200 takes 10us).

Warner

Loading...