public inbox for ecos-discuss@sourceware.org
 help / color / mirror / Atom feed
* [ECOS] routing sockets / far end address resolution
@ 2008-01-21 22:04 Daniel Paape
  2008-01-22  9:19 ` [ECOS] Half Duplex RS485 Laurie Gellatly
  0 siblings, 1 reply; 14+ messages in thread
From: Daniel Paape @ 2008-01-21 22:04 UTC (permalink / raw)
  To: ecos-discuss

Hello,

Someone asked a question
(http://sourceware.org/ml/ecos-discuss/2006-12/msg00137.html) about a
year ago regarding routing sockets.  There was no response to the
question and I'm wondering whether someone might have a go at a
re-worded version.  Does eCos support routing sockets?  The individual
above was having difficulty with the fileio (read/write) calls
associated with a routing socket.  Could one use sendmsg/recvmsg instead
(if they are indeed supported)?  If so, how does one convey that the
second argument is a "rt_msghdr" rather than just a "msghdr" structure?

My ultimate goal is to resolve a far end IP address to its mac address
(it may be local or may be on the other side of the gateway).  The
address probably isn't resident in the ARP table, so what I am in
essence attempting to do is to get the stack to do a synchronized ARP
request for me.  A ping would (most likely) get the address into the ARP
table but I would really like to avoid an ICMP exchange.  I've cobbled a
proprietary IOCTL into the stack and can get it to do a lookup and if
necessary send out the ARP request... but implementing a wait for the
response is going to be difficult.

Is there a better way?

Thanks for any help.
Dan Paape

--
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [ECOS] Half Duplex RS485
  2008-01-21 22:04 [ECOS] routing sockets / far end address resolution Daniel Paape
@ 2008-01-22  9:19 ` Laurie Gellatly
       [not found]   ` <001001c85dd0$c8083160$6501a8c0@global.ds.honeywell.com>
  2008-01-23 16:34   ` [ECOS] " Grant Edwards
  0 siblings, 2 replies; 14+ messages in thread
From: Laurie Gellatly @ 2008-01-22  9:19 UTC (permalink / raw)
  To: ecos-discuss

Hi All,
My project has RS485 half duplex driven by UART0 of an LPC2112.
At present I've modified pc_serial_start_xmit and pc_serial_stop_xmit to
change a pin state so that the same wires can be used for transmit and
receive.

This does not see to work when the FIFO is enabled.
Has anyone else done RS485 half duplex?
Did you modify these routines or write your own?
Did you get the FIFO to work?

Thanks			...Laurie:{)

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* Re: [ECOS] Half Duplex RS485
       [not found]   ` <001001c85dd0$c8083160$6501a8c0@global.ds.honeywell.com>
@ 2008-01-23 15:01     ` Wang Cui
  0 siblings, 0 replies; 14+ messages in thread
From: Wang Cui @ 2008-01-23 15:01 UTC (permalink / raw)
  To: 'Laurie Gellatly', ecos-discuss

As I used RS-485, I designed the hardware to automatically control the Tx/Rx
of transceiver.
So nothing need to be modified on driver level. However, you must ensure no
more than 1 node on RS-485 bus Tx date at any moment, otherwise it will
cause collision.

---------------------------------------------------------------------------
Hi All,
My project has RS485 half duplex driven by UART0 of an LPC2112.
At present I've modified pc_serial_start_xmit and pc_serial_stop_xmit to
change a pin state so that the same wires can be used for transmit and
receive.

This does not see to work when the FIFO is enabled.
Has anyone else done RS485 half duplex?
Did you modify these routines or write your own?
Did you get the FIFO to work?

Thanks			...Laurie:{)

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss



-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [ECOS]  Re: Half Duplex RS485
  2008-01-22  9:19 ` [ECOS] Half Duplex RS485 Laurie Gellatly
       [not found]   ` <001001c85dd0$c8083160$6501a8c0@global.ds.honeywell.com>
@ 2008-01-23 16:34   ` Grant Edwards
  2008-01-23 21:12     ` Laurie Gellatly
  1 sibling, 1 reply; 14+ messages in thread
From: Grant Edwards @ 2008-01-23 16:34 UTC (permalink / raw)
  To: ecos-discuss

On 2008-01-22, Laurie Gellatly <laurie.gellatly@netic.com> wrote:

> My project has RS485 half duplex driven by UART0 of an
> LPC2112. At present I've modified pc_serial_start_xmit and
> pc_serial_stop_xmit to change a pin state so that the same
> wires can be used for transmit and receive.
>
> This does not see to work when the FIFO is enabled.

Then you probably did it wrong. :)

I imagine that RTS is shutting off too soon.  The problem is
that pc_serial_stop_xmit() is called when the driver has no
more data to send _to_ the UART.  That's not when you need to
shut off RTS.  You need to shut off RTS when the UART is done
sending data and both the FIFO and shift register are empty.

You're probably shutting off RTS while the UART still has data
in the tx FIFO and the tx shift register.

> Has anyone else done RS485 half duplex?

Many, many times.

> Did you modify these routines or write your own?

