zabsalahid / serialport-gsm

SerialPort-GSM is a simplified plugin for communicating with gsm modems. (Primarily for sms) (Focused in PDU mode)
MIT License
91 stars 48 forks source link

Discussion: URC Sequencing and 'Guard time" #35

Closed psmass closed 5 years ago

psmass commented 5 years ago

Hi all,

@zabsalahid @karianpour @Apollon77 What do you guys understand about this issue (see below)? I don't see that serialport-gsm code handles this possibility?

This issue pertains to guarantees that a URC from the modem will not occur while the modem (and any host state machine) is in the middle of processing a current command.

// Good behavior: ATZ OK +CMTI... <--- URC comes within 100ms after a command from the host completes

// Bad behavior ATZ +CMTI... <---URC comes asynchronously in the middle of a command OK

Here is a discussion that highlights the issue and how it's handled: https://embeddedfreak.wordpress.com/2008/08/19/handling-urc-unsolicited-result-code-in-hayes-at-command/

It mentions that a modem can 'crash' if an AT command is sent to the modem at the same time the modem sends a URC. To prevent commands from the host to the modem colliding with a URC, the host should ALWAYS wait 100ms after an OK from a previous command to give the modem time to send any cached URCs.

Thank you Paul

psmass commented 5 years ago

Well perhaps this is not something at the serialport-gsm library level you need to direcly worry about since you usually send one command corresponding to a users call. Therefore it is incumbant upon the use to ensure a 100ms delay between issuing commands to the serialport-gsm driver layer. [I do see though, that in delete messages, in a loop you send multiple back-to-back 'AT+CMGD=n' commands, similar with AT+CMGS=parts for concatenated messages - so these two commands might be in conflict with at least my understanding of how the URC Guard time works]

I know what I believe I need to do to fix this on my end, but if you have any further insights in to this, I would appreciate your input.

I believe, this is something the users of the library should to be aware of, even if it is not directly a serialport-gsm issue.
Thx Paul

Apollon77 commented 5 years ago

I also would see that strange if it really mixes in one line. As soon as the URC is coming as an own line the library will handle it correctly I assume. And the modem side itself need to make sure that „lines“ (characters ended by /r/n or such) itself are send „atomic“

Apollon77 commented 5 years ago

And BTW the article linked (sorry to say that but my opinion) just shows some protocol assumptions that are proofed wrong by „reality“ ;-) Yes using Echo, as we do here too, helps to detect when the processing if one command starts. After this it is parsing line by line including handling URC messages and decide which data are interesting and which not. I like the parsing approach we use here. ;-)

Apollon77 commented 5 years ago

Pps: s modem crashing when sending and receiving happens in parallel is a modem bug ;-) Serial communication is based on separat RX and TX lines that are connected cross-wise. So sending and receiving are different things and the applications on both sides are responsible to handle their incoming data ...

psmass commented 5 years ago

Thanks for your response. I like the parsing and approach to the library as well, and agree a modem crashing is abug. However, I would like to understand this potential race condition and wanted to get your experience /views on it. Below is what I see as an unavoidable and subtle race condition with any modem chip and an issue that needs to be considered at least at the application layer.

