Buffered Serial Port Driver for RTOS
Dependents: nucleo_cannonball PiballNeoController
SerialDriver.h
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 };
Generated on Tue Jul 12 2022 15:12:29 by 1.7.2