I usually pick a UART that supports half-duplex operation, and
then just enabled that feature in the UART.  [I use a custom
eCos serial driver that supports quite a few more advanced UART
features than the standard driver (e.g. flow control,
half-duplex, inter-byte timeouts, 9-bit modes, FIFO control,
etc.).

If you don't have a proper UART, you need to enable the tx
shift register empty interrupt and use that to trigger code
that de-asserts RTS.  If you're using a broken UART that
doesn't have a tx shift register empty interrupt, then you'll
have to poll for the tx shift register empty status.  If you're
using a really broken UART that doesn't have a _working_
shift-register empty status[1], then you may have to start a
timer that will wake you up at the point in time where RTS
needs to be changed.

> Did you get the FIFO to work?

When there was one, yes.


[1] There are broken UARTs (including a few PC chipsets) whose
    shift-register empty bit gets set _before_ the stop bit has
    been sent.  In that case, you may need to use some sort of
    time-delay to wait until after the stop bit has been sent
    to toggle RTS.  On a properly implimented RS-485 bus, there
    should be pull-up and pull-down resisters so that the bus
    idles in the mark state (same value as a stop bit), but to
    be on the safe side you should leave the bus driver on
    until after the stop bit has been sent.

-- 
Grant Edwards                   grante             Yow! I'm also against
                                  at               BODY-SURFING!!
                               visi.com            


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [ECOS]  Re: Half Duplex RS485
  2008-01-23 16:34   ` [ECOS] " Grant Edwards
@ 2008-01-23 21:12     ` Laurie Gellatly
  2008-01-23 22:03       ` Grant Edwards
  2008-01-25  1:33       ` wangcui
  0 siblings, 2 replies; 14+ messages in thread
From: Laurie Gellatly @ 2008-01-23 21:12 UTC (permalink / raw)
  To: Grant Edwards, ecos-discuss

Wang/Grant, thanks for the replies.

>> My project has RS485 half duplex driven by UART0 of an
>> LPC2112. At present I've modified pc_serial_start_xmit and
>> pc_serial_stop_xmit to change a pin state so that the same
>> wires can be used for transmit and receive.
>>
>> This does not see to work when the FIFO is enabled.
>
>Then you probably did it wrong. :)
>
>I imagine that RTS is shutting off too soon.  The problem is
>that pc_serial_stop_xmit() is called when the driver has no
>more data to send _to_ the UART.  That's not when you need to
>shut off RTS.  You need to shut off RTS when the UART is done
>sending data and both the FIFO and shift register are empty.
>
>You're probably shutting off RTS while the UART still has data
>in the tx FIFO and the tx shift register.
Funny thing is that it appears that the first part of the 
transmission is lost.

>> Has anyone else done RS485 half duplex?
>
>Many, many times.
>
>> Did you modify these routines or write your own?
>
>I usually pick a UART that supports half-duplex operation, and
>then just enabled that feature in the UART.  [I use a custom
>eCos serial driver that supports quite a few more advanced UART
>features than the standard driver (e.g. flow control,
>half-duplex, inter-byte timeouts, 9-bit modes, FIFO control,
>etc.).
>
>If you don't have a proper UART, you need to enable the tx
>shift register empty interrupt and use that to trigger code
>that de-asserts RTS.  If you're using a broken UART that
>doesn't have a tx shift register empty interrupt, then you'll
>have to poll for the tx shift register empty status.  If you're
>using a really broken UART that doesn't have a _working_
>shift-register empty status[1], then you may have to start a
>timer that will wake you up at the point in time where RTS
>needs to be changed.
>
>> Did you get the FIFO to work?
>
>When there was one, yes.
>
>
>[1] There are broken UARTs (including a few PC chipsets) whose
>    shift-register empty bit gets set _before_ the stop bit has
>    been sent.  In that case, you may need to use some sort of
>    time-delay to wait until after the stop bit has been sent
>    to toggle RTS.  On a properly implimented RS-485 bus, there
>    should be pull-up and pull-down resisters so that the bus
>    idles in the mark state (same value as a stop bit), but to
>    be on the safe side you should leave the bus driver on
>    until after the stop bit has been sent.

Grant, do you know if the LPC series have 'broken' UARTS?
Specifically LPC2212 and LPC2103?
U0TSR looks promising as an indication of when the bits
'have left the building' - is it accurate or do I
need to add a time delay?

Really appreciate the help.			...Laurie:{)

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [ECOS]  Re: Half Duplex RS485
  2008-01-23 21:12     ` Laurie Gellatly
@ 2008-01-23 22:03       ` Grant Edwards
  2008-01-23 23:06         ` Laurie Gellatly
  2008-01-25  1:33       ` wangcui
  1 sibling, 1 reply; 14+ messages in thread
From: Grant Edwards @ 2008-01-23 22:03 UTC (permalink / raw)
  To: ecos-discuss

On 2008-01-23, Laurie Gellatly <laurie.gellatly@netic.com> wrote:

>>I imagine that RTS is shutting off too soon.  The problem is
>>that pc_serial_stop_xmit() is called when the driver has no
>>more data to send _to_ the UART.  That's not when you need to
>>shut off RTS.  You need to shut off RTS when the UART is done
>>sending data and both the FIFO and shift register are empty.
>>
>>You're probably shutting off RTS while the UART still has data
>>in the tx FIFO and the tx shift register.
> 
> Funny thing is that it appears that the first part of the 
> transmission is lost.

Ah. 

If you look at io/serial.c, you can see that the serial_write()
function calls start_xmit() _after_ it's done filling up the
UART's tx fifo (the UART will start sending when the first byte
is written to the tx fifo).  RTS needs to be asserted before
any data is written to the tx fifo.  That means that
start_xmit() is being called too late: the first byte is
already on it's way out of the UART before start_xmit() is
called.  If your protocol allows it, adding an extra "idle"
byte to the beginning of the message will probably fix that.

Off the top of my head, here are a couple other options:

 1) Add code to the low-level driver's putc() method that
    asserts RTS _before_ it transfers the byte to the UART tx
    fifo.

 2) Add another driver hook that is called by serial_write()
    before it fills the tx fifo.

 3) Always leave the UART in a mode where the transmit logic is
    disabled until it's enabled by a call to start_xmit(). IOW,
    when the last bit it in a transmission has been sent not
    only do you de-assert RTS, you also shut off the UART's
    transmit hw so that the next time somebody fills up the tx
    fifo nothing goes out until start_xmit() is called.

Number 1) is probably the simplest.
    
> Grant, do you know if the LPC series have 'broken' UARTS?
> Specifically LPC2212 and LPC2103? U0TSR looks promising as an
> indication of when the bits 'have left the building' - is it
> accurate or do I need to add a time delay?

I don't know -- I've never worked with the LPC parts.  The vast
majority of the the parts I've used have been OK (many don't
provide an interrupt, but at least the status bit worked
correctly when polled).  IIRC, the ones that I had problems
with were a UART in one of Motorola's old uControllers (don't
remember which one, but it was from about 10-15 years ago) and
a couple different PC motherboard chipsets.

