Unfortunately my task being locked on the
GNAT_Serial_Communications.write call with no error or exception.
I opened the port with these options
At first I opened this port with
GNAT.Serial_Communications.Open (Port => the_port, Name => "/dev/
ttyUSB0");
GNAT.Serial_Communications.Set (Port => the_port,
Rate =>
GNAT.Serial_Communications.B115200,
Bits =>
GNAT.Serial_Communications.CS8,
Parity =>
GNAT.Serial_Communications.None);
I have also tried a half second timeout by opening the port with this
GNAT.Serial_Communications.Open (Port => the_port, Name => "/dev/
ttyUSB0");
GNAT.Serial_Communications.Set (Port => the_port,
Rate =>
GNAT.Serial_Communications.B115200,
Bits =>
GNAT.Serial_Communications.CS8,
Parity =>
GNAT.Serial_Communications.None,
Timeout => 0.5);
Unfortunately the write call is still indefinetely locking and the
timeout does not seem to apply to writes. Some over things of note are
that I am beginning the write string with a '$' and the end of the
string with a ASCII.cr, is anyone able to shed any light on this ?
> I have been using this package in code which receives and sends messages
> across a serial interface to some electronics.
>
> Unfortunately my task being locked on the
> GNAT_Serial_Communications.write call with no error or exception. I
> opened the port with these options
> Unfortunately the write call is still indefinetely locking and the
> timeout does not seem to apply to writes.
Is there a way to set "control flow" to "none"?
It is possible the hardware is sitting waiting for a handshake signal.
Also have you checked the serial link in any other way, e.g. with Minicom
(or Hyperterminal on Windows)? Or with another terminal (or PC running
Minicom) in the place of "some electronics".
- Brian
The serial link has been tested using hyperterminal and a windows
application, I am now constructing a linux application using Ada
rather than C sharp which was used for windows. The parity / 8 bit
stuff is definitely ok. I was fishing to see if anyone had used the
serial communications and could confirm it was all working etc or had
a suggestion on why etc. Thanks for your help Brian
> I was fishing to see if anyone had used the
> serial communications and could confirm it was all working etc or had
> a suggestion on why etc. Thanks for your help Brian
I've used GNAT.Serial_Communications on Windows and Linux to transmit
commands to/receive responses from robots via a USB Bluetooth
transceiver.
The package worked as expected for me. I certainly didn't have any
issues with the package blocking on writes. Where is your program
blocking? Is it:
a) right after the Ada statement prior to the Write, but before any
data is transmitted over the serial port
b) mid-transmission (i.e., some of the data is received at the distant
end, but not all of it)
c) after transmitting all data, but before executing the next Ada
statement
Alex
Its actually blocking on top of the write. Also I've discovered after
much experimentation that the writes are not doing the job when it
does not block up. Usually it blocks up after 3-4 write attempts. I
expect I need to discover what is happening at the other end of the
wire, but its my first experience of using a serial port for anything.
I suspect there is an option I am not engaging in the setting up of
the port. I am using the gpl version so I was thinking there could be
a bug that is not in the gnat pro version, but I don't want to be a
bad craftsman :) and gnat are usually pretty much on top of stuff like
that from previous experience, but then again its a relatively new
addition to the gnat compiler and no ones perfect. But.... its usually
me.....
Saying that though I am successfully reading from the port the
incoming messages although they do appear in sections and I have to
keep re reading the port to get the full message...
> Its actually blocking on top of the write. Also I've discovered after
> much experimentation that the writes are not doing the job when it
> does not block up. Usually it blocks up after 3-4 write attempts. I
> expect I need to discover what is happening at the other end of the
> wire, but its my first experience of using a serial port for anything.
>
> I suspect there is an option I am not engaging in the setting up of
> the port. I am using the gpl version so I was thinking there could be
> a bug that is not in the gnat pro version, but I don't want to be a
> bad craftsman :) and gnat are usually pretty much on top of stuff like
> that from previous experience, but then again its a relatively new
> addition to the gnat compiler and no ones perfect. But.... its usually
> me.....
>
> Saying that though I am successfully reading from the port the
> incoming messages although they do appear in sections and I have to
> keep re reading the port to get the full message...
I'm not exactly sure what you mean by "blocking on top of the write,"
but if I understand correctly, your calls to Write are outputting the
data correctly up to a point. You're just missing the tail end of the
data, right?
If my understanding is correct, I suspect that you are sending the data
faster than it is being read by the destination, causing the input
buffer to fill up. Once it is full, all the new data will just be
ignored. When you finally get around to reading the data from the port,
the only data available for you to read is that which is in the buffer.
While Write did actually send everything as it should have, some of it
got discarded for lack of buffer space. Since you haven't received all
the data you expected, though, it appears like Write stopped working.
Your statement that the "writes are not doing their job when it does
not block" suggests to me that your "electronics" are not actually
taking the data out of the input buffer and using it, resulting in both
the discarding of input described above and lack of action on the data
actually received. You are using a USB port, and I understand that USB
transmission is relatively harder than RS-232/UART transmission (which
is what I was doing with my Bluetooth transceiver). It may be that you
need to make a call to the device driver for the receiving device,
telling it that data is available to read, in order to cause it to read
the data, but I'm just guessing now.
HTH, and good luck! I'd be interested to hear what the solution is when
you do get it figured out.
Alex
I suspect it's the speed setting. Serial ports default to 9600 baud
which is slow so you're filling the buffers up with the first few writes
as they're unable to get the data out quick enough and then they start
to block cos there's nowhere to put the data.
> Saying that though I am successfully reading from the port the
> incoming messages although they do appear in sections and I have to
> keep re reading the port to get the full message...
This is how serial interfaces usually work. The lowest level read
function returns the number of bytes actually read.
I found the problem. Its very embarassing and completely my own fault!
Basically I did not have the write access to the usb port! I am using
ubuntu for this. Just to let those who are interested know.
Actually this is not the problem I spoke too soon. Minicom will talk
and read the correct values.
However gnat will read correctly but not write to the port properly,
but its not hanging anymore so thats a plus. I just cannot see why
minicom would write the string correctly to the port but when I write
the string to the port through gnat.serial_communication it does not
work!!
GNAT.Serial_Communications.Write(Port => The_Port,
Buffer =>
String_To_Stream(Broadcast_Message));
function String_To_Stream ( The_String : in String) return
Ada.Streams.Stream_Element_Array is
Return_Value :
Ada.Streams.Stream_Element_Array(1..The_String'length);
begin
Put (" Start of Data out :- ");
for count in
1..Ada.Streams.Stream_Element_Offset(The_String'Length) loop
Return_Value(count) :=
character'pos(The_String(Integer(count)));
int_io.Put(Integer(Return_Value(count)));
end loop;
Put (" End of Data out ");
Put_Line (The_String);
Return Return_Value(1..The_String'Length);
end String_To_Stream;
Is there anything you can see thats wrong there ?
With the Minicom reference, I assume this is a Linux/Unix system (I have
not been following this thread in detail).
The obvious place to start looking are the flow control signals and if
they are been set (and used) correctly.
Have you looked at a full stty output when Minicom is running and compared
it to the settings when your program is running and made sure that the
flow control modes are been setup correctly ?
What flow control is expected by the device receiving your output ?
If hardware flow control is expected by the other device, is your program
asserting the flow control signals (either directly or indirectly)
correctly ?
Simon.
--
Simon Clubley, clubley@remove_me.eisner.decus.org-Earth.UFP
Microsoft: Bringing you 1980s technology to a 21st century world
1115200 , 8N1 , NOR
the port in my code is set with
GNAT.Serial_Communications.Set (Port => The_Port,
Rate =>
GNAT.Serial_Communications.B115200,
Bits =>
GNAT.Serial_Communications.CS8,
Stop_Bits =>
GNAT.Serial_Communications.one,
Parity =>
GNAT.Serial_Communications.None);
I'm not sure what NOR means and if this is some to do with flow
control, there seems to be no option to set this within the
gnat.serial_communications package. The electronics I am working with
has no hardware or software handshaking. Is handshaking the same as
flow control ? The settings in minicom also has no hardware or
software flow control. hhhmmm
You assume that The_String'First = 1, which will not be the case if you pass a
slice with a different lower bound. However, that will cause Constraint_Error
(unless you have turned off this check), which does not seem to be the problem.
> Return Return_Value(1..The_String'Length);
I see no reason for the slice.
You should be able to replace the body of String_To_Stream with a simple
Unchecked_Conversion:
with Ada.Streams;
with Ada.Text_IO;
with Ada.Unchecked_Conversion;
procedure Stream_Convert is
subtype String3 is String (1 .. 3);
From : constant String3 := "abc";
subtype Stream3 is Ada.Streams.Stream_Element_Array (1 .. From'Length);
function To_Stream is new Ada.Unchecked_Conversion (Source => String3,
Target => Stream3);
To : Stream3;
begin -- Stream_Convert
To := To_Stream (From);
Output : for I in To'range loop
Ada.Text_IO.Put (Item => To (I)'Img);
end loop Output;
end Stream_Convert;
--
Jeff Carter
"Unix and C are the ultimate computer viruses."
Richard Gabriel
99
Yes, handshaking is the same as flow control.
You _really_ need to look at the _full_ stty settings for the comms port
when Minicom is running and when your program is running.
One possible failure mode (there are many others):
If your remote device does not manipulate the RTS/CTS lines, and if
Minicom reconfigures the port while it's running to also ignore the
RTS/CTS lines, then Minicom will work.
However, _if_ the default setting for the Linux/Unix comms port your Ada
program is opening is to implement RTS/CTS flow control then your remote
device will never receive data because the Linux/Unix system will be
waiting for the CTS line to be asserted by your remote device (which will
never happen).
_If_ hardware flow control is enabled on your Linux/Unix PC comms port,
you need to either reconfigure the comms port (either within your program
or using stty) to disable the flow control or implement flow control on
the remote device. If you do the latter, don't forget to use a correctly
wired serial cable.
This is making a lot of sense to me. Minicom is working perfectly with
setting the commands on the electronics. However for some reason, the
same commands relayed by the ada program are simply not received.
There does not seem a way in GNAT.Serial_Communications to disable
hardware and software flow control, I'll have a look at how linux does
it.
Have you compared the _full_ output from stty yet when Minicom and your
program are running ?
As I mention above, there are other possible failure modes and the full
output from stty will tell you if flow control is enabled on the port or
not. Checking the flow control is just the first thing I would check;
it is not the only thing.
Read the man page for stty. :-) You may save yourself quite a bit of time
if the flow control settings are not the problem.
This is the full output when minicom is running
tony@tony-workstation:~$ stty --file=/dev/ttyUSB0
speed 115200 baud; line = 0;
eof = ^A; min = 1; time = 5;
ignbrk -brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke
tony@tony-workstation:~$
This is the full output when the ada program is running
tony@tony-workstation:~$
tony@tony-workstation:~$ stty --file=/dev/ttyUSB0
speed 115200 baud; line = 0;
eof = ^A; min = 0; time = 100;
-brkint -icrnl -imaxbel
-opost -onlcr
-isig -icanon -iexten -echo -echoe -echok -echoctl -echoke
tony@tony-workstation:~$
The differences are ignbrk flag is up on the minicom readout and min
=1. I assume the time=100 bit is from the timeout parameter set
procedure in gnat.serial_communication.
Another thing occurred to me is that do I need to open the same port
twice for my read calls and my write calls. i.e. have two variables
read_port, write_port : gnat.serial_communications.serial_port;
which both open ttyUSB0 ? or I am barking up the wrong tree
I did that because I got a bit paranoid with the way ada handles
strings after finding out something new in the way its handles them. I
used to think that a slice's indexes changed when it went through a
procedure or functions paramaters but came unstuck by it. Thanks for
the code, I'll give it a try once I get this naughty serial port
sorted.
out put with minicom
tony@tony-workstation:~$ stty --file=/dev/ttyUSB0 -a
speed 115200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^A; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 1; time = 5;
-parenb -parodd cs8 hupcl -cstopb cread clocal -crtscts
ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -
ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0
ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -
tostop
-echoprt -echoctl -echoke
tony@tony-workstation:~$
Output with ada program
tony@tony-workstation:~$ stty --file=/dev/ttyUSB0 -a
speed 115200 baud; rows 0; columns 0; line = 0;
intr = ^C; quit = ^\; erase = ^?; kill = ^U; eof = ^A; eol = <undef>;
eol2 = <undef>; swtch = <undef>; start = ^Q; stop = ^S; susp = ^Z;
rprnt = ^R;
werase = ^W; lnext = ^V; flush = ^O; min = 0; time = 100;
-parenb -parodd cs8 -hupcl -cstopb cread clocal crtscts
-ignbrk -brkint -ignpar -parmrk -inpck -istrip -inlcr -igncr -icrnl -
ixon -ixoff
-iuclc -ixany -imaxbel -iutf8
-opost -olcuc -ocrnl -onlcr -onocr -onlret -ofill -ofdel nl0 cr0 tab0
bs0 vt0
ff0
-isig -icanon -iexten -echo -echoe -echok -echonl -noflsh -xcase -
tostop
-echoprt -echoctl -echoke
tony@tony-workstation:~$
Whoever thought a serial port did so much?
> Just found the stty -a setting which gives me all settings, I think that
> was maybe the full out put you were talking about before
>
> out put with minicom
>
> cs8 hupcl -cstopb cread clocal -crtscts ignbrk -brkint -ignpar -parmrk
> Output with ada program
>
> -parodd cs8 -hupcl -cstopb cread clocal crtscts -ignbrk -brkint -ignpar
But here, Minicom has -crtscts, Gnat has crtscts
which is pointing at a difference in the handshaking.
I bowed out of this thread earlier because I have no experience with USB
serial interfaces, or the specific Gnat library.
But this does look like you have to find a way to turn RTS/CTS
handshaking off.
> Whoever thought a serial port did so much?
heh, there are so many combinations it used to be the norm to hack serial
interfaces with a soldering iron. If all else fails, you can always short
pins 4 and 6 at t'other end (assuming a traditional 25 pin D connector)
to fake the handshaking. Not recommended with a USB port...
- Brian
Well spotted, I missed that after several trawls through. It also
screams out as the problem I am having. Now I just got to figure the
proper linux command to switch the handshaking off. Its interesting
that minicom seems to detect all this and configure itself so well....
You can use stty itself to change the default RTS/CTS setting before
running the Ada program.
However, this will not work if the GNAT serial port library package
issues any serial port flow control calls itself to reconfigure the
serial port.
I don't know if GNAT does this; I don't use the GNAT serial port
packages.
Try a "man 3 termios" on your Linux system for further information.
Looking at the gnat sercom package it has a total lack of options for
flow control. I am going to look at posix packages now and its options
with serial interfaces. Does anyone know if Adacore are planning to
add some more functionality to this package?
Looking at the gnat sercom package it has a total lack of options for
Just to let you all know ( I'm sure the world was waiting with baited
breath!) that thanks to the help received, its now all working. I'll
document what the problem was with some additional stuff to let future
people know.
It was the flow control setting and it can be fixed by opening another
terminal window and using the command
stty --file=/dev/ttyUSB0 -crtscts
However - any ada program compiled with the gnat serial communications
package if run again will reset the port to add flow control so this
needs it will need to be done again. Which is unfortunate for me and
anyone with non flow control electronics. I expect this will occur
everytime the port is opened. Out of interest do all you serial port
tinkerers out there use flow control?
I think you'll have to create a task-specific binding to ioctl(2) to
set the flow control options before writing to the port. The fact
that ioctl(2) is variadic, non-portable and non-standard may explain
why there is nothing in GNAT.Serial_Communications related to flow
control.
If you're not sure what arguments to pass to ioctl, maybe you can try:
strace stty --file=/dev/ttyUSB0 -crtscts
--
Ludovic Brenta.
Interesting. I would not expect that; there may be something resetting
the port (maybe in the GNAT library or the version of the Linux kernel you
are using) without you realising it as I don't recall seeing that while
working with Linux serial ports (which, for the set of applications in
question, I do in C and not Ada).
> anyone with non flow control electronics. I expect this will occur
> everytime the port is opened. Out of interest do all you serial port
> tinkerers out there use flow control?
Yes. It's a hardware based RTS/CTS flow control setup and it's a integral
part of my microcontroller UART library (at least for the hardware UART;
I also created a Tx only software UART for my library and I don't support
flow control on that as it's just used for debugging).
This is for microcontroller to microcontroller communications however.
When I connect the devices to the Linux PC, I use the standard MAX232
setup and since it's been a number of months since I last did this, I
cannot remember if my library supports inverting the RTS/CTS lines
to allow the signals to pass through the MAX232 or if I just disable
the flow control on both sides as I am generally just debugging.
Given that I need to transmit 8 bit data on these ports, I have not
bothered creating a software flow control Xon/Xoff implementation.
HHhhmm a task specific binding? is that a c interface just for one
task? I ask because I know I want to do this but just not sure how to,
and I 've not heard of that phrase before.
I didn't remember this bit correctly. (It's been several years since I
wrote this library.)
When I originally wrote the library, I incorrectly believed that RTS/CTS
logic 1 and Tx/Rx logic 1 were at the same voltage levels. Since the
library was been used on both sides of the link, this didn't matter.
I later discovered that the "asserted" voltage level for RTS/CTS was
inverted when compared to the Tx/Rx voltage levels.
I've just looked around for a online reference and I see Wikipedia has a
writeup about it:
http://en.wikipedia.org/wiki/MAX232
By "task" I meant "the task at hand", not the Ada keyword task as in
multitasking. Basically, this means creating a different binding for
ioctl for each thing you want to achieve with it. For more details, you
can peruse the thread "The black magic of ioctl" on comp.lang.ada from
October 2010.
--
Ludovic Brenta.
> I think you'll have to create a task-specific binding to ioctl(2) to
> set the flow control options before writing to the port.
...
> If you're not sure what arguments to pass to ioctl, maybe you can try:
>
> strace stty --file=/dev/ttyUSB0 -crtscts
Does anyone know if the code below would work? I don't have a Linux box
handy here, so I can't test it myself. I'm just going off of some notes
on forking Linux child processes I acquired -- I've never actually done
this, myself....
** begin code **
with Ada.Text_IO; use Ada.Text_IO;
with Interfaces.C;
with Interfaces.C.Strings;
procedure Main is
procedure Config_Stty is
package C renames Interfaces.C;
-- create an array that contains each portion of the command
-- to be executed
-- array must contain a null pointer in the last element
Stty_Cmd : C.Strings.Chars_Ptr_Array :=
(C.Strings.New_String ("stty"),
C.Strings.New_String ("--file=/dev/ttyUSB0"),
C.Strings.New_String ("-crtscts"),
C.Strings.Null_Ptr);
-- create an Ada-style prototype as an interface to the C execvp
-- function and associate the two with an Import pragma
procedure Execvp (File : C.Strings.Chars_Ptr;
Args : C.Strings.Chars_Ptr_Array);
pragma Import (C, Execvp, "execvp");
-- create an Ada-style prototype to the C fork function so
-- you can call execvp then resume this program's execution
function Fork return Long_Integer;
pragma Import (C, Fork, "fork");
-- create an Ada-style prototype to the C waitpid function so
-- the parent will wait until the forked process completes
procedure Waitpid (Pid : Long_Integer; Stat_Loc, Options :
Integer);
pragma Import (C, Waitpid, "waitpid");
Pid : Long_Integer;
begin -- Config_Stty
Put_Line ("Configuring serial port...");
-- create child process
Pid := Fork;
if Pid = 0 then -- I'm the child process
-- call execvp with the stty command
Execvp (Stty_Cmd (Stty_Cmd'First), Stty_Cmd);
-- Execvp does not return unless there's an error;
-- should probably check for that here and raise exception on
error
elsif Pid > 0 then -- I'm the parent process
Waitpid (Pid, 0, 0);
Put_Line ("Continuing execution...");
else -- if Fork returns -1, then it was unsuccessful
Put_Line ("Unable to create new process.");
end if;
end Config_Stty;
begin -- Main
Config_Stty;
-- serial port's ready to go; do the rest of your stuff here...
end Main;
> When I connect the devices to the Linux PC, I use the standard MAX232
> setup and since it's been a number of months since I last did this,
s/months/decades/ and you'll understand why my advice was not more
specific...
Might be worth reading a little bit about the Linux sysfs interface ...
if the serial ports appear there, it may be possible to (shell command
version)
echo 1 > /sys/something/ttyusb0/flow_ctrl_something
in which case, opening it as a normal file and writing to it within your
Ada program will also work.
Again I can't be more specific as I know very little about sysfs, but it
seems to be a fairly recent/developing area with neat possibilities.
- Brian
I don't think this would work because the port's settings need to be
overwritten after it is opened, as Gnat sercom will open it with
control flow enabled. I suspect it may be best to modify the serial
communications package so that there is a control flow option within
the set port procedure. Or to make a copy of the sercom package, call
it something else, modify that and use it.
>
> I don't think this would work because the port's settings need to be
> overwritten after it is opened, as Gnat sercom will open it with
> control flow enabled.
So open the port before calling this code. I don't see why that
wouldn't work.
> On 2011-04-19, tonyg <tonyt...@gmail.com> wrote:
>>
>> Just to let you all know ( I'm sure the world was waiting with baited
>> breath!) that thanks to the help received, its now all working. I'll
>> document what the problem was
...
>> stty --file=/dev/ttyUSB0 -crtscts
>>
>> However - any ada program compiled with the gnat serial communications
>> package if run again will reset the port to add flow control so this
>> needs it will need to be done again. Which is unfortunate for me and
>
> Interesting. I would not expect that;
Having just read g-sercom-linux.adb, this is now exactly what I would
expect.
The "Set" procedure in Gnat.Serial_Communications uses "tcsetattr" and
"tcgetattr" C syscalls to do the job of setting baud rate ... "man
tcsetattr" should give you the relevant information.
Unfortunately it uses the pseudo-code
tcgetattr(current settings);
overwrite baud rate and other things you want to set;
overwrite control settings inc. ctsrts for good measure
tcsetattr(current settings);
to do the job.
See g-sercom-linux.adb for more details. It's very easy to understand
what it's doing.
Forget my earlier remarks about sysfs etc (maybe someday, it's clearly
the intent to allow control that way, but for an "obsolete" interface
it's not going to get much priority).
Also forget using ioctl calls; tc[g|s]etattr are a good wrapper over ioctl
without the variadic problems.
So you are left with two options:
(1) modify g-sercom-linux.adb to do the job, or at least, what it's
supposed to (not corrupt settings unnecessarily). Then ... what has to
happen to regenerate the GNAT.Serial_Communications package? Rebuild
libada, or does the change happen next time you build your app? I am
showing my ignorance of Gnat here...
Then perhaps, submit patches upstream?
(2) Copy the basic approach from procedure Set.
Namely, after opening the port, import and use tcgetattr, tcsetattr in
your own code.
- Brian
> (1) modify g-sercom-linux.adb to do the job, or at least, what it's
> supposed to (not corrupt settings unnecessarily). Then ... what has to
> happen to regenerate the GNAT.Serial_Communications package? Rebuild
> libada, or does the change happen next time you build your app? I am
> showing my ignorance of Gnat here...
Put the modified g-sercom-linux.adb in the compiler's search path, then
use the "-a" flag to gnatmake.
(a) I think that gprbuild may not support the -a flag?
(b) don't say "gnatmake -f" for a full rebuild or you'll end up
rebuilding the RTS!
Yes that would work. I think I am going to mod the gnat-sercom package
though for elegance's sake. Many thanks for taking the time, looking
at it has improved my knowledge of Ada.
yep its going to be a mod to g-sercom.ad(sb), thanks for the help
guys. The obsolete interface thing is quite funny given now that it is
controlling robots and all sorts of automation. I want to say
something funny about this, but I guess I'll just modify the package!
Here are the 'monkey with a spanner' changes I have done, :o)
g-sercom.ads
type Flow_Control is (None, Active);
procedure Set
(Port : Serial_Port;
Rate : Data_Rate := B9600;
Bits : Data_Bits := CS8;
Stop_Bits : Stop_Bits_Number := One;
Parity : Parity_Check := None;
Block : Boolean := True;
Timeout : Duration := 10.0;
Flow : Flow_Control := Active);
g-sercom.adb
C_Flow_Control : Constant array (Flow_Control) of unsigned :=
(None => 0, Active => CRTSCTS);
procedure Set
(Port : Serial_Port;
Rate : Data_Rate := B9600;
Bits : Data_Bits := CS8;
Stop_Bits : Stop_Bits_Number := One;
Parity : Parity_Check := None;
Block : Boolean := True;
Timeout : Duration := 10.0;
Flow : Flow_Control := Active)
Current.c_cflag := C_Data_Rate (Rate)
or C_Bits (Bits)
or C_Stop_Bits (Stop_Bits)
or C_Parity (Parity)
or CLOCAL
or CREAD
or C_Flow_Control (Flow);
what do you think? I have tried to maintain compatibility.
I tend to not use the GNAT.* specific packages and my comment was based on
the OP's statement that the GNAT serial port package does not present a
method for changing the flow control settings.
Given that, I would have been very surprised if the package imposed it's
own flow control settings without the programmer been able to override
them when there are several equally viable options to choose from.
However, as you mention, that is clearly what is happening, and IMHO, is
unjustified arrogance on the part of the package designer that they know
better than the programmer.
As well as RTS/CTS flow control based devices, I routinely come across
devices without flow control (such as some GPS modules or the DBGU port
on some Atmel microcontrollers) and devices with Xon/Xoff flow control
(such as DEC based hardware).
In my opinion, if you have several options to choose from, you either
expose the options via a API so the end programmer can choose the one
best suited to their environment, or you preserve the current settings
and let the programmer alter them in some other way (say via stty in
this case).
> The "Set" procedure in Gnat.Serial_Communications uses "tcsetattr" and
> "tcgetattr" C syscalls to do the job of setting baud rate ... "man
> tcsetattr" should give you the relevant information.
>
> Unfortunately it uses the pseudo-code
> tcgetattr(current settings);
> overwrite baud rate and other things you want to set;
> overwrite control settings inc. ctsrts for good measure
> tcsetattr(current settings);
> to do the job.
>
I hope the rest of the GNAT.* packages are written to a higher standard
than that. :-)
Fair enough.
For what it's worth, it may even be more elegant to just extend
GNAT.Serial_Communications by writing a child package (e.g.:
GNAT.Serial_Communications.Flow_Control) that defines any necessary
types and overloads the Set procedure, adding a flow control parameter.
As a child package, your extension would have visibility of all the
types and subprograms in the parent, but you wouldn't have to hack up
GNAT.Serial_Communications or recompile it, in case you have some other
code that uses it as-written, or if you ever want to use the unmodified
version in the future.
> tonyg wrote:
>> Yes that would work. I think I am going to mod the gnat-sercom package
>> though for elegance's sake. Many thanks for taking the time, looking at
>> it has improved my knowledge of Ada.
>
> For what it's worth, it may even be more elegant to just extend
> GNAT.Serial_Communications by writing a child package (e.g.:
> GNAT.Serial_Communications.Flow_Control) that defines any necessary
> types and overloads the Set procedure, adding a flow control parameter.
Thanks for pointing that out.
I expect I should have thought of that, but I didn't...
-Brian
> Brian Drummond <br...@shapes.demon.co.uk> writes:
>
>> (1) modify g-sercom-linux.adb to do the job, or at least, what it's
>> supposed to (not corrupt settings unnecessarily). Then ... what has to
>> happen to regenerate the GNAT.Serial_Communications package?
> Put the modified g-sercom-linux.adb in the compiler's search path, then
> use the "-a" flag to gnatmake.
presumably the right thing to do for this application...
> (b) don't say "gnatmake -f" for a full rebuild or you'll end up
> rebuilding the RTS!
Would that be the right thing to do to avoid the problem in all future
applications?
- Brian
The recompiled binaries are in this application's program library, so -
not.
I think you could get away with putting the .ads/.adb in the adainclude/
directory and the .ali/.o in the adalib/ directory (write-protect the
.ali). Worth a try, and easier than rebuilding the entire library.