support library for C027 helper functions for Buffer Pipes, Buffered Serial Port (rtos capable) and GPS parsing. It includes modem APIs for USSD, SMS and Sockets.

Fork of C027_Support by u-blox

Files at this revision

API Documentation at this revision

Comitter:
mazgch
Date:
Fri May 16 14:13:00 2014 +0000
Parent:
74:208e3e32d263
Child:
76:f7c3dd568dae
Commit message:
minor tweaks

Changed in this revision

GPS.cpp Show annotated file Show diff for this revision Revisions of this file
GPS.h Show annotated file Show diff for this revision Revisions of this file
MDM.cpp Show annotated file Show diff for this revision Revisions of this file
MDM.h Show annotated file Show diff for this revision Revisions of this file
Pipe.h Show annotated file Show diff for this revision Revisions of this file
SerialPipe.cpp Show annotated file Show diff for this revision Revisions of this file
--- a/GPS.cpp	Thu May 15 22:20:42 2014 +0000
+++ b/GPS.cpp	Fri May 16 14:13:00 2014 +0000
@@ -258,7 +258,7 @@
 #endif
 }
 
-bool GPSSerial::init(void)
+bool GPSSerial::init(PinName pn)
 {
     // send a byte to wakup the device again
     putc(0);
@@ -301,12 +301,14 @@
 #endif
 }
 
-bool GPSI2C::init(void)
+bool GPSI2C::init(PinName pn)
 {
-    DigitalOut pin(GPSINT, 0);
-    wait_us(1);
-    pin = 1;
-    RELAX_MS(100);
+    if (pn != NC) {
+        DigitalOut pin(pn, 0);
+        wait_us(1);
+        pin = 1;
+        RELAX_MS(100);
+    }
     return !I2C::write(_i2cAdr,&REGSTREAM,sizeof(REGSTREAM));
 }
 
--- a/GPS.h	Thu May 15 22:20:42 2014 +0000
+++ b/GPS.h	Fri May 16 14:13:00 2014 +0000
@@ -5,9 +5,9 @@
 #include "SerialPipe.h"
 
 #ifdef TARGET_UBLOX_C027
- #define _IF(onboard, shield) onboard
+ #define GPS_IF(onboard, shield) onboard
 #else
- #define _IF(onboard, shield) shield
+ #define GPS_IF(onboard, shield) shield
 #endif
 
 /** basic gps parser class 
@@ -21,7 +21,7 @@
    
     /** Power on / Wake up the gps 
     */
