Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Threaded RS232 communication

by tobias_hofer (Friar)
on Jan 30, 2013 at 09:30 UTC ( #1016009=perlquestion: print w/ replies, xml ) Need Help??
tobias_hofer has asked for the wisdom of the Perl Monks concerning the following question:

Hello,

I am developing a perl module which shall communicate by rs232 with a micro controller. The communication is done by threads and thread::queues.
Messages I want to send are put into a queue. A thread is taking messages from the queue and sends them onto the RS232 by a handle to the RS232 Win32::SerialPort object.
The same approach I do for receving rs232 stuff.
Once the receive thread got something on the rs232, the thread puts it into the receive queue. In the main thread I will handle all the received messages and send new messages.

My problem occurs on shutdown. I am not able to end the read thread as it is blocked by a call to

my ($receivedBytes, $data) = $HandleToRS232->read();
So I changed to "background read"
my ($receivedBytes, $data) = $HandleToRS232->read_bg();
Doing this I got nothing in $data so I did a call to
my($done, $count_in, $string_in) = $HandleToRS232->read_done(1);
Then I receive the message in the $string_in variable, but the call to read_done is also blocking.

I have read the doc. in the Win32::SerialPort and have come to give a try with the API from Win32API::CommPort.
There is a API for receiving with timeout (I need this timeout so I can end the thread). This API is based on the ReadFile API.

However, I do not get this API working properly. I did the following:

my ($result) = Win32API::CommPort::ReadFile( $HandleToRS232,$data,$NumberOfBytesToRead, $ActualReadBytes,$template);

But the code is breaking and I do not receive an error message.. so I do not know why..
I am quite sure I missuse somehow this ReadFile API..

Any help is very welcome!

Best regards!

Comment on Threaded RS232 communication
Select or Download Code
Re: Threaded RS232 communication
by BrowserUk (Pope) on Jan 30, 2013 at 10:48 UTC

    First off, you are probably limiting your audience unnecessarily by mentioning "threads" in the title.

    Your basic problem, that of needing a non-blocking read, has nothing to do with threading.

    Secondly, do you really need to terminate your read thread? That is, if you detached it, it would just silently melt into the ether when your main thread decides to exit the process.

    But if you do really need to, I think that you've already discovered the 'right' solution, namely read_bg(). All you nee to do is use the API correctly and alter your coding strategy a little. (NOTE: None of the following is tested.)

    So I changed to "background read" my ($receivedBytes, $data) = $HandleToRS232->read_bg(); Doing this I got nothing in $data so I did a call to my($done, $count_in, $string_in) = $HandleToRS232->read_done(1); Then I receive the message in the $string_in variable, but the call to read_done is also blocking.

    Based on my reading the source -- and I may well have misread it --

    • read_bg() uses overlapped IO to operate, therefore it is expected that it will (often) not return (somplete) data immediately

      It basically says, this is what I want to read, initiate that for me and return immediately (with any data that happens to have already arrived.)

      I'll call read_done() when I'm ready for (the rest of) it.

    • read_done() is only blocking if you pass a true argument (As you are:read_done(1);).

      To prevent it from blocking, pass 0;

      That will require you to recode your read thread so that instead of blocking in a read, you poll (with a delay!).

      Then within that polling loop you can check to see if you should exit the thread.


    With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
    Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
    "Science is about questioning the status quo. Questioning authority".
    In the absence of evidence, opinion is indistinguishable from prejudice.

      I went back to $HandleRS232->read();
      Because it is simpler for me and simply meets the requirements.
      I have also detached the threads so they can go into the ether. :-D
      It working perfect! Super!

      Thanks a lot!

Re: Threaded RS232 communication
by sundialsvc4 (Monsignor) on Jan 31, 2013 at 22:56 UTC

    Hmm... maybe this is a dumb-question, or an unnecessary one, but I do want to cover it just-in-case.   If the port-reader thread that is feeding data into Thread::Queue is terminated in this way, can we in fact be certain that the reader of that queue will in fact receive all of the data that has been sent?   Do we indeed have the means to be certain that every single byte that the client may have transmitted to the port will in fact be accounted-for, even if the final transmission is incomplete?   (I am thinking, not only of the bytes that have been posted into the queue, but also of any bytes that may have been queued-up in the read operation that we are about to shoot in the foot.)

    “Just askin’ ...” ... but not entirely with an absence of motive or precedent.   Sometime in my distant past, a project that i was involved in was very seriously bitten by a manifestation of exactly this kind of issue.   Can we ... and I do not know this ... be c-e-r-t-a-i-n that this edge-case is covered?)

      This question is very important. In my case its a integration test system communicating with the target by rs232. What i am sending and receiving are requests for starting test-cases and getting the test-results.To avoid the loss of information i have designed a communication protocol. Thus the communication is going on like a ping-pong game.
      Request -RS232-> Target
      Target -RS232-> Answer+Acknowledge to requester

      Only when the communication sequence is done (test-sequence ended completley - recognised by the state machine) I close the rs232 connection. Thus I can be sure that no information is lost.

      Ok, regarding this test-system its a special case but IMHO having a protocol and a communication desgin is helping a lot to avoid loss of data


      Best regards!
      Tobias

        It is easy to reason (and demonstrate) that anything that has been pushed into the Queue prior to the thread being terminated, will still be in the queue and available to any other thread after the thread that queued it terminated. This obvious as were it not the case, Thread::Queue would necessarily be the source of many 'mysterious failures' in threaded code all over.

        As the detached read thread will not be terminated until the main thread decides that the program is complete; and it presumably decides based upon the data it has read from the queue; it stands to reason that not only will all of the data required to make teh decision to terminate have be pushed into the queue before the process terminates, it will also have been read from it. Else, how would the main thread make its decision.

        Thus, it all comes down to the efficacy of the comms protocol employed and the decision making processes based upon that protocol. The presence of threading and queuing in the communications path employed can have no influence upon either.


        With the rise and rise of 'Social' network sites: 'Computers are making people easier to use everyday'
        Examine what is said, not who speaks -- Silence betokens consent -- Love the truth but pardon error.
        "Science is about questioning the status quo. Questioning authority".
        In the absence of evidence, opinion is indistinguishable from prejudice.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://1016009]
Approved by vinoth.ree
Front-paged by Lotus1
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (11)
As of 2014-07-30 11:31 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    My favorite superfluous repetitious redundant duplicative phrase is:









    Results (230 votes), past polls