Richard Osterloh / SerialDriver

Fork of SerialDriver by BlazeX .

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SerialDriver.h Source File

SerialDriver.h

Go to the documentation of this file.
00001 /// @file SerialDriver.h
00002 /// @brief RTOS compatible buffered Serial port driver
00003 /// 
00004 /// Examples:
00005 /// - @ref Example_printf.cpp
00006 /// - @ref Example_Nullmodem.cpp
00007 /// - @ref Example_Bridge.cpp
00008 /// - @ref Example_Blocking.cpp
00009 /// 
00010 /// 
00011 /// Dependencies:
00012 /// - cstdarg
00013 /// @see https://developer.mbed.org/users/mbed_official/code/mbed-rtos/
00014 /// @see https://developer.mbed.org/users/mbed_official/code/mbed/
00015 
00016 #pragma once
00017 
00018 #include "mbed.h"
00019 #include "rtos.h"
00020 #include <cstdarg>
00021 
00022 
00023 /// @class SerialDriver
00024 /// @brief RTOS compatible buffered Serial port driver
00025 /// 
00026 /// - Based on SerialBase.
00027 /// - Can use external buffers.
00028 /// - ISR driven, ring buffered IO operation
00029 /// - Can Replace mbed RawSerial
00030 /// - IO operations are idle waiting, don't waste time in RTOS :D
00031 /// - Do not use attach methods for TxIrq or RxIrq! They are already in use.
00032 class SerialDriver : public SerialBase
00033 {
00034 protected:
00035     // ring buffered rx/tx
00036     unsigned char * txBuffer;
00037     unsigned char * rxBuffer;
00038     int txBufferLength, rxBufferLength;
00039     
00040     // ring buffer cursors
00041     volatile int txIn, txOut;
00042     volatile int rxIn, rxOut;
00043     volatile int txCount, rxCount;
00044     
00045     // semaphores for timeout (used as signals)
00046     Semaphore semTxBufferFull;   // used by putc to wait
00047     Semaphore semRxBufferEmpty;  // used by getc to wait
00048     
00049     // drop counters
00050     volatile int numTxDrops, numRxDrops;
00051     
00052     FunctionPointer _callback_rx_overflow;
00053     FunctionPointer _callback_tx_overflow;
00054     FunctionPointer _callback_auto_detect;
00055     
00056 public:
00057     enum IrqType { RxOvIrq = 0, TxOvIrq, RxAutoDetect};
00058     
00059     /// @brief Prepares ring buffer and irq
00060     /// 
00061     /// If no buffer was set, the buffer gets allocated.
00062     /// @param txPin TX PinName, e.g. USBTX
00063     /// @param rxPin RX PinName, e.g. USBRX
00064     /// @param txBufferLength_ size of TX buffer. Must be > 1!
00065     /// @param rxBufferLength_ size of RX buffer. Must be > 1!
00066     /// @param txBuffer_ TX buffer, if NULL, the buffer will be allocated
00067     /// @param rxBuffer_ RX buffer, if NULL, the buffer will be allocated
00068     SerialDriver(PinName txPin, PinName rxPin, int txBufferLength_= 256, int rxBufferLength_= 256, unsigned char * txBuffer_= NULL, unsigned char * rxBuffer_= NULL);
00069     
00070     
00071     void attach(IrqType irq, void (*function)(void)) { 
00072         if (irq == RxOvIrq) {
00073             _callback_tx_overflow.attach( function );
00074         } else if (irq == TxOvIrq) {
00075             _callback_tx_overflow.attach( function );
00076         } else if (irq == RxAutoDetect) {
00077             _callback_auto_detect.attach( function ); 
00078         } //else {  }
00079     }
00080     
00081     ////////////////////////////////////////////////////////////////
00082     // Basic IO Operation
00083 
00084     /// @brief Put a byte to the TX buffer
00085     /// 
00086     /// If the TX buffer is full, it waits the defined timeout.
00087     /// Drops the byte, if TX buffer is still full after timeout.
00088     /// @param c The byte to write
00089     /// @param timeoutMs give TX buffer time to get writeable.
00090     /// @return 1 - success, 0 - if TX Buffer was full all the time
00091     int putc(int c, unsigned int timeoutMs= osWaitForever);
00092 
00093     
00094     /// @brief Get a byte from the RX buffer
00095     /// 
00096     /// If the RX buffer is empty, it waits the defined timeout.
00097     /// @param timeoutMs give RX buffer time to get readable.
00098     /// @return next byte from RX buffer or -1 after timeout.
00099     int getc(unsigned int timeoutMs= osWaitForever);    
00100     
00101     
00102 protected:
00103     ////////////////////////////////////////////////////////////////
00104     // Interrupts
00105     
00106     // TX: Move data from txBuffer to SerialBase::putc
00107     void onTxIrq(); // serial base port now writeable, lets put some bytes
00108     
00109     // RX: Move data from SerialBase::getc to rxBuffer
00110     void onRxIrq(); // serial base port now readable, lets get some bytes
00111     
00112     // Enable / Disable
00113     inline void disableTxInterrupt()   {    serial_irq_set(&_serial, (SerialIrq)TxIrq, 0);    }
00114     inline void enableTxInterrupt()    {    serial_irq_set(&_serial, (SerialIrq)TxIrq, 1);    }
00115     
00116     inline void disableRxInterrupt()   {    serial_irq_set(&_serial, (SerialIrq)RxIrq, 0);    }
00117     inline void enableRxInterrupt()    {    serial_irq_set(&_serial, (SerialIrq)RxIrq, 1);    }    
00118     
00119 
00120 public:
00121     ////////////////////////////////////////////////////////////////
00122     // Extended IO Operation
00123     
00124     /// @brief write a buck of bytes
00125     /// 
00126     /// No timeout! To block, or not to block. That is the question.
00127     /// @param buffer buck of bytes
00128     /// @param length write how much bytes?
00129     /// @param block idle wait for every @ref putc to complete
00130     /// @return written bytes. For non block write it could be < length!
00131     int write(const unsigned char * buffer, const unsigned int length, bool block= true);
00132     
00133     /// @brief read a buck of bytes
00134     /// 
00135     /// No timeout! To block, or not to block. That is the question.
00136     /// @param buffer buck of bytes
00137     /// @param length read how much bytes?
00138     /// @param block idle wait for every @ref getc to complete
00139     /// @return read bytes. For non block read it could be < length!
00140     int read(unsigned char * buffer, const unsigned int length, bool block= true);
00141     
00142     
00143     /// @brief Write a string (without terminating null)
00144     /// 
00145     /// For compatibility with mbed RawSerial
00146     /// @param str null terminated string
00147     /// @param block idle wait for every @ref putc to complete
00148     /// @return written chars (without terminating null)
00149     int puts(const char * str, bool block= true);
00150     
00151     /// @brief Print a formatted string.
00152     /// 
00153     /// Idle blocking!
00154     /// Dynamically allocates needed buffer.
00155     /// @param format null terminated format string
00156     /// @return written chars (without terminating null)
00157     int printf(const char * format, ...);    
00158     
00159     
00160     ////////////////////////////////////////////////////////////////
00161     // Buffer Infos
00162     
00163     /// @brief Checks if TX buffer is full
00164     /// @return true - TX buffer is full, false - else
00165     inline bool isTxBufferFull()    {   return txCount == txBufferLength;    }  
00166     
00167     /// @brief Checks if RX buffer is full
00168     /// @return true - RX buffer is full, false - else
00169     inline bool isRxBufferFull()    {   return rxCount == rxBufferLength;    } 
00170     
00171     /// @brief Checks if TX buffer is empty
00172     /// @return true - TX buffer is empty, false - else
00173     inline bool isTxBufferEmtpy()   {    return txCount == 0;    }    
00174     
00175     /// @brief Checks if RX buffer is empty
00176     /// @return true - RX buffer is empty, false - else
00177     inline bool isRxBufferEmpty()   {    return rxCount == 0;    }
00178     
00179     
00180     /// @brief Checks if TX buffer is writeable (= not full).
00181     /// 
00182     /// For compatibility with mbed Serial.
00183     /// @return true - TX buffer is writeable, false - else
00184     inline bool writeable()     {   return !isTxBufferFull();   }
00185     
00186     /// @brief Checks if RX buffer is readable (= not empty).
00187     /// 
00188     /// For compatibility with mbed Serial.
00189     /// @return true - RX buffer is readable, false - else
00190     inline bool readable()      {   return !isRxBufferEmpty();   }
00191     
00192     
00193     /// @brief Returns number of dropped bytes that did not fit into TX buffer
00194     /// @return number of dropped tx bytes
00195     inline int getNumTxDrops()  {   return numTxDrops;  }
00196     
00197     /// @brief Returns number of dropped bytes that did not fit into RX buffer
00198     /// @return number of dropped rx bytes
00199     inline int getNumRxDrops()  {   return numRxDrops;  }
00200 };