-    virtual bool init(void) = 0;
+    virtual bool init(PinName pn) = 0;
     
     enum { 
         // getLine Responses
@@ -178,13 +178,13 @@
         \param rxSize the size of the serial rx buffer
         \param txSize the size of the serial tx buffer
     */
-    GPSSerial(PinName tx    _IF( = GPSTXD, /* = D8 */), // resistor on shield not populated 
-              PinName rx    _IF( = GPSRXD, /* = D9 */), // resistor on shield not populated 
-              int baudrate  _IF( = GPSBAUD, = 9600 ),
+    GPSSerial(PinName tx    GPS_IF( = GPSTXD, /* = D8 */), // resistor on shield not populated 
+              PinName rx    GPS_IF( = GPSRXD, /* = D9 */), // resistor on shield not populated 
+              int baudrate  GPS_IF( = GPSBAUD, = 9600 ),
               int rxSize    = 256 , 
               int txSize    = 128 );
               
-    virtual bool init(void);
+    virtual bool init(PinName pn = NC);
     
     /** Get a line from the physical interface. 
         \param buf the buffer to store it
@@ -215,15 +215,15 @@
         \param adr the I2C address of the GPS set to (66<<1)
         \param rxSize the size of the serial rx buffer
     */
-    GPSI2C(PinName sda          _IF( = GPSSDA, = D14 ), 
-           PinName scl          _IF( = GPSSCL, = D15 ),
-           unsigned char i2cAdr _IF( = GPSADR, = (66<<1) ), 
+    GPSI2C(PinName sda          GPS_IF( = GPSSDA, = D14 ), 
+           PinName scl          GPS_IF( = GPSSCL, = D15 ),
+           unsigned char i2cAdr GPS_IF( = GPSADR, = (66<<1) ), 
            int rxSize           = 256 );
     
     /** helper function to probe the i2c device
         \return true if successfully detected the gps. 
     */ 
-    virtual bool init(void);
+    virtual bool init(PinName pn = GPS_IF( GPSINT, NC /* D7 resistor R67 on shield not mounted */));
     
     /** Get a line from the physical interface. 
         \param buf the buffer to store it
--- a/MDM.cpp	Thu May 15 22:20:42 2014 +0000
+++ b/MDM.cpp	Fri May 16 14:13:00 2014 +0000
@@ -11,27 +11,40 @@
 #define MAX_SIZE        128   //!< max expected messages
 //! test if it is a socket
 #define ISSOCKET(s)     (((s) >= 0) && ((s) < (sizeof(_sockets)/sizeof(*_sockets))))
-
+//! check for timeout
+#define TIMEOUT(t, ms)  ((ms != TIMEOUT_BLOCKING) && (ms < t.read_ms())) 
 
 #ifdef MDM_DEBUG
 void dumpAtCmd(const char* buf, int len)
 {
-    printf(" %3d \"", len);
+    ::printf(" %3d \"", len);
     while (len --) {
         char ch = *buf++;
-        if      (ch == '\r') puts("\\r");
-        else if (ch == '\n') puts("\\n");
-        else if (ch >= 0x20) putchar(ch);
-        else                 printf("\\x%02x", ch);
+        if ((ch > 0x1F) && (ch != 0x7F)) { // is printable
+            if      (ch == '%')  ::printf("%%");
+            else if (ch == '"')  ::printf("\\\"");
+            else if (ch == '\\') ::printf("\\\\");
+            else putchar(ch);
+        } else {
+            if      (ch == '\a') ::printf("\\a"); // BEL (0x07)
+            else if (ch == '\b') ::printf("\\b"); // Backspace (0x08)
+            else if (ch == '\t') ::printf("\\t"); // Horizontal Tab (0x09)
+            else if (ch == '\n') ::printf("\\n"); // Linefeed (0x0A)
+            else if (ch == '\v') ::printf("\\v"); // Vertical Tab (0x0B)
+            else if (ch == '\f') ::printf("\\f"); // Formfeed (0x0C)
+            else if (ch == '\r') ::printf("\\r"); // Carriage Return (0x0D)
+            else                 ::printf("\\x%02x", ch);
+        }
     }
-    puts("\"\r\n");
+    ::printf("\"\r\n");
 }
  
- #define INFO  (_debugLevel >= 1) ? : printf
- #define TRACE (_debugLevel >= 2) ? : printf
+ #define ERROR(fmt) (_debugLevel < 0) ? : ::printf(RED(fmt))
+ #define INFO(fmt)  (_debugLevel < 1) ? : ::printf(GRE(fmt))
+ #define TRACE(...) (_debugLevel < 2) ? : ::printf(__VA_ARGS__)
  
  #if 1 // colored terminal output using ANSI escape sequences
-  #define COL(c,t) "\33[" c t "\33[" "39m"
+  #define COL(c,t) "\033[" c t "\033[" "39m"
  #else
   #define COL(c,t) t
  #endif
@@ -46,6 +59,7 @@
  
 #else
  
+ #define ERROR(...) (void)0 // no tracing
  #define INFO(...)  (void)0 // no tracing
  #define TRACE(...) (void)0 // no tracing
 
@@ -80,7 +94,7 @@
 {
 #ifdef MDM_DEBUG
     if (_debugLevel >= 3) {
-        printf("%10.3f AT send    ", _debugTime.read_ms()*0.001);
+        ::printf("%10.3f AT send    ", _debugTime.read_ms()*0.001);
         dumpAtCmd(buf,len);
     }
 #endif
@@ -117,16 +131,13 @@
                             (type == TYPE_PLUS)   ? CYA(" + ") : 
                             (type == TYPE_PROMPT) ? BLU(" > ") : 
                                                         "..."  ;
-            printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
+            ::printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s);
             dumpAtCmd(buf, len);
         }
 #endif        
         if ((ret != WAIT) && (ret != NOT_FOUND))
         {
             int type = TYPE(ret);
-            if (type == TYPE_OK)        return RESP_OK;
-            if (type == TYPE_ERROR)     return RESP_ERROR;
-            if (type == TYPE_PROMPT)    return RESP_PROMPT;
             // handle unsolicited commands here
             if (type == TYPE_PLUS) {
                 const char* cmd = buf+3;
@@ -208,14 +219,14 @@
                 if (WAIT != ret)
                     return ret; 
             }
+            if (type == TYPE_OK)        return RESP_OK;
+            if (type == TYPE_ERROR)     return RESP_ERROR;
+            if (type == TYPE_PROMPT)    return RESP_PROMPT;
         }
         // relax a bit
         RELAX_MS(10); 
     }
-    while ((timeout_ms == TIMEOUT_BLOCKING) || 
-           (timer.read_ms() < timeout_ms));
-    timer.stop();
-    timer.reset();
+    while (!TIMEOUT(timer, timeout_ms));
     return WAIT;
 }
 
@@ -244,28 +255,17 @@
             const char* apn, const char* username, const char* password,
             PinName pn)
 {
-    DevStatus devStatus = {};
-    bool mdmOk = init(simpin, &devStatus, pn);  
+    bool ok = init(simpin, NULL, pn);  
 #ifdef MDM_DEBUG
-    if (_debugLevel >= 1) dumpDevStatus(&devStatus);
+    if (_debugLevel >= 1) dumpDevStatus(&_dev);
 #endif
-    if (!mdmOk)
+    if (!ok)
         return false;
-    // wait until we are connected
-    int i = 180;
-    NetStatus netStatus = {};
-    INFO("Modem::register\r\n");
-    while (!checkNetStatus(&netStatus))
-    {
-        if ((netStatus.reg == REG_DENIED) || (i == 0))
-            break;;
-        i --;
-        RELAX_MS(1000);
-    }
+    ok = registerNet();
 #ifdef MDM_DEBUG
-    if (_debugLevel >= 1) dumpNetStatus(&netStatus);
+    if (_debugLevel >= 1) dumpNetStatus(&_net);
 #endif
-    if ((netStatus.reg == REG_DENIED) || (i == 0))
+    if (!ok)
         return false;
     IP ip = join(apn,username,password);
 #ifdef MDM_DEBUG
@@ -292,9 +292,12 @@
             if(RESP_OK == waitFinalResp(NULL,NULL,500))
                 break;
         }
-        if (i < 0)
+        if (i < 0) {
+            ERROR("No Reply from Modem");
             return false;
+        }
     }
+    
     INFO("Modem::init\r\n");
     // echo off
     sendFormated("AT E0\r\n");
@@ -363,9 +366,12 @@
             if ((RESP_OK != ret) && (RESP_ERROR != ret))
                 return false;
             // Enter PIN if needed
-            if (_dev.sim == SIM_PIN) {
+            if (_dev.sim == SIM_MISSING) {
+                ERROR("SIM not inserted\r\n");
+                return false;
+            } else if (_dev.sim == SIM_PIN) {
                 if (!simpin) {
-                    INFO("SIM PIN not available\r\n");
+                    ERROR("SIM PIN not available\r\n");
                     return false;
                 }
                 sendFormated("AT+CPIN=%s\r\n", simpin);
@@ -398,12 +404,6 @@
         sendFormated("AT+CGSN\r\n");
         if (RESP_OK != waitFinalResp(_cbString, _dev.imei))
             return false;
-#if 0
-        // Configure New message indication
-        sendFormated("AT+CNMI=2,1,0,0,0\r\n");
-        if (RESP_OK != waitFinalResp())
-            return false;
-#endif
         // enable power saving
         if (_dev.lpm != LPM_DISABLED) {
              // enable power saving (requires flow control, cts at least)
@@ -418,7 +418,7 @@
     if (RESP_OK != waitFinalResp())
         return false;
     // setup new message indication
-    sendFormated("AT+CNMI=1,1\r\n");
+    sendFormated("AT+CNMI=2,1\r\n");
     if (RESP_OK != waitFinalResp())
         return false;
     // Request IMSI (International Mobile Subscriber Identification)
@@ -462,10 +462,14 @@
 
 int MDMParser::_cbCPIN(int type, const char* buf, int len, Sim* sim)
 {
-    if ((type == TYPE_PLUS) && sim){
-        char s[16];
-        if (sscanf(buf, "\r\n+CPIN: %[^\r]\r<n", s) >= 1) {
-            *sim = (strcmp("READY", s) == 0) ? SIM_READY : SIM_PIN;
+    if (sim) {
+        if (type == TYPE_PLUS){
+            char s[16];
+            if (sscanf(buf, "\r\n+CPIN: %[^\r]\r\n", s) >= 1)
+                *sim = (0 == strcmp("READY", s)) ? SIM_READY : SIM_PIN;
+        } else if (type == TYPE_ERROR) {
+            if (strstr(buf, "+CME ERROR: SIM not inserted"))
+                *sim = SIM_MISSING;
         }
     }
     return WAIT;
@@ -480,53 +484,69 @@
     return WAIT;
 }
 
+bool MDMParser::registerNet(NetStatus* status /*= NULL*/, int timeout_ms /*= 180000*/) 
+{
+    Timer timer;
+    timer.start();
+    INFO("Modem::register\r\n");
+    while (!checkNetStatus(status) && !TIMEOUT(timer, timeout_ms))
+        RELAX_MS(1000);
+    if (_net.reg == REG_DENIED)
+        ERROR("Network Registration Denied\r\n");
+    return (_net.reg == REG_ROAMING) || (_net.reg == REG_HOME);
+}
+
 bool MDMParser::checkNetStatus(NetStatus* status /*= NULL*/)
 {
+    memset(&_net, 0, sizeof(_net));
+    _net.lac = 0xFFFF;
+    _net.ci = 0xFFFFFFFF;
     // check registration
     sendFormated("AT+CREG?\r\n");
     if (RESP_OK != waitFinalResp())
         return false;
-    if ((_net.reg != REG_ROAMING) && (_net.reg != REG_HOME))
-        return false;
-    // check modem specific status messages 
-    if (_dev.dev == DEV_LISA_C200) {
-        sendFormated("AT+CSS?\r\n");
-        if (RESP_OK != waitFinalResp())
-            return false;
-        // get the Telephone number
-        sendFormated("AT$MDN?\r\n");
-        if (RESP_OK != waitFinalResp(_cbString, _net.num))
-            return false;
-        // check if we have a Mobile Directory Number
-        if (memcmp(_net.num, "0000", 4) == 0)
-            return false;
-        // get the the Network access identifier string
-        char nai[64];
-        sendFormated("AT$QCMIPNAI?\r\n");
-        if (RESP_OK != waitFinalResp(_cbString, nai))
+    if ((_net.reg == REG_ROAMING) || (_net.reg == REG_HOME))
+    {
+        // check modem specific status messages 
+        if (_dev.dev == DEV_LISA_C200) {
+            sendFormated("AT+CSS?\r\n");
+            if (RESP_OK != waitFinalResp())
+                return false;
+            // get the Telephone number
+            sendFormated("AT$MDN?\r\n");
+            if (RESP_OK != waitFinalResp(_cbString, _net.num))
+                return false;
+            // check if we have a Mobile Directory Number
+            if (!*_net.num || (memcmp(_net.num, "0000", 4) == 0))
+                return false;
+            // get the the Network access identifier string
+            char nai[64];
+            sendFormated("AT$QCMIPNAI?\r\n");
+            if (RESP_OK != waitFinalResp(_cbString, nai))
+                return false;
+        } else {
+            // check GPRS attach status
+            sendFormated("AT+CGATT?\r\n");
+            if (RESP_OK != waitFinalResp(_cbCGATT, &_net.gprs))
+                return false;
+            // check operator selection 
+            sendFormated("AT+COPS?\r\n");
+            if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
+                return false;
+            // Returns the MSISDNs related to this subscriber
+            sendFormated("AT+CNUM\r\n");
+            if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
+                return false;
+        }  
+        // Returns the signal strength indication
+        sendFormated("AT+CSQ\r\n");
+        if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
             return false;
-    } else {
-        // check GPRS attach status
-        sendFormated("AT+CGATT?\r\n");
-        if (RESP_OK != waitFinalResp(_cbCGATT, &_net.gprs))
-            return false;
-        // check operator selection 
-        sendFormated("AT+COPS?\r\n");
-        if (RESP_OK != waitFinalResp(_cbCOPS, &_net))
-            return false;
-        // Returns the MSISDNs related to this subscriber
-        sendFormated("AT+CNUM\r\n");
-        if (RESP_OK != waitFinalResp(_cbCNUM, _net.num))
-            return false;
-    }  
-    // Returns the signal strength indication
-    sendFormated("AT+CSQ\r\n");
-    if (RESP_OK != waitFinalResp(_cbCSQ, &_net))
-        return false;
+    }
     if (status) {
         memcpy(status, &_net, sizeof(NetStatus));
     }
-    return true;
+    return ((_net.reg == REG_HOME) || (_net.reg == REG_ROAMING) || (_net.reg == REG_DENIED));
 }
 
 int MDMParser::_cbCGATT(int type, const char* buf, int len, Gprs* gprs)
@@ -636,7 +656,7 @@
         // Activate the profile and make connection
         sendFormated("AT+UPSDA=" PROFILE ",3\r\n");
         if (RESP_OK != waitFinalResp(NULL,NULL,150*1000)) {
-            INFO("Your modem APN/password/username may be wrong\r\n");
+            ERROR("Your modem APN/password/username may be wrong\r\n");
             return NOIP;
         }
         //Get local IP address
@@ -900,18 +920,14 @@
             cnt += blk;
             buf += blk;
             _sockets[socket].pending -= blk;
-        } else if ((_sockets[socket].state == SOCK_CONNECTED) && (
-                   (_sockets[socket].timeout_ms == TIMEOUT_BLOCKING) || 
-                   (timer.read_ms() < _sockets[socket].timeout_ms))){
+        } else if ((_sockets[socket].state == SOCK_CONNECTED) && 
+                   !TIMEOUT(timer, _sockets[socket].timeout_ms)) {
             // allow to receive unsolicited commands 
             waitFinalResp(NULL, NULL, 10);
         } else {
             len = 0; // no more data and socket closed or timed-out
         }
     }