At one point I modified the Linux PC UART driver to support
half-duplex operation, but it never worked reliably, so I just
gave up and bought serial cards that had UARTs which supported
half-duplex mode.  Now that I think about it, I also built a
little 9-pin pass-through dongle with a one-shot in it that
controlled RTS.  It worked pretty well also (for the one baud
rate it was designed for), but since the first bit was usually
mangled, it only worked on protocols where the messages had
training preambles.

-- 
Grant Edwards                   grante             Yow! We are now enjoying
                                  at               total mutual interaction in
                               visi.com            an imaginary hot tub ...


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [ECOS]  Re: Half Duplex RS485
  2008-01-23 22:03       ` Grant Edwards
@ 2008-01-23 23:06         ` Laurie Gellatly
  2008-01-23 23:44           ` Grant Edwards
  2008-01-24  9:02           ` Daniel Néri
  0 siblings, 2 replies; 14+ messages in thread
From: Laurie Gellatly @ 2008-01-23 23:06 UTC (permalink / raw)
  To: Grant Edwards, ecos-discuss


Grant,

>>>I imagine that RTS is shutting off too soon.  The problem is
>>>that pc_serial_stop_xmit() is called when the driver has no
>>>more data to send _to_ the UART.  That's not when you need to
>>>shut off RTS.  You need to shut off RTS when the UART is done
>>>sending data and both the FIFO and shift register are empty.
>>>
>>>You're probably shutting off RTS while the UART still has data
>>>in the tx FIFO and the tx shift register.
>> 
>> Funny thing is that it appears that the first part of the 
>> transmission is lost.

>Ah. 

>If you look at io/serial.c, you can see that the serial_write()
>function calls start_xmit() _after_ it's done filling up the
>UART's tx fifo (the UART will start sending when the first byte
>is written to the tx fifo).  RTS needs to be asserted before
>any data is written to the tx fifo.  That means that
>start_xmit() is being called too late: the first byte is
>already on it's way out of the UART before start_xmit() is
>called.  If your protocol allows it, adding an extra "idle"
>byte to the beginning of the message will probably fix that.

>Off the top of my head, here are a couple other options:

> 1) Add code to the low-level driver's putc() method that
>    asserts RTS _before_ it transfers the byte to the UART tx
>    fifo.

> 2) Add another driver hook that is called by serial_write()
>    before it fills the tx fifo.

> 3) Always leave the UART in a mode where the transmit logic is
>    disabled until it's enabled by a call to start_xmit(). IOW,
>    when the last bit it in a transmission has been sent not
>    only do you de-assert RTS, you also shut off the UART's
>    transmit hw so that the next time somebody fills up the tx
>    fifo nothing goes out until start_xmit() is called.

>Number 1) is probably the simplest.
    
Did not see that xmit happened after the FIFO was filled.
I have to flip a bit before the transmit and clear it when done.
So I'm thinking that setting the bit before the cyg_io_write in
application code would be OK and clear it (after waiting for TEMT
plus maybe a small delay) in xmit_stop might work for me.
I always write a complete message so as long as stop_xmit happens
fairly soon after the last bit has gone then I'll be ready to receive 
the response.

Possibly part of my problem stems from having two serial lines.
One for 485 and the other for 232.
The 232 serial line uses ppp_chat to conduct a simple exchange.
When you include the ppp package it forces you to have flow control
on ALL serial lines and I don't want that on the 485 line.

Looks like I'll have to try to carve out ppp_chat and make it 
into its own package without the flow control requirement 
unless you have a better alternative?

Thanks again. 			...Laurie:{)

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [ECOS]  Re: Half Duplex RS485
  2008-01-23 23:06         ` Laurie Gellatly
@ 2008-01-23 23:44           ` Grant Edwards
  2008-01-24  9:02           ` Daniel Néri
  1 sibling, 0 replies; 14+ messages in thread
From: Grant Edwards @ 2008-01-23 23:44 UTC (permalink / raw)
  To: ecos-discuss

On 2008-01-23, Laurie Gellatly <laurie.gellatly@netic.com> wrote:

>>> Funny thing is that it appears that the first part of the 
>>> transmission is lost.
>
>>Ah. 
>
>>If you look at io/serial.c, you can see that the serial_write()
>>function calls start_xmit() _after_ it's done filling up the
>>UART's tx fifo (the UART will start sending when the first byte
>>is written to the tx fifo).  RTS needs to be asserted before
>>any data is written to the tx fifo.  That means that
>>start_xmit() is being called too late: the first byte is
>>already on it's way out of the UART before start_xmit() is
>>called.


> Did not see that xmit happened after the FIFO was filled. I
> have to flip a bit before the transmit and clear it when done.
> So I'm thinking that setting the bit before the cyg_io_write
> in application code would be OK and clear it (after waiting
> for TEMT plus maybe a small delay) in xmit_stop might work for
> me. I always write a complete message so as long as stop_xmit
> happens fairly soon after the last bit has gone then I'll be
> ready to receive the response.

stop_xmit doesn't happen after the last bit is gone.  It
happens a long, long time before that.

stop_xmit() is called when the last byte has been transferred
from the serial driver's buffer into the UART's tx fifo.  At
the point in time when stop_xmit() is called, there's still up
to an entire fifo's worth (somewhere from 8 to 4K bytes
depending on the UART) of transmit data still waiting to be
sent.  It could happen many seconds before the last bit has
gone.  At 9600 baud with a 1K tx fifo, it would get called
about one second before the last bit is gone (assuming the tx
message didn't fit entirely within the tx fifo).

Despite it's name, stop_xmit() has nothing to do with the UART
stopping transmission.  It is called to shut off the tx
interrupt that requests additional tx data from the serial
driver's transmit buffer.  It is called when the upper level
serial driver has no more bytes to send.  The UART might still
have plenty of bytes waiting to be sent.  stop_xmit() is not
all that useful in determining when the UART has finished
sending bits down the wire.  There's no point in polling for tx
empty until stop_xmit() has been called, but there can be a
very long time between stop_xmit() and the transmission being
completed.  You need to be prepared to poll for an entire tx
fifo's worth of time.

> Possibly part of my problem stems from having two serial
> lines.

I wouldn't think so.  The ports should operate independently.
If they don't, then I'd say the low-level driver is broken.

> One for 485 and the other for 232. The 232 serial line uses
> ppp_chat to conduct a simple exchange. When you include the
> ppp package it forces you to have flow control on ALL serial
> lines and I don't want that on the 485 line.

It sounds to me like the PPP package is broken if it's mucking
about with serial ports on which you're not using PPP.

> Looks like I'll have to try to carve out ppp_chat and make it 
> into its own package without the flow control requirement 
> unless you have a better alternative?

I've never looked at the PPP stuff, and I don't know how flow
control works in the standard serial driver.  In my serial
driver, flow control is configurable on a per-port basis at run
time by the application and is implemented by either the UART
itself or by the low-level driver in the case of UARTs that
don't do flow control in hardware.

-- 
Grant Edwards                   grante             Yow! PEGGY FLEMMING is
                                  at               stealing BASKET BALLS to
                               visi.com            feed the babies in VERMONT.


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* [ECOS]  Re: Half Duplex RS485
  2008-01-23 23:06         ` Laurie Gellatly
  2008-01-23 23:44           ` Grant Edwards
@ 2008-01-24  9:02           ` Daniel Néri
  1 sibling, 0 replies; 14+ messages in thread
