Buffered Serial Port Driver for RTOS

Dependents:   nucleo_cannonball PiballNeoController

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 RawSerial.
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 RawSerial
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 public:
00053     /// @brief Prepares ring buffer and irq
00054     /// 
00055     /// If no buffer was set, the buffer gets allocated.
00056     /// @param txPin TX PinName, e.g. USBTX
00057     /// @param rxPin RX PinName, e.g. USBRX
00058     /// @param txBufferLength_ size of TX buffer. Must be > 1!
00059     /// @param rxBufferLength_ size of RX buffer. Must be > 1!
00060     /// @param txBuffer_ TX buffer, if NULL, the buffer will be allocated
00061     /// @param rxBuffer_ RX buffer, if NULL, the buffer will be allocated
00062     SerialDriver(PinName txPin, PinName rxPin, int txBufferLength_= 256, int rxBufferLength_= 256, unsigned char * txBuffer_= NULL, unsigned char * rxBuffer_= NULL);
00063     
00064     
00065     ////////////////////////////////////////////////////////////////
00066     // Basic IO Operation
00067 
00068     /// @brief Put a byte to the TX buffer
00069     /// 
00070     /// If the TX buffer is full, it waits the defined timeout.
00071     /// Drops the byte, if TX buffer is still full after timeout.
00072     /// @param c The byte to write
00073     /// @param timeoutMs give TX buffer time to get writeable.
00074     /// @return 1 - success, 0 - if TX Buffer was full all the time
00075     int putc(int c, unsigned int timeoutMs= osWaitForever);
00076 
00077     
00078     /// @brief Get a byte from the RX buffer
00079     /// 
00080     /// If the RX buffer is empty, it waits the defined timeout.
00081     /// @param timeoutMs give RX buffer time to get readable.
00082     /// @return next byte from RX buffer or -1 after timeout.
00083     int getc(unsigned int timeoutMs= osWaitForever);    
00084     
00085     
00086 protected:
00087     ////////////////////////////////////////////////////////////////
00088     // Interrupts
00089     
00090     // TX: Move data from txBuffer to SerialBase::putc
00091     void onTxIrq(); // serial base port now writeable, lets put some bytes
00092     
00093     // RX: Move data from SerialBase::getc to rxBuffer
00094     void onRxIrq(); // serial base port now readable, lets get some bytes
00095     
00096     // Enable / Disable
00097     inline void disableTxInterrupt()   {    serial_irq_set(&_serial, (SerialIrq)TxIrq, 0);    }
00098     inline void enableTxInterrupt()    {    serial_irq_set(&_serial, (SerialIrq)TxIrq, 1);    }
00099     
00100     inline void disableRxInterrupt()   {    serial_irq_set(&_serial, (SerialIrq)RxIrq, 0);    }
00101     inline void enableRxInterrupt()    {    serial_irq_set(&_serial, (SerialIrq)RxIrq, 1);    }    
00102     
00103 
00104 public:
00105     ////////////////////////////////////////////////////////////////
00106     // Extended IO Operation
00107     
00108     /// @brief write a buck of bytes
00109     /// 
00110     /// No timeout! To block, or not to block. That is the question.
00111     /// @param buffer buck of bytes
00112     /// @param length write how much bytes?
00113     /// @param block idle wait for every @ref putc to complete
00114     /// @return written bytes. For non block write it could be < length!
00115     int write(const unsigned char * buffer, const unsigned int length, bool block= true);
00116     
00117     /// @brief read a buck of bytes
00118     /// 
00119     /// No timeout! To block, or not to block. That is the question.
00120     /// @param buffer buck of bytes
00121     /// @param length read how much bytes?
00122     /// @param block idle wait for every @ref getc to complete
00123     /// @return read bytes. For non block read it could be < length!
00124     int read(unsigned char * buffer, const unsigned int length, bool block= true);
00125     
00126     
00127     /// @brief Write a string (without terminating null)
00128     /// 
00129     /// For compatibility with mbed RawSerial
00130     /// @param str null terminated string
00131     /// @param block idle wait for every @ref putc to complete
00132     /// @return written chars (without terminating null)
00133     int puts(const char * str, bool block= true);
00134     
00135     /// @brief Print a formatted string.
00136     /// 
00137     /// Idle blocking!
00138     /// Dynamically allocates needed buffer.
00139     /// @param format null terminated format string
00140     /// @return written chars (without terminating null)
00141     int printf(const char * format, ...);    
00142     
00143     
00144     ////////////////////////////////////////////////////////////////
00145     // Buffer Infos
00146     
00147     /// @brief Checks if TX buffer is full
00148     /// @return true - TX buffer is full, false - else
00149     inline bool isTxBufferFull()    {   return txCount == txBufferLength;    }  
00150     
00151     /// @brief Checks if RX buffer is full
00152     /// @return true - RX buffer is full, false - else
00153     inline bool isRxBufferFull()    {   return rxCount == rxBufferLength;    } 
00154     
00155     /// @brief Checks if TX buffer is empty
00156     /// @return true - TX buffer is empty, false - else
00157     inline bool isTxBufferEmtpy()   {    return txCount == 0;    }    
00158     
00159     /// @brief Checks if RX buffer is empty
00160     /// @return true - RX buffer is empty, false - else
00161     inline bool isRxBufferEmpty()   {    return rxCount == 0;    }
00162     
00163     
00164     /// @brief Checks if TX buffer is writeable (= not full).
00165     /// 
00166     /// For compatibility with mbed Serial.
00167     /// @return true - TX buffer is writeable, false - else
00168     inline bool writeable()     {   return !isTxBufferFull();   }
00169     
00170     /// @brief Checks if RX buffer is readable (= not empty).
00171     /// 
00172     /// For compatibility with mbed Serial.
00173     /// @return true - RX buffer is readable, false - else
00174     inline bool readable()      {   return !isRxBufferEmpty();   }
00175     
00176     
00177     /// @brief Returns number of dropped bytes that did not fit into TX buffer
00178     /// @return number of dropped tx bytes
00179     inline int getNumTxDrops()  {   return numTxDrops;  }
00180     
00181     /// @brief Returns number of dropped bytes that did not fit into RX buffer
00182     /// @return number of dropped rx bytes
00183     inline int getNumRxDrops()  {   return numRxDrops;  }
00184 };