From: Rolf on
Stephen Leake wrote:
> "Rolf" <rolf.ebert_nospam_(a)gmx.net> writes:
>
> > tmoran(a)acm.org wrote:
> >> But it seems to me that if the object is to use TCP to emulate hardware,
> >> one should design for that hardware and do whatever is needed with UDP or
> >> TCP to make the best emulation. Is the intended hardware going to be
> >> polled or generate interrupts or Windows messages or what?
> >
> > The real sensor hardware will be directly connected to the I/O pins of
> > the mcu. I think that counts as polling. The application code simply
> > reads variables from the h/w abstraction layer.
>
> How do those "variables" get set?
>
> Does one of the IO pins generate an interrupt, that triggers the h/w
> abstraction layer "read all pins" function?
>
> Or is the h/w abstraction layer a cyclic executor, driven by a clock?
>
> How does the application know when to read the variables? By a clock,
> or some interrupt/event from the h/w abstraction layer?

The main program essentially looks like this:

loop
Read_Sens;

Behave;

delay until Next;
Next := Next + Period; -- Period == 0.1 sec typ.
end loop;

The call to Read_Sens is commented out in the simulation case and
replaced by the second thread as outlined in the original posting. The
sensor data are global variables in a package spec. The Behave reads
them whenever it thinks it needs their values.

The world simulation program at the other end of the TCP socket does
not know about the internal timing of the application (perhaps I should
add a synchronization protocol, now that I think of it)

From: Dmitry A. Kazakov on
On Tue, 31 Jan 2006 21:55:57 +0000, Simon Wright wrote:

> "Dmitry A. Kazakov" <mailbox(a)dmitry-kazakov.de> writes:
>
>> On 30 Jan 2006 14:12:51 -0800, Rolf wrote:
>
>>> - I don't know much about sockets (or better I don't remember much).
>>> Does a waiting read (in the second task) block a write in the first
>>> task?
>>
>> Usually not. Note that you must wait not for a socket read, but for a
>> "variable-update" event from the middleware layer.
>
> _Something_ has to wait for a socket read! If you're writing your own
> 'middleware' (lower layers, anyway) that will be you.

It depends. The point is, that it should not the application task.
Especially because socket I/O events are not directly mapped into
application events, due to buffering. So if the application needs fresh
data it can wait for a protected object, which state is changed by the
reader task (the reader waits, of course.) However more often, when dealing
with sensors and actors (which are continuous-state things), the
application does not wait at all, but just takes the last available value.
[ Quality of service checks, and generating consequent alarms is a
middleware's responsibility. ]

>>> - what other hints can you give me?
>>
>> Never ever use UPD, avoid TCP_NO_DELAY with TCP/IP. The first is
>> unreliable for your purpose, the second quickly brings the network
>> down.
>
> Probably best to avoid these (I guess that UPD was a typo for UDP) at
> the start, but sometimes they are the appropriate solution. Not often,
> maybe.

Yes.

Maybe off-topic, but. Multicasting finally came. Now there are viable
alternatives to UDP. For example, PGM is a reliable multicasting protocol.

--
Regards,
Dmitry A. Kazakov
http://www.dmitry-kazakov.de
From: Stephen Leake on
"Rolf" <rolf.ebert_nospam_(a)gmx.net> writes:

> Stephen Leake wrote:
>> "Rolf" <rolf.ebert_nospam_(a)gmx.net> writes:
>>
>> > tmoran(a)acm.org wrote:
>> >> But it seems to me that if the object is to use TCP to emulate hardware,
>> >> one should design for that hardware and do whatever is needed with UDP or
>> >> TCP to make the best emulation. Is the intended hardware going to be
>> >> polled or generate interrupts or Windows messages or what?
>> >
>> > The real sensor hardware will be directly connected to the I/O pins of
>> > the mcu. I think that counts as polling. The application code simply
>> > reads variables from the h/w abstraction layer.
>>
>> How do those "variables" get set?
>>
>> Does one of the IO pins generate an interrupt, that triggers the h/w
>> abstraction layer "read all pins" function?
>>
>> Or is the h/w abstraction layer a cyclic executor, driven by a clock?
>>
>> How does the application know when to read the variables? By a clock,
>> or some interrupt/event from the h/w abstraction layer?
>
> The main program essentially looks like this:
>
> loop
> Read_Sens;
>
> Behave;
>
> delay until Next;
> Next := Next + Period; -- Period == 0.1 sec typ.
> end loop;

Ok. So Read_Sens runs the h/w abstraction layer, Behave is the
application layer.

> The call to Read_Sens is commented out in the simulation case and
> replaced by the second thread as outlined in the original posting.

Better to not edit the code, but define an alternate body for
Read_Sens. Not a big deal.

> The sensor data are global variables in a package spec. The Behave
> reads them whenever it thinks it needs their values.

Ok.

> The world simulation program at the other end of the TCP socket does
> not know about the internal timing of the application (perhaps I should
> add a synchronization protocol, now that I think of it)

I'm still not clear where the sockets are. I think Read_Sens reads
from a socket to get the simulated sensor values. Does it try to read
data for all variables from the socket _every_ time it is called? Or
does it check to see if some new data is available?

Behave writes to a socket for user display?

Then the question is what drives the simulation; does it wait for
Read_Sens to read data, or just run at some rate? Does the simulation
react to anything Behave does?

Yes, you need synchronization between the simulation and Read_Sens,
and possibly Behave. That is probably the root cause of your problem.

--
-- Stephe
From: Simon Wright on
Stephen Leake <stephen_leake(a)acm.org> writes:

> Hmm. I don't know how this maps to Read_Socket commands. I would guess
> that it waits for the number of Stream_Elements in Sensor_Cmd_T to be
> available. But it might wait longer than that, especially if
> Sensor_Cmd_T is unconstrained.

If the type is unconstrained, 'Input will read dope info (whose length
it does know) and then read the number of bytes specified by the dope
info. It uses recv() for TCP, recvfrom() for UDP (well, this is 4.0.0
on Darwin, but as I recall this part is pretty standard).