Let's take the following scenario: The host is in the final instruction to send an AT-Command (say an AT+CMGS - the modem can't know this command is coming apriori), when just prior or roughly the same time, the modem received a message and is about to send a +CMTI. So in this scenario, the modem would get the AT-command after it sent +CMTI to the host, and the host would see the +CMTI command and not the echo of the AT-Command it had sent. The modem should now respond to the AT-command given by the host a per normal [ albeit the AT-Command is usually in response to the +CMTI -but the fact that it is not in response to the +CMTI should not cause an issue with the modem]. At this point the host, seeing the echo of its earlier sent AT+CMTS, has to cache the +CMTI to respond to it after the AT-command that is now being echoed is processed. After the AT-command processing is complete and the host receives an OK or ERROR, the host then needs to recall the +CMTI (it's not going to get sent again) and then process it, or the URC will be lost.

I understand where a 'guard time' attempts to address this. If a first AT-Command is being processed when the modem receives a message, the modem caches the +CMTI until after the current command has completed (or in potential implementation, the modem, simply ignores the new received message until after the current command has completed, allowing the receive state to drive the +CMTI after the modem returns to IDLE). By the host waiting 100ms after OK before sending a new 2nd AT-command unambiguous time is given to the modem to send the +CMTI, allowing the host to clearly and cleanly receive the +CMTI, before sending the 2nd command. It would be up to the host, but logically, the host could then process the +CMTI first followed by any other commands it needed to send based on it's internal state. However, even with the 'guard time protocol, at idle state, i.e., the host has nothing going on, when the modem receives a message and issues a +CMTI in response. At the same time state on the host, application triggers a new sequence of AT-commands. At this point, with or without a guard time, the above scenario can once again occur.

Apollon77 commented 5 years ago

I personally have no experience in embedded development, so I can not say that hhat youz are saying is true of wrong. And in the modern architectureds also "Multi processing" and event driven processing should be possible and in fact the AT parsing on both sides is not that difficult. You assume a very "fix" understanding of the processing logic (after I send an AT command the next lines are my answer) which may not be that true ... in fact all AT commands I know are repeated directly in the response. So you send AT+XYZ=? and the reuslting lines normally all take +XYZ at the beginning ... so it could also be parsed like that. Ok there are some special cases, but on modem side this is very well defined from "protocol level" I think.

What we also see is that the modem is processing the commands strict sequencially ... so it simply queues all new incling events.

For the modem the events are "fire and forget" because he only wants to send them out. So it directly puts it into the send queue and then it gets delivered. The applications need to understand and work with this. All "events" are one liners ... so easiely detectable as "Not belonging to the answer of current command"

psmass commented 5 years ago

In making the description above, I have a clearer understanding of what should and should not occur between the modem and host. So let me update the original command sequence, shown at the top of this thread with more detail. (I agree that if the modem is implemented correctly a +CMTI should not occur between the echo of a command by the modem and it’s final processing state (OK or ERROR) from the modem [in the example below, +CMTI should not occur between times T5 and T7, however a +CMTI can occur after the AT+CMTS is sent by the host in T2 but before the echo in T5.

Time                 Host                           Modem                  External source
====   ==============================   ===============================   =================
T0               Idle                               Idle                   <— sends SMS   
T1        Internal state change                 Receives SMS              (async to both Host and Modem)
T2           Sends AT+CMTS (not echo)      Sends +CMTI for rcvd SMS
T3          Receives +CMTI               Rcvs AT+CMTS starts processing 
T4     (waiting for echo of AT+CMTS)          Echoes AT+CMTS                                                       
T5        Receives AT+CMTS echo          Sends response to AT+CMTS
T6       Receives AT+CMTS response       Sends OK
T7       Receives OK
T8   Sends AT+CMTR in response to +CMTI

Comments?

Apollon77 commented 5 years ago

I still do not agree with "it should not occure ion between a response".

I more see it as "in the modem several threads are running inside". One thread is processing the AT commands and 1-n other threads are getting events from the other components. The "event threads" get signals from the HW and are sending out event infos. The AT-command processor (which is also communicating e.g. withg the SIM card which is not a very fast communication will simply send out data once they are available ... so also line by line ... but this means that there are times between e.g. delivering all messages because SIM card needs to work. ANd because data queuing is expensive also here data are send out line by line once they are available.

Sending out for all means: I put a target line into the "transmission queue" and the serial HW will send all lines out in the other they were put in (FIFO) ... all other mechanism would block event threads to wait for the current AT command to be finished. This is too complex and expensive.

Event queue is more important then AT cvommands bevause you want your phone to "ring" when a call is incoming, unimportant if some other task (read out all SIM messages) is working longer in the background because of bad "contact areas on your sim card" ;-)

Do you see what I mean? And with this assumption the event queue has higher prio then commands and so the events are coming whenever possible.

psmass commented 5 years ago

Thank you for your time and insight. Based on my "googling" while I think most modem vendors do pause sending URCs until after processing of commands in process (i.e. would not interleave a URC between a command echo and it's completion(OK)), I can't find any specification or guarantees of this. In my experience, when ever possible, it's always better to receive flexibly and to transmit strictly when adhering to such standards.

I'm going to close this issue as I am now convinced the code as written in this libary is agnostic to URCs coming in between a host command echo and the completion of the command by the modem.

Key to this library, is that sending of AT commands are tracked in sequence in a command.queue FIFO, and proecessing of commands and URCs are handled separately in the dataRecieved(). So, anytime a +CMTI (and a couple other URCs) come in, corresponding specific AT commands are immediately issued. Just as any another command being executed by the host these commands are pushed in to the command.queue FIFO. They are then read in FIFO order, so this code expects the actual command process by the modem to be in sequence issued by the host.