-    
-    timer.stop();
-    timer.reset();
     return cnt;
 }
 
@@ -957,13 +973,11 @@
             cnt += blk;
             buf += blk;
             _sockets[socket].pending -= blk;
-        } else if ((_sockets[socket].timeout_ms == TIMEOUT_BLOCKING) || 
-                   (timer.read_ms() < _sockets[socket].timeout_ms)) {
+        } else if (!TIMEOUT(timer, _sockets[socket].timeout_ms)) {
             // allow to receive unsolicited commands 
             waitFinalResp(NULL, NULL, 10);
-        } else {
+        } else
             len = 0; // no more data and socket closed or timed-out
-        }
     }
     timer.stop();
     timer.reset();
@@ -1084,14 +1098,14 @@
 void MDMParser::dumpDevStatus(MDMParser::DevStatus* status, 
             _DPRINT dprint, void* param) 
 {
-    dprint(param, "Modem Device Status:\r\n");
+    dprint(param, "Modem::devStatus\r\n");
     const char* txtDev[] = { "Unknown", "SARA-G350", "LISA-U200", "LISA-C200" };
     if (status->dev < sizeof(txtDev)/sizeof(*txtDev) && (status->dev != MDMParser::DEV_UNKNOWN))
         dprint(param, "  Device:       %s\r\n", txtDev[status->dev]);
     const char* txtLpm[] = { "Disabled", "Enabled", "Active" };
     if (status->lpm < sizeof(txtLpm)/sizeof(*txtLpm))
         dprint(param, "  Power Save:   %s\r\n", txtLpm[status->lpm]);
-    const char* txtSim[] = { "Unknown", "Pin", "Ready" };
+    const char* txtSim[] = { "Unknown", "Missing", "Pin", "Ready" };
     if (status->sim < sizeof(txtSim)/sizeof(*txtSim) && (status->sim != MDMParser::SIM_UNKNOWN))
         dprint(param, "  SIM:          %s\r\n", txtSim[status->sim]);
     if (*status->ccid)  
@@ -1113,7 +1127,7 @@
 void MDMParser::dumpNetStatus(MDMParser::NetStatus *status,
             _DPRINT dprint, void* param)
 {
-    dprint(param, "Modem Network Status:\r\n");
+    dprint(param, "Modem::netStatus\r\n");
     const char* txtReg[] = { "Unknown", "Denied", "None", "Home", "Roaming" };
     if (status->reg < sizeof(txtReg)/sizeof(*txtReg) && (status->reg != MDMParser::REG_UNKNOWN))
         dprint(param, "  Registration:       %s\r\n", txtReg[status->reg]);
@@ -1141,7 +1155,7 @@
             _DPRINT dprint, void* param) 
 {
     if (ip != NOIP)
-        dprint(param, "Modem IP Address: " IPSTR "\r\n", IPNUM(ip));
+        dprint(param, "Modem:IP " IPSTR "\r\n", IPNUM(ip));
 }
     
 // ----------------------------------------------------------------
--- a/MDM.h	Thu May 15 22:20:42 2014 +0000
+++ b/MDM.h	Fri May 16 14:13:00 2014 +0000
@@ -7,9 +7,9 @@
 #include "SerialPipe.h"
 
 #ifdef TARGET_UBLOX_C027
- #define _IF(onboard,shield) onboard
+ #define MDM_IF(onboard,shield) onboard
 #else
- #define _IF(onboard,shield) shield
+ #define MDM_IF(onboard,shield) shield
 #endif
 
 //! include debug capabilty on more powerful targets with a dedicated debug port 
@@ -35,7 +35,7 @@
     //! MT Device Types 
     typedef enum { DEV_UNKNOWN, DEV_SARA_G350, DEV_LISA_U200, DEV_LISA_C200 } Dev; 
     //! SIM Status
-    typedef enum { SIM_UNKNOWN, SIM_PIN, SIM_READY } Sim;
+    typedef enum { SIM_UNKNOWN, SIM_MISSING, SIM_PIN, SIM_READY } Sim;
     //! SIM Status
     typedef enum { LPM_DISABLED, LPM_ENABLED, LPM_ACTIVE, LPM_SLEEP } Lpm; 
     //! Device status
@@ -98,7 +98,7 @@
     */
     bool connect(const char* simpin, 
             const char* apn, const char* username, const char* password,
-            PinName pn _IF( = MDMPWRON, = D4));    
+            PinName pn MDM_IF( = MDMPWRON, = D4));    
 
     /** register (Attach) the MT to the GPRS service. 
         \param simpin a optional pin of the SIM card
@@ -106,7 +106,14 @@
         \return true if successful, false otherwise
     */
     bool init(const char* simpin = NULL, DevStatus* status = NULL, 
-                PinName pn _IF( = MDMPWRON, = D4));
+                PinName pn MDM_IF( = MDMPWRON, = D4));
+    
+    /** register to the network 
+        \param status an optional structure to with network information 
+        \param timeout_ms -1 blocking, else non blocking timeout in ms
+        \return true if successful and connected to network, false otherwise
+    */
+    bool registerNet(NetStatus* status = NULL, int timeout_ms = 180000);
     
     /** check if the network is available 
         \param status an optional structure to with network information 
@@ -527,12 +534,12 @@
         \param rxSize the size of the serial rx buffer
         \param txSize the size of the serial tx buffer
     */