From: Daniel Néri @ 2008-01-24  9:02 UTC (permalink / raw)
  To: ecos-discuss

"Laurie Gellatly" <laurie.gellatly@netic.com> writes:

> When you include the ppp package it forces you to have flow control
> on ALL serial lines and I don't want that on the 485 line.

No, it just enables flow control by default on all serial ports. You can
change it for individual ports in your application, using
cyg_io_set_config.

Or change the default to "NONE" for all ports via
CYGDAT_IO_SERIAL_FLOW_CONTROL_DEFAULT (pppd will enable it on its own
serial device, unless you tell it not to)

> Looks like I'll have to try to carve out ppp_chat and make it into its
> own package without the flow control requirement unless you have a
> better alternative?

Actually the requirement is on the flow control support code. There is
no requirement on flow control being enabled for the serial device used
by pppd (and it works pretty well when disabled too).


Regards,
-- 
Daniel Néri <daniel.neri@sigicom.se>
Sigicom AB, Stockholm, Sweden


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [ECOS]  Re: Half Duplex RS485
  2008-01-23 21:12     ` Laurie Gellatly
  2008-01-23 22:03       ` Grant Edwards
@ 2008-01-25  1:33       ` wangcui
  2008-01-25  2:00         ` Laurie Gellatly
  1 sibling, 1 reply; 14+ messages in thread
From: wangcui @ 2008-01-25  1:33 UTC (permalink / raw)
  To: Laurie Gellatly, Grant Edwards, ecos-discuss

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 3670 bytes --]


Just FYI, the LPC2XXX's UART0 is not fully functional. So when the 16x5x serial driver check FIFO(in serial_config_port()), it will fail, thus FIFO is disabled for UART0. But UART1 works fine.

To resolve it, I have to modified 16x5x driver code, force enable FIFO for UART0 and UART1.

> From: laurie.gellatly@netic.com
> To: grante@visi.com; ecos-discuss@sources.redhat.com
> Date: Thu, 24 Jan 2008 08:12:17 +1100
> Subject: RE: [ECOS] Re: Half Duplex RS485
>
> Wang/Grant, thanks for the replies.
>
>>> My project has RS485 half duplex driven by UART0 of an
>>> LPC2112. At present I've modified pc_serial_start_xmit and
>>> pc_serial_stop_xmit to change a pin state so that the same
>>> wires can be used for transmit and receive.
>>>
>>> This does not see to work when the FIFO is enabled.
>>
>>Then you probably did it wrong. :)
>>
>>I imagine that RTS is shutting off too soon. The problem is
>>that pc_serial_stop_xmit() is called when the driver has no
>>more data to send _to_ the UART. That's not when you need to
>>shut off RTS. You need to shut off RTS when the UART is done
>>sending data and both the FIFO and shift register are empty.
>>
>>You're probably shutting off RTS while the UART still has data
>>in the tx FIFO and the tx shift register.
> Funny thing is that it appears that the first part of the
> transmission is lost.
>
>>> Has anyone else done RS485 half duplex?
>>
>>Many, many times.
>>
>>> Did you modify these routines or write your own?
>>
>>I usually pick a UART that supports half-duplex operation, and
>>then just enabled that feature in the UART. [I use a custom
>>eCos serial driver that supports quite a few more advanced UART
>>features than the standard driver (e.g. flow control,
>>half-duplex, inter-byte timeouts, 9-bit modes, FIFO control,
>>etc.).
>>
>>If you don't have a proper UART, you need to enable the tx
>>shift register empty interrupt and use that to trigger code
>>that de-asserts RTS. If you're using a broken UART that
>>doesn't have a tx shift register empty interrupt, then you'll
>>have to poll for the tx shift register empty status. If you're
>>using a really broken UART that doesn't have a _working_
>>shift-register empty status[1], then you may have to start a
>>timer that will wake you up at the point in time where RTS
>>needs to be changed.
>>
>>> Did you get the FIFO to work?
>>
>>When there was one, yes.
>>
>>
>>[1] There are broken UARTs (including a few PC chipsets) whose
>> shift-register empty bit gets set _before_ the stop bit has
>> been sent. In that case, you may need to use some sort of
>> time-delay to wait until after the stop bit has been sent
>> to toggle RTS. On a properly implimented RS-485 bus, there
>> should be pull-up and pull-down resisters so that the bus
>> idles in the mark state (same value as a stop bit), but to
>> be on the safe side you should leave the bus driver on
>> until after the stop bit has been sent.
>
> Grant, do you know if the LPC series have 'broken' UARTS?
> Specifically LPC2212 and LPC2103?
> U0TSR looks promising as an indication of when the bits
> 'have left the building' - is it accurate or do I
> need to add a time delay?
>
> Really appreciate the help. ...Laurie:{)
>
> --
> Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
> and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
>

_________________________________________________________________
ÌìÁ¹ÁË£¬ÌíÒÂÁË£¬ÐĶ¯ÁË£¬¡°Æß¼þ¡±ÁË 
http://get.live.cn

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [ECOS]  Re: Half Duplex RS485
  2008-01-25  1:33       ` wangcui
@ 2008-01-25  2:00         ` Laurie Gellatly
  0 siblings, 0 replies; 14+ messages in thread
From: Laurie Gellatly @ 2008-01-25  2:00 UTC (permalink / raw)
  To: wangcui, Grant Edwards, ecos-discuss

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; 	charset="gb2312", Size: 4079 bytes --]

