<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/simtrace2/+/23643">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">card_emu: Fix USART timer, particularly in re-start situations<br><br>The existing code started the timer once (and expired once) but didn't<br>properly handle re-starting of the timer.  Neither did it handle<br>the 'half time expiration' case.  If we want to call a function after<br>half the WT expiring, we must of course program the hardware for half<br>the timeout, and not the full timeout...<br><br>Change-Id: Ia999d97f835c27597fcd1cf7ac78bac0ab9c98c1<br>---<br>M firmware/libcommon/source/mode_cardemu.c<br>1 file changed, 40 insertions(+), 12 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/simtrace2 refs/changes/43/23643/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/firmware/libcommon/source/mode_cardemu.c b/firmware/libcommon/source/mode_cardemu.c</span><br><span>index 8531eb5..14f62a6 100644</span><br><span>--- a/firmware/libcommon/source/mode_cardemu.c</span><br><span>+++ b/firmware/libcommon/source/mode_cardemu.c</span><br><span>@@ -212,6 +212,23 @@</span><br><span>  return 1;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static uint16_t compute_next_timeout(struct cardem_inst *ci)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   uint32_t want_to_expire;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    if (ci->wt.total == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!ci->wt.half_time_notified) {</span><br><span style="color: hsl(120, 100%, 40%);">+          /* we need to make sure to expire after half the total waiting time */</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_ASSERT(ci->wt.remaining > (ci->wt.total / 2));</span><br><span style="color: hsl(120, 100%, 40%);">+          want_to_expire = ci->wt.remaining - (ci->wt.total / 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else</span><br><span style="color: hsl(120, 100%, 40%);">+                want_to_expire = ci->wt.remaining;</span><br><span style="color: hsl(120, 100%, 40%);">+ TRACE_INFO("want_to_expire=%u (total=%u, remaining=%u)\r\n", want_to_expire, ci->wt.total, ci->wt.remaining);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* if value exceeds the USART TO range, use the maximum possible value for one round */</span><br><span style="color: hsl(120, 100%, 40%);">+       return OSMO_MIN(want_to_expire, 0xffff);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span> </span><br><span> /*! common handler if interrupt was received.</span><br><span>  *  \param[in] inst_num Instance number, range 0..1 (some boards only '0' permitted) */</span><br><span>@@ -254,6 +271,9 @@</span><br><span>     * how many etu have expired since we last sent a byte.  See section</span><br><span>          * 33.7.3.11 "Receiver Time-out" of the SAM3S8 Data Sheet */</span><br><span>       if (csr & US_CSR_TIMEOUT) {</span><br><span style="color: hsl(120, 100%, 40%);">+               /* clear timeout flag (and stop timeout until next character is received) */</span><br><span style="color: hsl(120, 100%, 40%);">+          usart->US_CR |= US_CR_STTTO;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>            /* RX has been inactive for some time */</span><br><span>             if (ci->wt.remaining <= (usart->US_RTOR & 0xffff)) {</span><br><span>                    /* waiting time is over; will stop the timer */</span><br><span>@@ -266,17 +286,26 @@</span><br><span>              if (ci->wt.remaining == 0) {</span><br><span>                      /* let the FSM know that WT has expired */</span><br><span>                   card_emu_wtime_expired(ci->ch);</span><br><span style="color: hsl(0, 100%, 40%);">-              } else if (ci->wt.remaining <= ci->wt.total / 2 && !ci->wt.half_time_notified) {</span><br><span style="color: hsl(0, 100%, 40%);">-                    /* let the FS know that half of the WT has expired */</span><br><span style="color: hsl(0, 100%, 40%);">-                   card_emu_wtime_half_expired(ci->ch);</span><br><span style="color: hsl(0, 100%, 40%);">-                 ci->wt.half_time_notified = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                  /* don't automatically re-start in this case */</span><br><span style="color: hsl(120, 100%, 40%);">+           } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      bool half_time_just_reached = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                        if (ci->wt.remaining <= ci->wt.total / 2 && !ci->wt.half_time_notified) {</span><br><span style="color: hsl(120, 100%, 40%);">+                         ci->wt.half_time_notified = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                          /* don't immediately call card_emu_wtime_half_expired(), as that</span><br><span style="color: hsl(120, 100%, 40%);">+                           * in turn may calls card_emu_uart_update_wt() which will change</span><br><span style="color: hsl(120, 100%, 40%);">+                               * the timeout but would be overridden 4 lines below */</span><br><span style="color: hsl(120, 100%, 40%);">+                               half_time_just_reached = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   /* update the counter no matter if we reached half time or not */</span><br><span style="color: hsl(120, 100%, 40%);">+                     usart->US_RTOR = compute_next_timeout(ci);</span><br><span style="color: hsl(120, 100%, 40%);">+                 /* restart the counter (if wt is 0, the timeout is not started) */</span><br><span style="color: hsl(120, 100%, 40%);">+                    usart->US_CR |= US_CR_RETTO;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (half_time_just_reached)</span><br><span style="color: hsl(120, 100%, 40%);">+                           card_emu_wtime_half_expired(ci->ch);</span><br><span>              }</span><br><span style="color: hsl(0, 100%, 40%);">-               /* if value exceeds the USART TO range, use the maximum for now */</span><br><span style="color: hsl(0, 100%, 40%);">-              usart->US_RTOR = OSMO_MIN(ci->wt.remaining, 0xffff);</span><br><span style="color: hsl(0, 100%, 40%);">-              /* clear timeout flag (and stop timeout until next character is received) */</span><br><span style="color: hsl(0, 100%, 40%);">-            usart->US_CR |= US_CR_STTTO;</span><br><span style="color: hsl(0, 100%, 40%);">-         /* restart the counter (it wt is 0, the timeout is not started) */</span><br><span style="color: hsl(0, 100%, 40%);">-              usart->US_CR |= US_CR_RETTO;</span><br><span>      }</span><br><span> }</span><br><span> </span><br><span>@@ -336,8 +365,7 @@</span><br><span>     /* FIXME: guard against race with interrupt handler */</span><br><span>       ci->wt.remaining = ci->wt.total;</span><br><span>       ci->wt.half_time_notified = false;</span><br><span style="color: hsl(0, 100%, 40%);">-   /* if value exceeds the USART TO range, use the maximum for now */</span><br><span style="color: hsl(0, 100%, 40%);">-      usart->US_RTOR = OSMO_MIN(ci->wt.remaining, 0xffff);</span><br><span style="color: hsl(120, 100%, 40%);">+    usart->US_RTOR = compute_next_timeout(ci);</span><br><span>        /* restart the counter (if wt is 0, the timeout is not started) */</span><br><span>   usart->US_CR |= US_CR_RETTO;</span><br><span> }</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/simtrace2/+/23643">change 23643</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/simtrace2/+/23643"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: simtrace2 </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: Ia999d97f835c27597fcd1cf7ac78bac0ab9c98c1 </div>
<div style="display:none"> Gerrit-Change-Number: 23643 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-CC: Jenkins Builder </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>