-    MDMSerial(PinName tx    _IF( = MDMTXD,  = D1 ), 
-              PinName rx    _IF( = MDMRXD,  = D2 ), 
-              int baudrate  _IF( = MDMBAUD, = 115200 ),
+    MDMSerial(PinName tx    MDM_IF( = MDMTXD,  = D1 ), 
+              PinName rx    MDM_IF( = MDMRXD,  = D0 ), 
+              int baudrate  MDM_IF( = MDMBAUD, = 115200 ),
  #if DEVICE_SERIAL_FC
-              PinName rts   _IF( = MDMRTS,  = NC ), 
-              PinName cts   _IF( = MDMCTS,  = NC ),
+              PinName rts   MDM_IF( = MDMRTS,  = NC /* D2 resistor R62 on shield not mounted */ ), 
+              PinName cts   MDM_IF( = MDMCTS,  = NC /* D3 resistor R63 on shield not mounted */ ),
  #endif
               int rxSize    = 256 , 
               int txSize    = 128 );
@@ -553,6 +560,7 @@
     virtual int _send(const void* buf, int len);
 };
 
+ 
 // -----------------------------------------------------------------------
 
 //#define HAVE_MDMUSB
--- a/Pipe.h	Thu May 15 22:20:42 2014 +0000
+++ b/Pipe.h	Fri May 16 14:13:00 2014 +0000
@@ -1,4 +1,5 @@
 #pragma once 