Hi Wang,
I'd be interested to see what you had to modify to make the FIFO work.

The eCos source does not know about the fractional divider.
Did you enable fix that as well?

			...Laurie:{)

-----Original Message-----
From: wangcui [mailto:iucgnaw@msn.com]
Sent: Friday, 25 January 2008 12:33 PM
To: Laurie Gellatly; Grant Edwards; ecos-discuss@sources.redhat.com
Subject: RE: [ECOS] Re: Half Duplex RS485



Just FYI, the LPC2XXX's UART0 is not fully functional. So when the 16x5x
serial driver check FIFO(in serial_config_port()), it will fail, thus FIFO
is disabled for UART0. But UART1 works fine.

To resolve it, I have to modified 16x5x driver code, force enable FIFO for
UART0 and UART1.

> From: laurie.gellatly@netic.com
> To: grante@visi.com; ecos-discuss@sources.redhat.com
> Date: Thu, 24 Jan 2008 08:12:17 +1100
> Subject: RE: [ECOS] Re: Half Duplex RS485
>
> Wang/Grant, thanks for the replies.
>
>>> My project has RS485 half duplex driven by UART0 of an
>>> LPC2112. At present I've modified pc_serial_start_xmit and
>>> pc_serial_stop_xmit to change a pin state so that the same
>>> wires can be used for transmit and receive.
>>>
>>> This does not see to work when the FIFO is enabled.
>>
>>Then you probably did it wrong. :)
>>
>>I imagine that RTS is shutting off too soon. The problem is
>>that pc_serial_stop_xmit() is called when the driver has no
>>more data to send _to_ the UART. That's not when you need to
>>shut off RTS. You need to shut off RTS when the UART is done
>>sending data and both the FIFO and shift register are empty.
>>
>>You're probably shutting off RTS while the UART still has data
>>in the tx FIFO and the tx shift register.
> Funny thing is that it appears that the first part of the
> transmission is lost.
>
>>> Has anyone else done RS485 half duplex?
>>
>>Many, many times.
>>
>>> Did you modify these routines or write your own?
>>
>>I usually pick a UART that supports half-duplex operation, and
>>then just enabled that feature in the UART. [I use a custom
>>eCos serial driver that supports quite a few more advanced UART
>>features than the standard driver (e.g. flow control,
>>half-duplex, inter-byte timeouts, 9-bit modes, FIFO control,
>>etc.).
>>
>>If you don't have a proper UART, you need to enable the tx
>>shift register empty interrupt and use that to trigger code
>>that de-asserts RTS. If you're using a broken UART that
>>doesn't have a tx shift register empty interrupt, then you'll
>>have to poll for the tx shift register empty status. If you're
>>using a really broken UART that doesn't have a _working_
>>shift-register empty status[1], then you may have to start a
>>timer that will wake you up at the point in time where RTS
>>needs to be changed.
>>
>>> Did you get the FIFO to work?
>>
>>When there was one, yes.
>>
>>
>>[1] There are broken UARTs (including a few PC chipsets) whose
>> shift-register empty bit gets set _before_ the stop bit has
>> been sent. In that case, you may need to use some sort of
>> time-delay to wait until after the stop bit has been sent
>> to toggle RTS. On a properly implimented RS-485 bus, there
>> should be pull-up and pull-down resisters so that the bus
>> idles in the mark state (same value as a stop bit), but to
>> be on the safe side you should leave the bus driver on
>> until after the stop bit has been sent.
>
> Grant, do you know if the LPC series have 'broken' UARTS?
> Specifically LPC2212 and LPC2103?
> U0TSR looks promising as an indication of when the bits
> 'have left the building' - is it accurate or do I
> need to add a time delay?
>
> Really appreciate the help. ...Laurie:{)
>
> --
> Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
> and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
>

_________________________________________________________________
ÌìÁ¹ÁË£¬ÌíÒÂÁË£¬ÐĶ¯ÁË£¬¡°Æß¼þ¡±ÁË
http://get.live.cn


-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [ECOS]  Re: Half Duplex RS485
  2008-01-26 20:41 ` Laurie Gellatly
@ 2008-01-28 10:34   ` wangcui
  0 siblings, 0 replies; 14+ messages in thread
From: wangcui @ 2008-01-28 10:34 UTC (permalink / raw)
  To: Laurie Gellatly, ecos-discuss

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 1116 bytes --]


Sorry for late reply.
Yes, when I specify appropriate deviceType in serial-channel-instance, the driver code will not check chip and just enable it.
So I explictly set deviceType for LPC2XXX's UART0, and intialize UART1 and other channels(of SC16C550) as before, then all channels works well with FIFO enabled.


> From: laurie.gellatly@netic.com
> To: ecos-discuss@sources.redhat.com
> Date: Sun, 27 Jan 2008 07:40:53 +1100
> Subject: RE: [ECOS] Re: Half Duplex RS485
>
> Hi Wang,
> I've been looking through the patch you sent.
> I don't see any change to the FIFO handling unless you mean where
> it figures out the deviceType?
>
> ...Laurie:{)
>
> --
> Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
> and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
>

_________________________________________________________________
ÊÖ»úÒ²ÄÜÉÏ MSN ÁÄÌìÁË£¬¿ìÀ´ÊÔÊÔ°É£¡
http://mobile.msn.com.cn/

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [ECOS]  Re: Half Duplex RS485
  2008-01-25  4:16 wangcui
@ 2008-01-26 20:41 ` Laurie Gellatly
  2008-01-28 10:34   ` wangcui
  0 siblings, 1 reply; 14+ messages in thread
From: Laurie Gellatly @ 2008-01-26 20:41 UTC (permalink / raw)
  To: ecos-discuss