> You could do a Read_Socket into a Stream_Array, and then do 'Input
> from that. That would make it clearer when the task is suspended.

That doesn't work (for TCP) unless you know how large the object is on
the wire!

On the other hand for UDP messages, you *must* read the whole packet
into a stream array (at least as large as the largest supported
packet) and do 'Input from that, because you really really want to
make only one call to the OS socket interface. Similarly for 'Output.
From: Rolf on
Stephen Leake wrote:
> "Rolf" <rolf.ebert_nospam_(a)gmx.net> writes:
>
> > The main program essentially looks like this:
> >
> > loop
> > Read_Sens;
> >
> > Behave;
> >
> > delay until Next;
> > Next := Next + Period; -- Period == 0.1 sec typ.
> > end loop;
>
> Ok. So Read_Sens runs the h/w abstraction layer, Behave is the
> application layer.

More or less. Behave also calls a write routine in the abstraction
layer.

> > The world simulation program at the other end of the TCP socket does
> > not know about the internal timing of the application (perhaps I should
> > add a synchronization protocol, now that I think of it)
>
> I'm still not clear where the sockets are. I think Read_Sens reads
> from a socket to get the simulated sensor values. Does it try to read
> data for all variables from the socket _every_ time it is called? Or
> does it check to see if some new data is available?

Read_Sens reads the hardware sensors in the non-simulated case and
writes them to global variables. It reads them from a protected object
when communicating via TCP. The second task (besides the main program)
continuously reads from the socket and writes to the protected object.
That second task and the protected object do not exist in the
non-simulated case.

> Behave writes to a socket for user display?

and it changes the world in the world simulation. The world simulation
also has a GUI.

> Then the question is what drives the simulation; does it wait for
> Read_Sens to read data, or just run at some rate? Does the simulation
> react to anything Behave does?
>
> Yes, you need synchronization between the simulation and Read_Sens,
> and possibly Behave. That is probably the root cause of your problem.

that is certainly true and I have to think about it again.

No, the root cause of my problem was a buggy socket implementation in
gcc-3.4.4 (at least I think so). I recompiled my program with GNAT GPL
2005 and it worked without any other modification