I have a tcl script that polls the serial port DSR line with the
fconfigure command every 3 - 8 ms, selectable by the user. I then know
I have data waiting on the embbeded device and can query it. The
processing of the data is plenty fast enough but getting it off the
remote device is a bit time consuming, I have little control over
that, I would prefer to know the data is available more precisley
with out putting load on the main CPU at the script level.
Is there any way to be more efficient, i.e. get an event/interrupt
perhaps with the new channel setup in 8.5, or am I overstepping the
domain of dynamic languages.
Thanks
Derek
Sorry if my suggestion is stupid, but what's wrong with fileevents ?
Or, can you give details on what [fconfigure] you're doing to query
the line status ? Does it map to some ioctl(), or do you just want to
know when read() would not block ?
-Alex
Yes, should have made my self clear, the code goes something like this
proc checkDSR { fd }
if {[regexp "DSR 1" [fconfigure $fd -ttystatus]} {
#some data available
.
.
} else {
after $::delay checkDSR
}
}
The DSR line is manipulated by a NXP TEA5764 radio chip and indicates
that some RDS data is available.
The requirement is to test that the device under test is still sending
RDS data and to be able to check for any Data errors, which the radio
chip can handle the bit level errors.
I'm using the serial port to extract the rds data via a Uart to I2C
chip, serial ports are still quite common on most PCs, so it seemed
the easiest option.
With modern machines it is possible to poll for this signal but
timings can vary and the OS can have an impact.
As this is a to be part of a test environment, albeit a sanity test, I
want it to be as depenadable as possible.
Derek
I'm not sure fileevents are available for the flow control lines are
they?
Derek
I don't know hardware enough to answer this. But basically, at the
syscall level, can't you just rely on I/O (read()/write()) rather than
polling yourself the flow control bits ?
What happens if you do
set ch [open /dev/YOURSERIAL r]
fconfigure $ch YOUROPTIONS
fileevent $ch readable {puts BYTE:[read $ch 1]}
vwait forever
-Alex
I will give this a go.
My question would then be
Can the fileevent readable be triggered by a flow control state
change.
The device at the other end isn't able to push data over the uart just
signals on the flow control lines
Derek
Otherwise you may use fileevents, see
http://wiki.tcl.tk/1108
Regards, Rolf.
This would usually be the case if hardware-handshake is used (after
all, this is what the DSR/DTR/... lines were made for). Simply put,
the device signals DSR, the computer says go-ahead-send-data by
signalling DTR (or whatever the appropriate line is) and buffers the
data in the serial port buffer, and then the application gets notified
via fileevent-serial-port-is-readable.
Can't you use hardware-handshake here?
| The device at the other end isn't able to push data over the uart
| just signals on the flow control lines
So after you see 'DSR 1', you send a query, and then the device sends
data back?
R'
hi Helmut
When I know data is available I send a binary string to the UarttoI2C
chip, using normal pus nad flush , that tells it to read some bytes,
n, from I2C address,x.
due to timing issues, i.e. waiting for the uartToI2c chip to pass up
the data I have to hang around a bit before I can do a read on the com
port.
I then convert to asci with binary format and process.
Yep, see my belated response to Helmut
I use the serial port normaly expect for polling the DSR line
Derek
I could combine the two I suppose, poll until I get DSr = 1 , then
send the UartToI2C chip a command to send data, using a file event to
read it in.
I have to wait around a little though as the data may not all come at
once checking the queue may be better than what I'm doing now
Derek
I need to clarify that the UartToI2C chip does not do H/W flow
control. I'm using the DSR line directly from the radio chips
interrupt line, via a RS232 level shifter of course.
Derek
This is roughly what I would have suggested.
set fd [open ... ]
fconfigure $fd -encoding binary -blocking 0 ...
fileevent $fd readable [list read_data $fd]
proc read_data {fd} {
if {[eof $fd]} {
close $fd
return
}
set bytes [read $fd]
if [[string length $bytes] > 0} {
# Add $bytes to previous contents, check whether all data are
# there, if so, set flag for processing in/before the
# DSR-checker, or go processing directly.
}
}
# Now poll DSR and send the trigger if high, the fileevent does the rest.
# Sending the trigger could reset the response buffer to empty
R'
I'll take at look at these suggestions at work next week, I have amore
pressing problem in that the polling version that works fine under
linux dosn't under windows.
It seems a write over the serial port is screwwing things up some
where. I have to find out what this issue is before I can get any
further.
Thanks for all your comments, I'll return with some feedback later.
Derek
Anybody heard of serial port FRAME error issues under windows?
Derek
...
set bytes [read $fd]
if {[eof $fd]} {
...
See the [open] mangpage:
FRAME
A stop-bit error has been detected by your UART. Wrong mode settings
with fconfigure -mode or a noisy data line (RXD) may cause this error.
FRAME errors can also occur, when the baud rates do not match exactly
due to different clocks.
Rolf.
Write issues: Many people are not aware, that a non-blocking channel
means non-blocking reads *_and writes_* (this was different for
Windows-Tcl before 8.4).
Non-blocking writes means, that your [puts $chan] returns immediately
buffering the data for background write *_at full baud speed_*. A slower
receiving hardware may have problems with those writes.
[fconfigure $chan -queue] opens alternatives to you:
(A) Blocking channel, polling [fconfigure $chan -queue] in an
after-script until the expected number of bytes have been received.
(B) Non-blocking channel, waiting for the output bytes to be sent after
each write operation.
Hi Derek,
I have been doing lots of serial communication, mostly under Windows,
and when the software said 'frame error' there usually _was_ a frame
error. Hooking up an osci and looking at the signal might help. If you
want to pursue this, here is how I would go about it:
- read one char at a time but put it into a 'catch'
- if the 'catch' triggers toggle one of the handshake lines and have
your osci trigger on this signal.
Something like
if { [catch {read $portFd 1} input] } {
# toggle DTR line
...
# produce some visual output
puts "Error: [fconfigure $portFd -lasterror]"
}
Good luck
Helmut Giese
It seems its an OS related, or a Tcl platform related behaviour, as
the same code and same H/W work fine for Linux.
I'll get a scope on it when I return to work next week.
Derek
I run this script without problems, that I can see anyway, on the same
H/W i.e. PC and target under Linux.
I wonder whats making the difference Windows drivers of Tcl core?
I'll follow Helmut's advice and get some scope traces see if there is
a difference.
Derek
What do you mean by full speed, at the set baud rate?
I presume the latency in the actual write from the background is OS
dependant!, this may not be the issue but would have an impact on what
I'm doing.
I have quite strict timing, i need to detect and process RDS data
within 22mS worse case.
This is fine under Linux, Tcl is quite fast at doing the processing,
getting the data into the script is the slow part!
Derek
I've been using the DTR line for scope triggering which is usefull and
shows me that most of the time is spent in the communications rather
than the processing.
In fact I can hardley see the glitch that is the Tcl processing the
data when on the same scale as looking at the coms over the I2C and
uart.
I did notice, under Linux, a pause just after the device transmitted
the data over the UART and the script being able to process it.
Iassume this is OS and Tcl core latencies.
Derek
P.S. Wish I had a scope at home
I was thinking about this over night and if I know I have data to I
might as well just read , rather than wait for the event to happen.
The only thing the event tells me is that there is data to read, I
currently sit in a while loop for a few counts waiting, not much else
I can do in that time.
Derek
Of course you're right, I should adjust my old habits, especially when
posting code as example ;-)
The eof-before-read works here because at EOF, 'read' gets 0 bytes,
the code does nothing and then the fileevent triggers immediately
again with eof.
R'
By "full speed" I mean that in worst case bytes are transmitted as fast
as the baud rate allows, one character after the other using the
UART-FIFO (if no handshake).
And you don't have any control, because specially Windows is far from
being a real-time OS with predictable timing.
Your OS may even decide not to send/receive characters even for seconds,
if it thinks, that there is something more important to do.
If there are real timing restrictions on the receiver side, then you
need handshake. Adding artificial delays after sending each character
may help (I'm doing this), but there is no guaranty, neither for Linux
nor for Windows.
> I have quite strict timing, i need to detect and process RDS data
> within 22mS worse case.
> This is fine under Linux, Tcl is quite fast at doing the processing,
> getting the data into the script is the slow part!
Generally that should be possible, but this depends on your baud rate
and your serial driver settings.
E.g. in the device manager/com port/Port settings/advanced there is a
slider for interrupt levels for your FIFO which radically changes your
serial I/O latency. I prefer the Low(1) settings meaning that an
interrupt is generated after reception of the first incoming character
without any delay. The Higher(14) settings are useful for very fast
serial transmissions (Modem Internet) to avoid overloading the OS with
serial interrupts.
I'm not totally clear, where is your problem.
Do you suspect that sent characters are not received ?
Or do you have more trouble to detect and process incoming bytes ?
What is your baud rate and your complete [fconfigure] settings ?
Regards,
Rolf.
If you wait in a busy loop, the GUI does not update nor respond to
user input. This effect is much more visible on Windows than on
Linux.
R'
> > I have quite strict timing, i need to detect and process RDS data
> > within 22mS worse case.
> > This is fine under Linux, Tcl is quite fast at doing the processing,
> > getting the data into the script is the slow part!
>
> Generally that should be possible, but this depends on your baud rate
> and your serial driver settings.
Looking on the scope a buad rate of just 115200 seems to be fine, I'm
keeping to this as I can't predict the performance
of the inbuilt uarts. I assume that a modern PC will do 115200.
> E.g. in the device manager/com port/Port settings/advanced there is a
> slider for interrupt levels for your FIFO which radically changes your
> serial I/O latency. I prefer the Low(1) settings meaning that an
> interrupt is generated after reception of the first incoming character
> without any delay. The Higher(14) settings are useful for very fast
> serial transmissions (Modem Internet) to avoid overloading the OS with
> serial interrupts.
I've looked at the buffers when I found I wasn't getting anything back
and shrunk them both down to minimum.
I'll check out the interrupt settings.
> I'm not totally clear, where is your problem.
> Do you suspect that sent characters are not received ?
> Or do you have more trouble to detect and process incoming bytes ?
> What is your baud rate and your complete [fconfigure] settings ?
Under Linux there was no problem per-se but I was wondering if there
was a better way of doing what I'm doing.
Some event driven method rather than polling.
Since starting this thread I found that Windows does not want to play
ball.
I know that the script side of things can handle detecting and
processing the data.
I know that the H/W can deliver the data at the rate required, it all
works under Linux
However it seems under windows I'm missing some aspect of the chain of
command, I do have to do more testing
to determine if there is any thing "on the wire" that could be giving
windows cause for concern.
I suspect my use of the flow control lines to indicate data available
may be causing the windows a problem.
Cant remember the fconfigure off the top of my head, I'll post it
later.
>
> Regards,
> Rolf.
Thanks
Derek
Hi R'
This busy loop is quite short, unless there is an issue receiving
data.
I have a number of time to run round this loop before declaring a time
out.
This is where I found the problem under windows kicking in
Derek
But you don't invoke the loop in the loop? Just make sure you don't...
R'
Yes, generally there is no problem. Everything depends on the total data
amount and your required response time.
> ...
> Since starting this thread I found that Windows does not want to play
> ball.
>
> I know that the script side of things can handle detecting and
> processing the data.
> I know that the H/W can deliver the data at the rate required, it all
> works under Linux
> However it seems under windows I'm missing some aspect of the chain of
> command, I do have to do more testing
> to determine if there is any thing "on the wire" that could be giving
> windows cause for concern.
>
> I suspect my use of the flow control lines to indicate data available
> may be causing the windows a problem.
>
> Cant remember the fconfigure off the top of my head, I'll post it
> later.
Yes, please do this.
And please try to describe briefly your communication requirements.
Who is the master, who is the slave ?
Do both sides send data synchronously/asynchronously (logically) ?
Fixed block sizes ? Required timing ?
Regards, Rolf.
My observations on the scope suggest that the data can be requested and
sent from the target in under 6 ms. This is looking at the Tx and Rx
lines of the uart mind and does not account for OS latency, although on
the read request, using some debug signaling via the DTR line, there
seems to be little latency, unless it is also affecting the control
lines. Again using the same debug signaling I have seen 5 or more milli
seconds of latency before processing the data starts.
>
> Regards, Rolf.
I did make some progress today.
I found that sending 20+ bytes of data through the uart to I2C
device followed quickly by a read of 20+ bytes screws up.
Looking on the scope the write only takes a couple of milliseconds, but
I'm leaving the procedure and calling the next read, before this in some
cases. with a 15- 20ms delay in its gets further.
What I should do is query the I2C status registers on the uart to I2c
chip to confirm that the data went over the I2C. There are timeouts and
nack etc status fields.
I also managed to poll the stae of the DSr line and get some RDS data in.
Again observations on the scope indicate that the after command isn't as
reliably timed as under Linux. I set the after for 8 milliseconds and
get 15!, shrinking it down to 3 didn't seem to do much, but that was a
quick test before leaving for the day. In this case I loose at least 4
blocks of RDS data on a regular basis.
Things I should check now then is how reliable the after command is on
Windows. I'm assuming the poll period on the uart setting does not
affect reading the state of the control lines.
Check that I can read the state of the DSR reliably.
My fconfigure by the way is
fconfigure $fd -mode 115200,n,8,1 -handshake none -translation binary
-blocking 0 -buffering none
More timing test tomorrow I think, find out where
Derek
> Things I should check now then is how reliable the after command is on
> Windows. I'm assuming the poll period on the uart setting does not
> affect reading the state of the control lines.
>
> Check that I can read the state of the DSR reliably.
>
> My fconfigure by the way is
>
> fconfigure $fd -mode 115200,n,8,1 -handshake none -translation binary
> -blocking 0 -buffering none
>
>
> More timing test tomorrow I think, find out where
I have used expect on occasion for a similar setup.
filevent should work too. ( all on linux, sorry, but)
Set up either a
[fileevent readable .. ]
or
[expect_background .]
have the routines append to a receive buffer.
query the DSR line in these eventscripts.
the unix tty stuff provides a "tty_drain" function.
I have no idea if flush provides that when applied
to a serial chan.
uwe
It doesn't. Right now Tcl does nothing special to flush a TTY; it just
makes sure all the data is pushed to the OS.
Donal.
Then one is better of with a
continuous background receive job.
uwe
So confirming what is already on the wiki , that after 1 takes about
15ms on my quad core when running XP
I have to find another way of getting this data reliably under
windows, maybe put a PIC on the board and push the data up so that I
can use fileevents!
Derek