Hi Wang,
I've been looking through the patch you sent.
I don't see any change to the FIFO handling unless you mean where
it figures out the deviceType?

			...Laurie:{)

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

* RE: [ECOS]  Re: Half Duplex RS485
@ 2008-01-25  4:16 wangcui
  2008-01-26 20:41 ` Laurie Gellatly
  0 siblings, 1 reply; 14+ messages in thread
From: wangcui @ 2008-01-25  4:16 UTC (permalink / raw)
  To: Laurie Gellatly, Grant Edwards, ecos-discuss

[-- Warning: decoded text below may be mangled, UTF-8 assumed --]
[-- Attachment #1: Type: text/plain; charset="gb2312", Size: 4736 bytes --]



Here is the patch, shows all modifications in my working folder.
Acutally, I did more than FIFO stuff, I also made it support 2 diffent 16x5x chips on my target(different register-offset-step), and something else.

BTW, I prefer to solve half-duplex problem on hardware level, which avoid lots of effort on software level.

> From: laurie.gellatly@netic.com
> To: iucgnaw@msn.com; grante@visi.com; ecos-discuss@sources.redhat.com
> Subject: RE: [ECOS] Re: Half Duplex RS485
> Date: Fri, 25 Jan 2008 12:59:54 +1100
>
> Hi Wang,
> I'd be interested to see what you had to modify to make the FIFO work.
>
> The eCos source does not know about the fractional divider.
> Did you enable fix that as well?
>
> ...Laurie:{)
>
> -----Original Message-----
> From: wangcui [mailto:iucgnaw@msn.com]
> Sent: Friday, 25 January 2008 12:33 PM
> To: Laurie Gellatly; Grant Edwards; ecos-discuss@sources.redhat.com
> Subject: RE: [ECOS] Re: Half Duplex RS485
>
>
>
> Just FYI, the LPC2XXX's UART0 is not fully functional. So when the 16x5x
> serial driver check FIFO(in serial_config_port()), it will fail, thus FIFO
> is disabled for UART0. But UART1 works fine.
>
> To resolve it, I have to modified 16x5x driver code, force enable FIFO for
> UART0 and UART1.
>
>> From: laurie.gellatly@netic.com
>> To: grante@visi.com; ecos-discuss@sources.redhat.com
>> Date: Thu, 24 Jan 2008 08:12:17 +1100
>> Subject: RE: [ECOS] Re: Half Duplex RS485
>>
>> Wang/Grant, thanks for the replies.
>>
>>>> My project has RS485 half duplex driven by UART0 of an
>>>> LPC2112. At present I've modified pc_serial_start_xmit and
>>>> pc_serial_stop_xmit to change a pin state so that the same
>>>> wires can be used for transmit and receive.
>>>>
>>>> This does not see to work when the FIFO is enabled.
>>>
>>>Then you probably did it wrong. :)
>>>
>>>I imagine that RTS is shutting off too soon. The problem is
>>>that pc_serial_stop_xmit() is called when the driver has no
>>>more data to send _to_ the UART. That's not when you need to
>>>shut off RTS. You need to shut off RTS when the UART is done
>>>sending data and both the FIFO and shift register are empty.
>>>
>>>You're probably shutting off RTS while the UART still has data
>>>in the tx FIFO and the tx shift register.
>> Funny thing is that it appears that the first part of the
>> transmission is lost.
>>
>>>> Has anyone else done RS485 half duplex?
>>>
>>>Many, many times.
>>>
>>>> Did you modify these routines or write your own?
>>>
>>>I usually pick a UART that supports half-duplex operation, and
>>>then just enabled that feature in the UART. [I use a custom
>>>eCos serial driver that supports quite a few more advanced UART
>>>features than the standard driver (e.g. flow control,
>>>half-duplex, inter-byte timeouts, 9-bit modes, FIFO control,
>>>etc.).
>>>
>>>If you don't have a proper UART, you need to enable the tx
>>>shift register empty interrupt and use that to trigger code
>>>that de-asserts RTS. If you're using a broken UART that
>>>doesn't have a tx shift register empty interrupt, then you'll
>>>have to poll for the tx shift register empty status. If you're
>>>using a really broken UART that doesn't have a _working_
>>>shift-register empty status[1], then you may have to start a
>>>timer that will wake you up at the point in time where RTS
>>>needs to be changed.
>>>
>>>> Did you get the FIFO to work?
>>>
>>>When there was one, yes.
>>>
>>>
>>>[1] There are broken UARTs (including a few PC chipsets) whose
>>> shift-register empty bit gets set _before_ the stop bit has
>>> been sent. In that case, you may need to use some sort of
>>> time-delay to wait until after the stop bit has been sent
>>> to toggle RTS. On a properly implimented RS-485 bus, there
>>> should be pull-up and pull-down resisters so that the bus
>>> idles in the mark state (same value as a stop bit), but to
>>> be on the safe side you should leave the bus driver on
>>> until after the stop bit has been sent.
>>
>> Grant, do you know if the LPC series have 'broken' UARTS?
>> Specifically LPC2212 and LPC2103?
>> U0TSR looks promising as an indication of when the bits
>> 'have left the building' - is it accurate or do I
>> need to add a time delay?
>>
>> Really appreciate the help. ...Laurie:{)
>>
>> --
>> Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
>> and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss
>>
>
> _________________________________________________________________
> ÌìÁ¹ÁË£¬ÌíÒÂÁË£¬ÐĶ¯ÁË£¬¡°Æß¼þ¡±ÁË
> http://get.live.cn
>

_________________________________________________________________
MSN ÖÐÎÄÍø£¬×îÐÂʱÉÐÉú»î×ÊѶ£¬°×Áì¾Û¼¯ÃÅ»§¡£
http://cn.msn.com

[-- Attachment #2: 16x5x.patch --]
[-- Type: text/plain, Size: 10771 bytes --]

diff -r -u5 -N -x CVS /cygdrive/z/Share/Resource/eCos/anoncvs/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c /cygdrive/d/work/dev/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c
--- /cygdrive/z/Share/Resource/eCos/anoncvs/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c	2007-06-22 19:41:49.000000000 +0800
+++ /cygdrive/d/work/dev/ecos/packages/devs/serial/generic/16x5x/current/src/ser_16x5x.c	2008-01-25 11:47:46.232562700 +0800
@@ -62,15 +62,18 @@
 #include <cyg/hal/hal_io.h>
 
 // Only compile driver if an inline file with driver details was selected.
 #ifdef CYGDAT_IO_SERIAL_GENERIC_16X5X_INL
 
-#ifndef CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP
-#define CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP 1
-#endif
-
-#define SER_REG(_x_) ((_x_)*CYGPRI_IO_SERIAL_GENERIC_16X5X_STEP)
+//here we use a 'step' variable to indicate the address delta between a 16X5X channel's registers
+//user should new a variable named 'step' and set appropriate value before access 16X5X's register.
+//For example:
+//{
+//  int step = ser_chan->step;
+//  HAL_WRITE_UINT8(base+REG_thr, c);
+//}
+#define SER_REG(_x_) ((_x_)*step)
 
 // Receive control Registers
 #define REG_rhr SER_REG(0)    // Receive holding register
 #define REG_isr SER_REG(2)    // Interrupt status register
 #define REG_lsr SER_REG(5)    // Line status register
@@ -180,10 +183,15 @@
 // selec_baud[] must be define by the client
 
 typedef struct pc_serial_info {
     cyg_addrword_t base;
     int            int_num;
+    int            int_prio;
+    int            step;
+    int            baud_num;
+    int           *select_baud;
+    int          (*baud_generator)(unsigned int baud);
     cyg_interrupt  serial_interrupt;
     cyg_handle_t   serial_interrupt_handle;
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
     enum {
         sNone = 0,
@@ -233,12 +241,17 @@
 serial_config_port(serial_channel *chan, 
                    cyg_serial_info_t *new_config, bool init)
 {
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
-    unsigned short baud_divisor = select_baud[new_config->baud];
+    int step = ser_chan->step;
+    unsigned short baud_divisor;
     unsigned char _lcr, _ier;
+    
+    if (new_config->baud >= ser_chan->baud_num) return false;  // Invalid configuration
+
+    baud_divisor = ser_chan->select_baud[new_config->baud];
     if (baud_divisor == 0) return false;  // Invalid configuration
 
     // Disable port interrupts while changing hardware
     HAL_READ_UINT8(base+REG_ier, _ier);
     HAL_WRITE_UINT8(base+REG_ier, 0);
@@ -253,21 +266,22 @@
     if (init) {
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
         unsigned char _fcr_thresh;
         cyg_uint8 b;
 
-        /* First, find out what kind of device it is. */
-        ser_chan->deviceType = sNone;
-        HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP); // enable loopback mode
-        HAL_READ_UINT8(base+REG_msr, b);         
-        if (0 == (b & 0xF0)) {   // see if MSR had CD, RI, DSR or CTS set
-            HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP|MCR_DTR|MCR_RTS);
-            HAL_READ_UINT8(base+REG_msr, b);
-            if (0xF0 != (b & 0xF0))  // check that all of CD,RI,DSR and CTS set
-                ser_chan->deviceType = s8250;
+        if (ser_chan->deviceType == sNone) {
+            /* First, find out what kind of device it is. */
+            HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP); // enable loopback mode
+            HAL_READ_UINT8(base+REG_msr, b);         
+            if (0 == (b & 0xF0)) {   // see if MSR had CD, RI, DSR or CTS set
+                HAL_WRITE_UINT8(base+REG_mcr, MCR_LOOP|MCR_DTR|MCR_RTS);
+                HAL_READ_UINT8(base+REG_msr, b);
+                if (0xF0 != (b & 0xF0))  // check that all of CD,RI,DSR and CTS set
+                    ser_chan->deviceType = s8250;
+            }
+            HAL_WRITE_UINT8(base+REG_mcr, 0); // disable loopback mode
         }
-        HAL_WRITE_UINT8(base+REG_mcr, 0); // disable loopback mode
 
         if (ser_chan->deviceType == s8250) {
             // Check for a scratch register; scratch register 
             // indicates 16450 or above.
             HAL_WRITE_UINT8(base+REG_scr, 0x55);
@@ -308,10 +322,11 @@
               CYGNUM_IO_SERIAL_GENERIC_16X5X_FIFO_TX_SIZE;
             // Enable and clear FIFO
             HAL_WRITE_UINT8(base+REG_fcr, _fcr_thresh); 
         }
         else {
+            CYG_FAIL("Can't enable FIFO on this device.");
             ser_chan->tx_fifo_size = 1;
             HAL_WRITE_UINT8(base+REG_fcr, 0); // make sure it's disabled
         }
 
         ser_chan->tx_fifo_avail = ser_chan->tx_fifo_size;
@@ -348,36 +363,39 @@
 
 #ifdef CYG_IO_SERIAL_GENERIC_16X5X_BAUD_GENERATOR
     // Fill in baud rate table - used for platforms where this cannot
     // be determined statically
     int baud_idx, baud_val;
-    if (select_baud[0] == 9999) {
+
+    if (ser_chan->select_baud[0] == 9999) {
+        CYG_ASSERTC(ser_chan->baud_generator != NULL);
+
         // Table not yet initialized
         // Assumes that 'select_baud' looks like this:
         //   static int select_baud[] = {
         //       9999,  -- marker
         //       50,    -- first baud rate
         //       110,   -- second baud rate
         // etc.
-        for (baud_idx = 1;  baud_idx < sizeof(select_baud)/sizeof(select_baud[0]);  baud_idx++) {
-            baud_val = CYG_IO_SERIAL_GENERIC_16X5X_BAUD_GENERATOR(select_baud[baud_idx]);
-            select_baud[baud_idx] = baud_val;
+        for (baud_idx = 1;  baud_idx < ser_chan->baud_num;  baud_idx++) {
+            baud_val = ser_chan->baud_generator(ser_chan->select_baud[baud_idx]);
+            ser_chan->select_baud[baud_idx] = baud_val;
         }
-        select_baud[0] = 0;
+        ser_chan->select_baud[0] = 0;
     }
 #endif
 
 #ifdef CYGDBG_IO_INIT
-    diag_printf("16x5x SERIAL init - dev: %x.%d\n", 
-                ser_chan->base, ser_chan->int_num);
+    diag_printf("16x5x SERIAL init - dev: base=%x.step=%d.int_num=%d\n", 
+                ser_chan->base, ser_chan->step, ser_chan->int_num);
 #endif
     // Really only required for interrupt driven devices
     (chan->callbacks->serial_init)(chan);
 
     if (chan->out_cbuf.len != 0) {
         cyg_drv_interrupt_create(ser_chan->int_num,
-                                 CYG_IO_SERIAL_GENERIC_16X5X_INT_PRIORITY,
+                                 ser_chan->int_prio == -1 ? CYG_IO_SERIAL_GENERIC_16X5X_INT_PRIORITY : ser_chan->int_prio,
                                  (cyg_addrword_t)chan,
                                  pc_serial_ISR,
                                  pc_serial_DSR,
                                  &ser_chan->serial_interrupt_handle,
                                  &ser_chan->serial_interrupt);
@@ -409,10 +427,11 @@
 #ifndef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
     cyg_uint8 _lsr;
 #endif
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
 
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_FIFO
     if (ser_chan->tx_fifo_avail > 0) {
         HAL_WRITE_UINT8(base+REG_thr, c);
         --ser_chan->tx_fifo_avail;
@@ -436,10 +455,11 @@
 {
     unsigned char c;
     cyg_uint8 _lsr;
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
 
     // Wait for char
     do {
         HAL_READ_UINT8(base+REG_lsr, _lsr);
     } while ((_lsr & LSR_RSR) == 0);
@@ -469,10 +489,11 @@
     case CYG_IO_SET_CONFIG_SERIAL_HW_RX_FLOW_THROTTLE:
       {
           cyg_uint8 _mcr;
           pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
           cyg_addrword_t base = ser_chan->base;
+          int step = ser_chan->step;
           cyg_uint32 *f = (cyg_uint32 *)xbuf;
           unsigned char mask=0;
           if ( *len < sizeof(*f) )
               return -EINVAL;
           
@@ -509,26 +530,34 @@
 static void
 pc_serial_start_xmit(serial_channel *chan)
 {
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
-    cyg_uint8 _ier;
+    int step = ser_chan->step;
+    cyg_uint8 _ier, _lsr;
     
     HAL_READ_UINT8(base+REG_ier, _ier);
     _ier |= IER_XMT;                    // Enable xmit interrupt
     HAL_WRITE_UINT8(base+REG_ier, _ier);
 #ifdef CYGPKG_IO_SERIAL_GENERIC_16X5X_XMIT_REQUIRE_PRIME
-    (chan->callbacks->xmt_char)(chan);
+    //some chip(at least LPC2XXX's embedded DUART) may not generate ISR_Tx interrupt after enable IER_XMT,
+    //so we try transmitting here to trigger the ISR_Tx intertupt.
+    HAL_READ_UINT8(base+REG_lsr, _lsr);
+    if ((_lsr & LSR_THE)) {
+        // transmitter holding register ready
+        (chan->callbacks->xmt_char)(chan);
+    }
 #endif
 }
 
 // Disable the transmitter on the device
 static void 
 pc_serial_stop_xmit(serial_channel *chan)
 {
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
     cyg_uint8 _ier;
 
     HAL_READ_UINT8(base+REG_ier, _ier);
     _ier &= ~IER_XMT;                   // Disable xmit interrupt
     HAL_WRITE_UINT8(base+REG_ier, _ier);
@@ -550,10 +579,11 @@
 pc_serial_DSR(cyg_vector_t vector, cyg_ucount32 count, cyg_addrword_t data)
 {
     serial_channel *chan = (serial_channel *)data;
     pc_serial_info *ser_chan = (pc_serial_info *)chan->dev_priv;
     cyg_addrword_t base = ser_chan->base;
+    int step = ser_chan->step;
     cyg_uint8 _isr;
 
     // Check if we have an interrupt pending - note that the interrupt
     // is pending of the low bit of the isr is *0*, not 1.
     HAL_READ_UINT8(base+REG_isr, _isr);
@@ -645,14 +675,16 @@
                 }
             }
             break;
 #endif
         default:
-            // Yes, this assertion may well not be visible. *But*
-            // if debugging, we may still successfully hit a breakpoint
-            // on cyg_assert_fail, which _is_ useful
-            CYG_FAIL("unhandled serial interrupt state");
+            #if 0
+            //some chip(at least Philips SC16C2550B) may generate a interrupt without valid source,
+            //so we print a error message rather than die here.
+            diag_printf("unhandled serial interrupt state""\r\n");
+            #endif
+            break;
         }
 
         HAL_READ_UINT8(base+REG_isr, _isr);
     } // while
 

[-- Attachment #3: Type: text/plain, Size: 148 bytes --]

-- 
Before posting, please read the FAQ: http://ecos.sourceware.org/fom/ecos
and search the list archive: http://ecos.sourceware.org/ml/ecos-discuss

^ permalink raw reply	[flat|nested] 14+ messages in thread

end of thread, other threads:[~2008-01-28 10:34 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2008-01-21 22:04 [ECOS] routing sockets / far end address resolution Daniel Paape
2008-01-22  9:19 ` [ECOS] Half Duplex RS485 Laurie Gellatly
     [not found]   ` <001001c85dd0$c8083160$6501a8c0@global.ds.honeywell.com>
2008-01-23 15:01     ` Wang Cui
2008-01-23 16:34   ` [ECOS] " Grant Edwards
2008-01-23 21:12     ` Laurie Gellatly
2008-01-23 22:03       ` Grant Edwards
2008-01-23 23:06         ` Laurie Gellatly
2008-01-23 23:44           ` Grant Edwards
2008-01-24  9:02           ` Daniel Néri
2008-01-25  1:33       ` wangcui
2008-01-25  2:00         ` Laurie Gellatly
2008-01-25  4:16 wangcui
2008-01-26 20:41 ` Laurie Gellatly
2008-01-28 10:34   ` wangcui

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).