All of lore.kernel.org
 help / color / mirror / Atom feed
* [Xenomai] rt_dev_write returns immediately on xeno_16550A
@ 2013-01-24  3:31 Doug Brunner
  2013-01-24  8:43 ` Wolfgang Grandegger
  2013-01-24  8:55 ` Jan Kiszka
  0 siblings, 2 replies; 5+ messages in thread
From: Doug Brunner @ 2013-01-24  3:31 UTC (permalink / raw)
  To: xenomai

I have a 16550A UART (actually 1/4 of a TI TL16C554) on the ISA bus on 
my WinSystems PPM-LX800-G SBC, and I'm finding that rt_dev_write returns 
control to the userspace process much earlier than I would expect, given 
how the kernel module is set up. (I'm using Xenomai 2.6.1 btw.) 
Fortunately it has a dedicated IRQ line, so I was able to put a logic 
analyzer on the IRQ, the TX line, and the RTS line (which my software 
manually controls to operate an RS485 transceiver).

I initially found that, with the TX FIFO size allowed to default to 16 
bytes, rt_dev_write with a block of size 13 returns immediately. (I 
could tell this because my userspace routine sets RTS just before 
calling rt_dev_write and clears RTS immediately after, so it was visible 
on the logic analyzer.) This makes sense, because I could see that the 
16C554 fires an IRQ immediately on the start of transmission (that 
violates the description of the TX IRQ in its datasheet, but that's a 
matter for TI). This would lead into rt_16550_interrupt, which would see 
that ctx->out_npend == 0 because the data was written to the FIFO in one 
go, and consequently fire out_event. The TX timeout was configured for 
100 ms, so rt_16550_write would be waiting on out_event, and 
rt_dev_write would return at that time.

However...I tried setting the TX FIFO to 1 byte via xeno_16550A module 
parameter, and found that rt_dev_write still returned almost 
immediately. This is what I don't understand, since I could see data 
being transmitted, and the IRQ line going high once for every byte. This 
means that rt_16550_interrupt MUST be getting called, and in turn 
calling rt_16550_tx_interrupt to move data out to the UART. For 
rt_16550_tx_interrupt to be doing so, out_npend must != 0, so out_event 
should not be getting fired until the very last character.

I did notice something odd: at the beginning of rt_16550_write, we 
initialize timeout_seq with ctx->config.rx_timeout. Later that timeout 
sequence is reused while waiting on out_event, which is naturally 
subject to ctx->config.tx_timeout. This seems like a possible source of 
error if tx and rx timeout are not equal--I didn't study the internal 
implementation of the timeout sequence so I'm not sure. However, I tried 
changing the references from rx_timeout to tx_timeout and it produced no 
change in behavior.

Do you know why rt_dev_write would be returning prematurely? I've 
attached the relevant userspace code snippets for reference. Note that 
RawInterface is a subclass of Interface, and higher level code will call 
RawInterface::Write.

-- 
     Doug Brunner

-------------- next part --------------
A non-text attachment was scrubbed...
Name: rt-16550a-snippet.cpp
Type: text/x-c++src
Size: 2784 bytes
Desc: not available
URL: <http://www.xenomai.org/pipermail/xenomai/attachments/20130123/d5da87ef/attachment.cpp>

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

* Re: [Xenomai] rt_dev_write returns immediately on xeno_16550A
  2013-01-24  3:31 [Xenomai] rt_dev_write returns immediately on xeno_16550A Doug Brunner
@ 2013-01-24  8:43 ` Wolfgang Grandegger
  2013-01-24  9:21   ` Wolfgang Grandegger
  2013-01-24  8:55 ` Jan Kiszka
  1 sibling, 1 reply; 5+ messages in thread
From: Wolfgang Grandegger @ 2013-01-24  8:43 UTC (permalink / raw)
  To: Doug Brunner; +Cc: xenomai

On 01/24/2013 04:31 AM, Doug Brunner wrote:
> I have a 16550A UART (actually 1/4 of a TI TL16C554) on the ISA bus on
> my WinSystems PPM-LX800-G SBC, and I'm finding that rt_dev_write returns
> control to the userspace process much earlier than I would expect, given
> how the kernel module is set up. (I'm using Xenomai 2.6.1 btw.)
> Fortunately it has a dedicated IRQ line, so I was able to put a logic
> analyzer on the IRQ, the TX line, and the RTS line (which my software
> manually controls to operate an RS485 transceiver).

The 16550A driver does not support half duplex RS485 mode but I see
below that you it it's handled in your application.

> I initially found that, with the TX FIFO size allowed to default to 16
> bytes, rt_dev_write with a block of size 13 returns immediately. (I
> could tell this because my userspace routine sets RTS just before
> calling rt_dev_write and clears RTS immediately after, so it was visible
> on the logic analyzer.) This makes sense, because I could see that the
> 16C554 fires an IRQ immediately on the start of transmission (that
> violates the description of the TX IRQ in its datasheet, but that's a
> matter for TI). This would lead into rt_16550_interrupt, which would see
> that ctx->out_npend == 0 because the data was written to the FIFO in one
> go, and consequently fire out_event. The TX timeout was configured for

rt_dev_write does store the data in a ring buffer and enable the TX
interrupt. When it occurs, the data is written to the FIFO and a
subsequent interrupt will signal completion when the FIFO is empty and
no more data in the ring buffer.

> 100 ms, so rt_16550_write would be waiting on out_event, and
> rt_dev_write would return at that time.

Yes, if the TX has not complete at that time.

> However...I tried setting the TX FIFO to 1 byte via xeno_16550A module
> parameter, and found that rt_dev_write still returned almost
> immediately. This is what I don't understand, since I could see data
> being transmitted, and the IRQ line going high once for every byte. This
> means that rt_16550_interrupt MUST be getting called, and in turn
> calling rt_16550_tx_interrupt to move data out to the UART. For
> rt_16550_tx_interrupt to be doing so, out_npend must != 0, so out_event
> should not be getting fired until the very last character.

What value does rt_dev_write return?

> I did notice something odd: at the beginning of rt_16550_write, we
> initialize timeout_seq with ctx->config.rx_timeout. Later that timeout
> sequence is reused while waiting on out_event, which is naturally
> subject to ctx->config.tx_timeout. This seems like a possible source of
> error if tx and rx timeout are not equal--I didn't study the internal
> implementation of the timeout sequence so I'm not sure. However, I tried
> changing the references from rx_timeout to tx_timeout and it produced no
> change in behavior.

The ctx->config.rx_timeout is used to lock (via mutex) the TX handling
against RX.

> Do you know why rt_dev_write would be returning prematurely? I've
> attached the relevant userspace code snippets for reference. Note that
> RawInterface is a subclass of Interface, and higher level code will call
> RawInterface::Write.

Not yet. An iPipe trace would help to understand the problem.

Wolfgang.



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

* Re: [Xenomai] rt_dev_write returns immediately on xeno_16550A
  2013-01-24  3:31 [Xenomai] rt_dev_write returns immediately on xeno_16550A Doug Brunner
  2013-01-24  8:43 ` Wolfgang Grandegger
@ 2013-01-24  8:55 ` Jan Kiszka
  1 sibling, 0 replies; 5+ messages in thread
From: Jan Kiszka @ 2013-01-24  8:55 UTC (permalink / raw)
  To: Doug Brunner; +Cc: xenomai

On 2013-01-24 04:31, Doug Brunner wrote:
> I have a 16550A UART (actually 1/4 of a TI TL16C554) on the ISA bus on
> my WinSystems PPM-LX800-G SBC, and I'm finding that rt_dev_write returns
> control to the userspace process much earlier than I would expect, given
> how the kernel module is set up. (I'm using Xenomai 2.6.1 btw.)
> Fortunately it has a dedicated IRQ line, so I was able to put a logic
> analyzer on the IRQ, the TX line, and the RTS line (which my software
> manually controls to operate an RS485 transceiver).
> 
> I initially found that, with the TX FIFO size allowed to default to 16
> bytes, rt_dev_write with a block of size 13 returns immediately. (I
> could tell this because my userspace routine sets RTS just before
> calling rt_dev_write and clears RTS immediately after, so it was visible
> on the logic analyzer.) This makes sense, because I could see that the
> 16C554 fires an IRQ immediately on the start of transmission (that
> violates the description of the TX IRQ in its datasheet, but that's a
> matter for TI). This would lead into rt_16550_interrupt, which would see
> that ctx->out_npend == 0 because the data was written to the FIFO in one
> go, and consequently fire out_event. The TX timeout was configured for
> 100 ms, so rt_16550_write would be waiting on out_event, and
> rt_dev_write would return at that time.
> 
> However...I tried setting the TX FIFO to 1 byte via xeno_16550A module
> parameter, and found that rt_dev_write still returned almost
> immediately. This is what I don't understand, since I could see data
> being transmitted, and the IRQ line going high once for every byte. This
> means that rt_16550_interrupt MUST be getting called, and in turn
> calling rt_16550_tx_interrupt to move data out to the UART. For
> rt_16550_tx_interrupt to be doing so, out_npend must != 0, so out_event
> should not be getting fired until the very last character.
> 
> I did notice something odd: at the beginning of rt_16550_write, we
> initialize timeout_seq with ctx->config.rx_timeout.

Oh, classic copy&paste mistake. A very old one (as old as the driver).
Please send a patch.

> Later that timeout
> sequence is reused while waiting on out_event, which is naturally
> subject to ctx->config.tx_timeout. This seems like a possible source of
> error if tx and rx timeout are not equal--I didn't study the internal
> implementation of the timeout sequence so I'm not sure. However, I tried
> changing the references from rx_timeout to tx_timeout and it produced no
> change in behavior.
> 
> Do you know why rt_dev_write would be returning prematurely? I've
> attached the relevant userspace code snippets for reference. Note that
> RawInterface is a subclass of Interface, and higher level code will call
> RawInterface::Write.

This behaviour makes sense, even with a hw fifo lenght of 1: 16550A's
rt_dev_write works against a software buffer (out_buf) first, and that
one is still 4K. Only if you fill up the buffer, rt_dev_write will start
to block (or time out).

Jan

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 263 bytes
Desc: OpenPGP digital signature
URL: <http://www.xenomai.org/pipermail/xenomai/attachments/20130124/4f064d50/attachment.pgp>

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

* Re: [Xenomai] rt_dev_write returns immediately on xeno_16550A
  2013-01-24  8:43 ` Wolfgang Grandegger
@ 2013-01-24  9:21   ` Wolfgang Grandegger
  2013-01-24  9:32     ` Wolfgang Grandegger
  0 siblings, 1 reply; 5+ messages in thread
From: Wolfgang Grandegger @ 2013-01-24  9:21 UTC (permalink / raw)
  To: Doug Brunner; +Cc: xenomai

On 01/24/2013 09:43 AM, Wolfgang Grandegger wrote:
> On 01/24/2013 04:31 AM, Doug Brunner wrote:
>> I have a 16550A UART (actually 1/4 of a TI TL16C554) on the ISA bus on
>> my WinSystems PPM-LX800-G SBC, and I'm finding that rt_dev_write returns
>> control to the userspace process much earlier than I would expect, given
>> how the kernel module is set up. (I'm using Xenomai 2.6.1 btw.)
>> Fortunately it has a dedicated IRQ line, so I was able to put a logic
>> analyzer on the IRQ, the TX line, and the RTS line (which my software
>> manually controls to operate an RS485 transceiver).
> 
> The 16550A driver does not support half duplex RS485 mode but I see
> below that you it it's handled in your application.
> 
>> I initially found that, with the TX FIFO size allowed to default to 16
>> bytes, rt_dev_write with a block of size 13 returns immediately. (I
>> could tell this because my userspace routine sets RTS just before
>> calling rt_dev_write and clears RTS immediately after, so it was visible
>> on the logic analyzer.) This makes sense, because I could see that the
>> 16C554 fires an IRQ immediately on the start of transmission (that
>> violates the description of the TX IRQ in its datasheet, but that's a
>> matter for TI). This would lead into rt_16550_interrupt, which would see
>> that ctx->out_npend == 0 because the data was written to the FIFO in one
>> go, and consequently fire out_event. The TX timeout was configured for
> 
> rt_dev_write does store the data in a ring buffer and enable the TX
> interrupt. When it occurs, the data is written to the FIFO and a
> subsequent interrupt will signal completion when the FIFO is empty and
> no more data in the ring buffer.
> 
>> 100 ms, so rt_16550_write would be waiting on out_event, and
>> rt_dev_write would return at that time.
> 
> Yes, if the TX has not complete at that time.
> 
>> However...I tried setting the TX FIFO to 1 byte via xeno_16550A module
>> parameter, and found that rt_dev_write still returned almost
>> immediately. This is what I don't understand, since I could see data
>> being transmitted, and the IRQ line going high once for every byte. This
>> means that rt_16550_interrupt MUST be getting called, and in turn
>> calling rt_16550_tx_interrupt to move data out to the UART. For
>> rt_16550_tx_interrupt to be doing so, out_npend must != 0, so out_event
>> should not be getting fired until the very last character.
> 
> What value does rt_dev_write return?
> 
>> I did notice something odd: at the beginning of rt_16550_write, we
>> initialize timeout_seq with ctx->config.rx_timeout. Later that timeout
>> sequence is reused while waiting on out_event, which is naturally
>> subject to ctx->config.tx_timeout. This seems like a possible source of
>> error if tx and rx timeout are not equal--I didn't study the internal
>> implementation of the timeout sequence so I'm not sure. However, I tried
>> changing the references from rx_timeout to tx_timeout and it produced no
>> change in behavior.
> 
> The ctx->config.rx_timeout is used to lock (via mutex) the TX handling
> against RX.
> 
>> Do you know why rt_dev_write would be returning prematurely? I've
>> attached the relevant userspace code snippets for reference. Note that
>> RawInterface is a subclass of Interface, and higher level code will call
>> RawInterface::Write.
> 
> Not yet. An iPipe trace would help to understand the problem.

Ah, I remember. FIFO empty does not mean that the transfer has been
complete (on the bus). But that's what you need for toggling RTS for RS485.

Wolfgang.



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

* Re: [Xenomai] rt_dev_write returns immediately on xeno_16550A
  2013-01-24  9:21   ` Wolfgang Grandegger
@ 2013-01-24  9:32     ` Wolfgang Grandegger
  0 siblings, 0 replies; 5+ messages in thread
From: Wolfgang Grandegger @ 2013-01-24  9:32 UTC (permalink / raw)
  To: Doug Brunner; +Cc: xenomai

On 01/24/2013 10:21 AM, Wolfgang Grandegger wrote:
> On 01/24/2013 09:43 AM, Wolfgang Grandegger wrote:
>> On 01/24/2013 04:31 AM, Doug Brunner wrote:
>>> I have a 16550A UART (actually 1/4 of a TI TL16C554) on the ISA bus on
>>> my WinSystems PPM-LX800-G SBC, and I'm finding that rt_dev_write returns
>>> control to the userspace process much earlier than I would expect, given
>>> how the kernel module is set up. (I'm using Xenomai 2.6.1 btw.)
>>> Fortunately it has a dedicated IRQ line, so I was able to put a logic
>>> analyzer on the IRQ, the TX line, and the RTS line (which my software
>>> manually controls to operate an RS485 transceiver).
>>
>> The 16550A driver does not support half duplex RS485 mode but I see
>> below that you it it's handled in your application.
>>
>>> I initially found that, with the TX FIFO size allowed to default to 16
>>> bytes, rt_dev_write with a block of size 13 returns immediately. (I
>>> could tell this because my userspace routine sets RTS just before
>>> calling rt_dev_write and clears RTS immediately after, so it was visible
>>> on the logic analyzer.) This makes sense, because I could see that the
>>> 16C554 fires an IRQ immediately on the start of transmission (that
>>> violates the description of the TX IRQ in its datasheet, but that's a
>>> matter for TI). This would lead into rt_16550_interrupt, which would see
>>> that ctx->out_npend == 0 because the data was written to the FIFO in one
>>> go, and consequently fire out_event. The TX timeout was configured for
>>
>> rt_dev_write does store the data in a ring buffer and enable the TX
>> interrupt. When it occurs, the data is written to the FIFO and a
>> subsequent interrupt will signal completion when the FIFO is empty and
>> no more data in the ring buffer.
>>
>>> 100 ms, so rt_16550_write would be waiting on out_event, and
>>> rt_dev_write would return at that time.
>>
>> Yes, if the TX has not complete at that time.
>>
>>> However...I tried setting the TX FIFO to 1 byte via xeno_16550A module
>>> parameter, and found that rt_dev_write still returned almost
>>> immediately. This is what I don't understand, since I could see data
>>> being transmitted, and the IRQ line going high once for every byte. This
>>> means that rt_16550_interrupt MUST be getting called, and in turn
>>> calling rt_16550_tx_interrupt to move data out to the UART. For
>>> rt_16550_tx_interrupt to be doing so, out_npend must != 0, so out_event
>>> should not be getting fired until the very last character.
>>
>> What value does rt_dev_write return?
>>
>>> I did notice something odd: at the beginning of rt_16550_write, we
>>> initialize timeout_seq with ctx->config.rx_timeout. Later that timeout
>>> sequence is reused while waiting on out_event, which is naturally
>>> subject to ctx->config.tx_timeout. This seems like a possible source of
>>> error if tx and rx timeout are not equal--I didn't study the internal
>>> implementation of the timeout sequence so I'm not sure. However, I tried
>>> changing the references from rx_timeout to tx_timeout and it produced no
>>> change in behavior.
>>
>> The ctx->config.rx_timeout is used to lock (via mutex) the TX handling
>> against RX.
>>
>>> Do you know why rt_dev_write would be returning prematurely? I've
>>> attached the relevant userspace code snippets for reference. Note that
>>> RawInterface is a subclass of Interface, and higher level code will call
>>> RawInterface::Write.
>>
>> Not yet. An iPipe trace would help to understand the problem.
> 
> Ah, I remember. FIFO empty does not mean that the transfer has been
> complete (on the bus). But that's what you need for toggling RTS for RS485.

IIRC, the 16550A is not be able to signal the RTSER_EVENT_TXEMPTY empty.
Therefore you need to poll the "Tramsmitter Empty" bit in the line
status register. Please check the datasheet of the TL16C554.

Wolfgang.


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

end of thread, other threads:[~2013-01-24  9:32 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2013-01-24  3:31 [Xenomai] rt_dev_write returns immediately on xeno_16550A Doug Brunner
2013-01-24  8:43 ` Wolfgang Grandegger
2013-01-24  9:21   ` Wolfgang Grandegger
2013-01-24  9:32     ` Wolfgang Grandegger
2013-01-24  8:55 ` Jan Kiszka

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.