Own fork of C027_Support
Dependents: MbedSmartRestMain MbedSmartRestMain
Fork of C027_Support by
Revision 74:208e3e32d263, committed 2014-05-15
- Comitter:
- mazgch
- Date:
- Thu May 15 22:20:42 2014 +0000
- Parent:
- 73:2b32e0a21df2
- Child:
- 75:ce6e12067d0c
- Commit message:
- initial version of restructured u-blox library
Changed in this revision
--- a/GPS.cpp Thu May 15 08:25:45 2014 +0000 +++ b/GPS.cpp Thu May 15 22:20:42 2014 +0000 @@ -1,6 +1,26 @@ #include "mbed.h" #include <ctype.h> #include "GPS.h" +#include "Relax.h" +#ifdef TARGET_UBLOX_C027 + #include "C027_api.h" +#endif + +GPSParser::~GPSParser(void) +{ + powerOff(); +#ifdef TARGET_UBLOX_C027 + if (_onboard) + c027_gps_powerOff(); +#endif +} + +void GPSParser::powerOff(void) +{ + // set the gps into backup mode using the command RMX-LPREQ + struct { unsigned long dur; unsigned long flags; } msg = {0/*endless*/,0/*backup*/}; + sendUbx(0x02, 0x41, &msg, sizeof(msg)); +} int GPSParser::_getMessage(Pipe<char>* pipe, char* buf, int len) { @@ -104,13 +124,6 @@ return _send(buf, len); } -void GPSParser::powerOff(void) -{ - // set the gps into backup mode using the command RMX-LPREQ - struct { unsigned long dur; unsigned long flags; } msg = {0/*endless*/,0/*backup*/}; - sendUbx(0x02, 0x41, &msg, sizeof(msg)); -} - int GPSParser::sendNmea(const char* buf, int len) { char head[1] = { '$' }; @@ -238,6 +251,26 @@ SerialPipe(tx, rx, rxSize, txSize) { baud(baudrate); +#ifdef TARGET_UBLOX_C027 + _onboard = (tx == GPSTXD) || (rx == GPSRXD); + if (_onboard) + c027_gps_powerOn(); +#endif +} + +bool GPSSerial::init(void) +{ + // send a byte to wakup the device again + putc(0); + // wait until we get some bytes + int size = _pipeRx.size(); + int i = 30; + while (i--) { + RELAX_MS(10); + if(size != _pipeRx.size()) + break; + } + return (i >= 0); } int GPSSerial::getMessage(char* buf, int len) @@ -261,18 +294,20 @@ _i2cAdr(i2cAdr) { frequency(100000); - found = false; +#ifdef TARGET_UBLOX_C027 + _onboard = (sda == GPSSDA) && (scl == GPSSCL); + if (_onboard) + c027_gps_powerOn(); +#endif } -bool GPSI2C::detect(void) +bool GPSI2C::init(void) { - if (!found) - { - int w = I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM)); - if (w == 0) - found = true; - } - return found; + DigitalOut pin(GPSINT, 0); + wait_us(1); + pin = 1; + RELAX_MS(100); + return !I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM)); } int GPSI2C::getMessage(char* buf, int len) @@ -294,7 +329,6 @@ { if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) sent = send(buf, len); - found = (len == sent); stop(); } return sent; @@ -305,7 +339,6 @@ int sent = 0; if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) sent = GPSParser::sendNmea(buf, len); - found = (len == sent); stop(); return sent; } @@ -315,7 +348,6 @@ int sent = 0; if (!I2C::write(_i2cAdr,®STREAM,sizeof(REGSTREAM),true)) sent = GPSParser::sendUbx(cls, id, buf, len); - found = (len == sent); I2C::stop(); return sent; } @@ -336,12 +368,8 @@ !I2C::read(_i2cAdr,buf,size)) { read = size; } - else - found = false; } } - else - found = false; return read; }
--- a/GPS.h Thu May 15 08:25:45 2014 +0000 +++ b/GPS.h Thu May 15 22:20:42 2014 +0000 @@ -5,12 +5,9 @@ #include "SerialPipe.h" #ifdef TARGET_UBLOX_C027 - // if we detect the C027 platform we will assign the - // default pinname and baudrate in the constructor - // this helper macro will be used. - #define _C027DEFAULT(name) = name + #define _IF(onboard, shield) onboard #else - #define _C027DEFAULT(name) + #define _IF(onboard, shield) shield #endif /** basic gps parser class @@ -18,6 +15,14 @@ class GPSParser { public: + + //! Constructor + ~GPSParser(void); + + /** Power on / Wake up the gps + */ + virtual bool init(void) = 0; + enum { // getLine Responses WAIT = -1, //!< wait for more incoming data (the start of a message was found, or no data available) @@ -66,7 +71,7 @@ */ virtual int sendUbx(unsigned char cls, unsigned char id, const void* buf = NULL, int len = 0); - + /** Power off the gps, it can be again woken up by an edge on the serial port on the external interrupt pin. */ @@ -155,6 +160,9 @@ virtual int _send(const void* buf, int len) = 0; static const char toHex[16]; //!< num to hex conversion +#ifdef TARGET_UBLOX_C027 + bool _onboard; +#endif }; /** gps class which uses a serial port @@ -170,12 +178,14 @@ \param rxSize the size of the serial rx buffer \param txSize the size of the serial tx buffer */ - GPSSerial(PinName tx _C027DEFAULT( GPSTXD ), - PinName rx _C027DEFAULT( GPSRXD ), - int baudrate _C027DEFAULT( GPSBAUD ), + 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 ), int rxSize = 256 , int txSize = 128 ); + virtual bool init(void); + /** Get a line from the physical interface. \param buf the buffer to store it \param len size of the buffer @@ -205,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 _C027DEFAULT( GPSSDA ), - PinName scl _C027DEFAULT( GPSSCL ), - unsigned char i2cAdr _C027DEFAULT( GPSADR ), + GPSI2C(PinName sda _IF( = GPSSDA, = D14 ), + PinName scl _IF( = GPSSCL, = D15 ), + unsigned char i2cAdr _IF( = GPSADR, = (66<<1) ), int rxSize = 256 ); - + /** helper function to probe the i2c device \return true if successfully detected the gps. */ - bool detect(void); + virtual bool init(void); /** Get a line from the physical interface. \param buf the buffer to store it @@ -277,7 +287,6 @@ int _get(char* buf, int len); Pipe<char> _pipe; //!< the rx pipe - bool found; //!< flag if device is detected. unsigned char _i2cAdr; //!< the i2c address static const char REGLEN; //!< the length i2c register address static const char REGSTREAM;//!< the stream i2c register address
--- a/MDM.cpp Thu May 15 08:25:45 2014 +0000 +++ b/MDM.cpp Thu May 15 22:20:42 2014 +0000 @@ -2,30 +2,34 @@ #include <ctype.h> #include <string.h> #include "MDM.h" +#include "Relax.h" +#ifdef TARGET_UBLOX_C027 + #include "C027_api.h" +#endif -#define TRACE (1/*1=off,0=trace*/)?:printf -//#define DEBUG // enable this for AT command debugging -#define PROFILE "0" // this is the psd profile used -// some helper +#define PROFILE "0" //!< this is the psd profile used +#define MAX_SIZE 128 //!< max expected messages +//! test if it is a socket #define ISSOCKET(s) (((s) >= 0) && ((s) < (sizeof(_sockets)/sizeof(*_sockets)))) -#define WAIT_MS(ms) wait_ms(ms) // you may choose to use Thread::wait(ms) -#define MAX_SIZE 128 // max expected messages -#ifdef DEBUG -void dump(const char* buf, int len) +#ifdef MDM_DEBUG +void dumpAtCmd(const char* buf, int len) { + printf(" %3d \"", len); while (len --) { char ch = *buf++; - if (ch == '\r') printf("\\r"); - else if (ch == '\n') printf("\\n"); - else if (ch >= 0x20) printf("%c", ch); + if (ch == '\r') puts("\\r"); + else if (ch == '\n') puts("\\n"); + else if (ch >= 0x20) putchar(ch); else printf("\\x%02x", ch); } + puts("\"\r\n"); } - -Timer dbgTime; - + + #define INFO (_debugLevel >= 1) ? : printf + #define TRACE (_debugLevel >= 2) ? : printf + #if 1 // colored terminal output using ANSI escape sequences #define COL(c,t) "\33[" c t "\33[" "39m" #else @@ -39,6 +43,12 @@ #define MAG(t) COL("35m",t) #define CYA(t) COL("36m",t) #define WHY(t) COL("37m",t) + +#else + + #define INFO(...) (void)0 // no tracing + #define TRACE(...) (void)0 // no tracing + #endif MDMParser* MDMParser::inst; @@ -52,18 +62,27 @@ _net.ci = 0xFFFFFFFF; _ip = NOIP; memset(_sockets, 0, sizeof(_sockets)); -#ifdef DEBUG - dbgTime.start(); +#ifdef MDM_DEBUG + _debugTime.start(); +#endif +} + +MDMParser::~MDMParser(void) +{ + powerOff(); +#ifdef TARGET_UBLOX_C027 + if (_onboard) + c027_mdm_powerOff(); #endif } int MDMParser::send(const char* buf, int len) { -#ifdef DEBUG - printf("%10.3f ", dbgTime.read_ms()*0.001); - printf("AT send %4d \"", len); - dump(buf,len); - printf("\"\r\n"); +#ifdef MDM_DEBUG + if (_debugLevel >= 3) { + printf("%10.3f AT send ", _debugTime.read_ms()*0.001); + dumpAtCmd(buf,len); + } #endif return _send(buf, len); } @@ -86,8 +105,8 @@ timer.start(); do { int ret = getLine(buf, sizeof(buf)); -#ifdef DEBUG - if ((ret != WAIT) && (ret != NOT_FOUND)) +#ifdef MDM_DEBUG + if ((_debugLevel >= 3) && (ret != WAIT) && (ret != NOT_FOUND)) { int len = LENGTH(ret); int type = TYPE(ret); @@ -98,10 +117,8 @@ (type == TYPE_PLUS) ? CYA(" + ") : (type == TYPE_PROMPT) ? BLU(" > ") : "..." ; - printf("%10.3f ", dbgTime.read_ms()*0.001); - printf("AT read %s %3d \"", s, len); - dump(buf, len); - printf("\"\r\n"); + printf("%10.3f AT read %s", _debugTime.read_ms()*0.001, s); + dumpAtCmd(buf, len); } #endif if ((ret != WAIT) && (ret != NOT_FOUND)) @@ -193,7 +210,7 @@ } } // relax a bit - WAIT_MS(10); + RELAX_MS(10); } while ((timeout_ms == TIMEOUT_BLOCKING) || (timer.read_ms() < timeout_ms)); @@ -225,46 +242,60 @@ bool MDMParser::connect( const char* simpin, const char* apn, const char* username, const char* password, - bool dump) + PinName pn) { DevStatus devStatus = {}; - WAIT_MS(2000); - bool mdmOk = init(simpin, &devStatus); - if (dump) dumpDevStatus(&devStatus); + bool mdmOk = init(simpin, &devStatus, pn); +#ifdef MDM_DEBUG + if (_debugLevel >= 1) dumpDevStatus(&devStatus); +#endif if (!mdmOk) return false; // wait until we are connected - int i = 60; + int i = 180; NetStatus netStatus = {}; + INFO("Modem::register\r\n"); while (!checkNetStatus(&netStatus)) { if ((netStatus.reg == REG_DENIED) || (i == 0)) break;; i --; - WAIT_MS(1000); + RELAX_MS(1000); } - if (dump) dumpNetStatus(&netStatus); +#ifdef MDM_DEBUG + if (_debugLevel >= 1) dumpNetStatus(&netStatus); +#endif if ((netStatus.reg == REG_DENIED) || (i == 0)) return false; IP ip = join(apn,username,password); - if (dump) dumpIp(ip); +#ifdef MDM_DEBUG + if (_debugLevel >= 1) dumpIp(ip); +#endif if (ip == NOIP) return false; return true; } -bool MDMParser::init(const char* simpin, DevStatus* status) +bool MDMParser::init(const char* simpin, DevStatus* status, PinName pn) { - int i = 5; - // we should wait some time before - while (i--) { - // check interface and disable local echo - sendFormated("AT\r\n"); - if(RESP_OK == waitFinalResp(NULL,NULL,1000)) - break; + int i = 10; + if (pn != NC) { + INFO("Modem::wakeup\r\n"); + DigitalOut pin(pn, 1); + while (i--) { + pin = 0; + RELAX_MS(5); // SARA-G/U + pin = 1; + RELAX_MS(100); + // check interface and disable local echo + sendFormated("AT\r\n"); + if(RESP_OK == waitFinalResp(NULL,NULL,500)) + break; + } + if (i < 0) + return false; } - if (i < 0) - return false; + INFO("Modem::init\r\n"); // echo off sendFormated("AT E0\r\n"); if(RESP_OK != waitFinalResp()) @@ -277,7 +308,7 @@ sendFormated("AT+IPR=115200\r\n"); if (RESP_OK != waitFinalResp()) return false; - WAIT_MS(40); + RELAX_MS(40); // identify the module sendFormated("ATI\r\n"); if (RESP_OK != waitFinalResp(_cbATI, &_dev.dev)) @@ -334,14 +365,14 @@ // Enter PIN if needed if (_dev.sim == SIM_PIN) { if (!simpin) { - TRACE("SIM PIN not available\r\n"); + INFO("SIM PIN not available\r\n"); return false; } sendFormated("AT+CPIN=%s\r\n", simpin); if (RESP_OK != waitFinalResp(_cbCPIN, &_dev.sim)) return false; } else if (_dev.sim != SIM_READY) { - WAIT_MS(1000); + RELAX_MS(1000); } } if (_dev.sim != SIM_READY) @@ -403,6 +434,15 @@ return true; } +bool MDMParser::powerOff(void) +{ + INFO("Modem::powerOff\r\n"); + sendFormated("AT+CPWROFF\r\n"); + if (RESP_OK != waitFinalResp(NULL,NULL,120*1000)) + return false; + return true; +} + int MDMParser::_cbATI(int type, const char* buf, int len, Dev* dev) { if ((type == TYPE_UNKNOWN) && dev) { @@ -538,19 +578,13 @@ } return WAIT; } -bool MDMParser::powerOff(void) -{ - sendFormated("AT+CPWROFF\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,120)) - return false; - return true; -} // ---------------------------------------------------------------- // internet connection MDMParser::IP MDMParser::join(const char* apn /*= NULL*/, const char* username /*= NULL*/, const char* password /*= NULL*/) { + TRACE("Modem::join\r\n"); _ip = NOIP; if (_dev.dev == DEV_LISA_C200) { // TODO: is there something to do here? @@ -565,7 +599,7 @@ } else { // check gprs attach status sendFormated("AT+CGATT=1\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) + if (RESP_OK != waitFinalResp(NULL,NULL,3*60*1000)) return NOIP; // Check the profile @@ -601,8 +635,10 @@ return NOIP; // Activate the profile and make connection sendFormated("AT+UPSDA=" PROFILE ",3\r\n"); - if (RESP_OK != waitFinalResp(NULL,NULL,150*1000)) + if (RESP_OK != waitFinalResp(NULL,NULL,150*1000)) { + INFO("Your modem APN/password/username may be wrong\r\n"); return NOIP; + } //Get local IP address sendFormated("AT+UPSND=" PROFILE ",0\r\n"); if (RESP_OK != waitFinalResp(_cbUPSND, &_ip)) @@ -655,6 +691,7 @@ { if (_ip == NOIP) return true; + INFO("Modem::disconnect\r\n"); if (_dev.dev == DEV_LISA_C200) { // TODO: is there something to do here? } else { @@ -738,7 +775,6 @@ TRACE("socketIsConnected(%d)\r\n", socket); if (!ISSOCKET(socket)) return false; - TRACE(" ... %d\r\n", _sockets[socket].state); return _sockets[socket].state == SOCK_CONNECTED; } @@ -786,7 +822,7 @@ sendFormated("AT+USOWR=%d,%d\r\n",socket,blk); if (RESP_PROMPT != waitFinalResp()) return SOCKET_ERROR; - WAIT_MS(50); + RELAX_MS(50); send(buf, blk); if (RESP_OK != waitFinalResp()) return SOCKET_ERROR; @@ -807,7 +843,7 @@ sendFormated("AT+USOST=%d,\"" IPSTR "\",%d,%d\r\n",socket,IPNUM(ip),port,blk); if (RESP_PROMPT != waitFinalResp()) return SOCKET_ERROR; - WAIT_MS(50); + RELAX_MS(50); send(buf, blk); if (RESP_OK != waitFinalResp()) return SOCKET_ERROR; @@ -1034,7 +1070,17 @@ } // ---------------------------------------------------------------- - +bool MDMParser::setDebug(int level) +{ +#ifdef MDM_DEBUG + if ((_debugLevel >= 0) && (level >= 0)) { + _debugLevel = level; + return true; + } +#endif + return false; +} + void MDMParser::dumpDevStatus(MDMParser::DevStatus* status, _DPRINT dprint, void* param) { @@ -1158,7 +1204,6 @@ return o; } - int MDMParser::_getLine(Pipe<char>* pipe, char* buf, int len) { int unkn = 0; @@ -1230,6 +1275,14 @@ int rxSize /*= 256*/, int txSize /*= 128*/) : SerialPipe(tx, rx, rxSize, txSize) { +#ifdef MDM_DEBUG + _debugLevel = (tx == USBTX) ? -1 : 1; +#endif +#ifdef TARGET_UBLOX_C027 + _onboard = (tx == MDMTXD) && (rx == MDMRXD); + if (_onboard) + c027_mdm_powerOn(false); +#endif baud(baudrate); #if DEVICE_SERIAL_FC if ((rts != NC) || (cts != NC)) @@ -1257,8 +1310,16 @@ // ---------------------------------------------------------------- #ifdef HAVE_MDMUSB -// TODO properly implement with USB -MDMUsb::MDMUsb(void) { } +MDMUsb(void) +{ +#ifdef MDM_DEBUG + _debugLevel = 1; +#endif +#ifdef TARGET_UBLOX_C027 + _onboard = true; + c027_mdm_powerOn(true); +#endif +} int MDMUsb::_send(const void* buf, int len) { return len; } int MDMUsb::getLine(char* buffer, int length) { return NOT_FOUND; } #endif
--- a/MDM.h Thu May 15 08:25:45 2014 +0000 +++ b/MDM.h Thu May 15 22:20:42 2014 +0000 @@ -7,14 +7,16 @@ #include "SerialPipe.h" #ifdef TARGET_UBLOX_C027 - // if we detect the C027 platform we will assign the - // default pinname and baudrate in the constructor - // this helper macro will be used. - #define _C027DEFAULT(name) = name + #define _IF(onboard,shield) onboard #else - #define _C027DEFAULT(name) + #define _IF(onboard,shield) shield #endif +//! include debug capabilty on more powerful targets with a dedicated debug port +#if defined(TARGET_LPC1768) || defined(TARGET_LPC4088) || defined(TARGET_K64F) + #define MDM_DEBUG +#endif + /** basic modem parser class */ class MDMParser @@ -22,6 +24,8 @@ public: //! Constructor MDMParser(); + //! Destructor + ~MDMParser(); //! get static instance static MDMParser* getInstance() { return inst; }; @@ -94,14 +98,15 @@ */ bool connect(const char* simpin, const char* apn, const char* username, const char* password, - bool dump); + PinName pn _IF( = MDMPWRON, = D4)); /** register (Attach) the MT to the GPRS service. \param simpin a optional pin of the SIM card \param status an optional struture to with device information \return true if successful, false otherwise */ - bool init(const char* simpin = NULL, DevStatus* status = NULL); + bool init(const char* simpin = NULL, DevStatus* status = NULL, + PinName pn _IF( = MDMPWRON, = D4)); /** check if the network is available \param status an optional structure to with network information @@ -279,9 +284,15 @@ bool ussdCommand(const char* cmd, char* buf); // ---------------------------------------------------------------- - // DUMP status to standard out (printf) + // DEBUG/DUMP status to standard out (printf) // ---------------------------------------------------------------- + /*! Set the debug level + \param level 0 = OFF, 1 = INFO(default), 2 = TRACE, 3 = ATCMD + \return true if successful, false not possible + */ + bool setDebug(int level); + //! helper type for DPRINT typedef int (*_DPRINT)(void* param, char const * format, ...); @@ -294,7 +305,7 @@ static void func(type arg, \ _DPRINT dprint = (_DPRINT)fprintf, \ void* param = (void*)stdout); - + /** dump the device status to stdout using printf \param status the status to convert to textual form, unavailable fields are ommited (not printed) @@ -487,6 +498,13 @@ // LISA-U and SARA-G have 7 sockets starting at index 1 SockCtrl _sockets[32]; static MDMParser* inst; +#ifdef TARGET_UBLOX_C027 + bool _onboard; +#endif +#ifdef MDM_DEBUG + int _debugLevel; + Timer _debugTime; +#endif }; // ----------------------------------------------------------------------- @@ -509,12 +527,12 @@ \param rxSize the size of the serial rx buffer \param txSize the size of the serial tx buffer */ - MDMSerial(PinName tx _C027DEFAULT(MDMTXD), - PinName rx _C027DEFAULT(MDMRXD), - int baudrate _C027DEFAULT(MDMBAUD), + MDMSerial(PinName tx _IF( = MDMTXD, = D1 ), + PinName rx _IF( = MDMRXD, = D2 ), + int baudrate _IF( = MDMBAUD, = 115200 ), #if DEVICE_SERIAL_FC - PinName rts _C027DEFAULT(MDMRTS), - PinName cts _C027DEFAULT(MDMCTS), + PinName rts _IF( = MDMRTS, = NC ), + PinName cts _IF( = MDMCTS, = NC ), #endif int rxSize = 256 , int txSize = 128 );
--- a/Pipe.h Thu May 15 08:25:45 2014 +0000 +++ b/Pipe.h Thu May 15 22:20:42 2014 +0000 @@ -15,7 +15,7 @@ */ Pipe(int n, T* b = NULL) { - _a = b ? NULL : new T[n]; + _a = b ? NULL : n ? new T[n] : NULL; _r = 0; _w = 0; _b = b ? b : _a; @@ -98,7 +98,7 @@ for (;;) // wait for space { f = free(); - if (f) break; // data avail + if (f > 0) break; // data avail if (!t) return n - c; // no more space and not blocking } // check free space
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Relax.cpp Thu May 15 22:20:42 2014 +0000 @@ -0,0 +1,8 @@ + +#include "Relax.h" + +// weak override wait function from cmsis_os.h on non rtos builds +extern "C" WEAK void osDelay(uint32_t ms) { + wait_ms(ms); +} +
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/Relax.h Thu May 15 22:20:42 2014 +0000 @@ -0,0 +1,16 @@ +#pragma once + +#include "mbed.h" + +// declare the osDelay (usually from cmsis_os.h) +extern "C" void osDelay(uint32_t ms); + +/** A wait function that is independent whether the OS is includes or not + if rtos is included the Thread will yield for a certain time + otherwise (without rtos) it will just stay in a busy loop. + + \param ms number of milliseconds to wait +*/ +inline void RELAX_MS(int ms) { + osDelay(ms); +} \ No newline at end of file
--- a/SerialPipe.cpp Thu May 15 08:25:45 2014 +0000 +++ b/SerialPipe.cpp Thu May 15 22:20:42 2014 +0000 @@ -2,10 +2,13 @@ #include "SerialPipe.h" -SerialPipe::SerialPipe(PinName tx, PinName rx, int rxSize, int txSize) - : _SerialPipeBase(tx,rx), _pipeRx(rxSize), _pipeTx(txSize) +SerialPipe::SerialPipe(PinName tx, PinName rx, int rxSize, int txSize) : + _SerialPipeBase(tx,rx), + _pipeRx( (rx!=NC) ? rxSize : 0), + _pipeTx( (tx!=NC) ? txSize : 0) { - attach(this, &SerialPipe::rxIrqBuf, RxIrq); + if (rx!=NC) + attach(this, &SerialPipe::rxIrqBuf, RxIrq); } SerialPipe::~SerialPipe(void)