+#include "Relax.h"
 
 /** pipe, this class implements a buffered pipe that can be savely 
     written and read between two context. E.g. Written from a task 
@@ -77,7 +78,7 @@
         int j = i;
         i = _inc(i);
         while (i == _r) // = !writeable() 
-            /*wait for space*/;
+            RELAX_MS(0);
         _b[j] = c;
         _w = i; 
         return c;
@@ -100,6 +101,7 @@
                 f = free();
                 if (f > 0) break;     // data avail
                 if (!t) return n - c; // no more space and not blocking
+                RELAX_MS(0);
             }
             // check free space
             if (c < f) f = c;
@@ -144,7 +146,7 @@
     {
         int r = _r;
         while (r == _w) // = !readable()
-            /*wait for data*/;
+            RELAX_MS(0);
         T t = _b[r];
         _r = _inc(r);
         return t;
@@ -167,6 +169,7 @@
                 f = size();
                 if (f)  break;        // free space
                 if (!t) return n - c; // no space and not blocking
+                RELAX_MS(0);
             }
             // check available data
             if (c < f) f = c;
--- a/SerialPipe.cpp	Thu May 15 22:20:42 2014 +0000
+++ b/SerialPipe.cpp	Fri May 16 14:13:00 2014 +0000
@@ -39,11 +39,16 @@
         do
         {
             int written = _pipeTx.put(ptr, count, false);
-            ptr += written;
-            count -= written;
-            txStart();
+            if (written) {
+                ptr += written;
+                count -= written;
+                txStart();
+            }
+            else if (!blocking)
+                break;
+            RELAX_MS(0);
         }
-        while (count && blocking);
+        while (count);
     }
     return (length - count);
 }