Buffered Serial Port Driver for RTOS
Dependents: nucleo_cannonball PiballNeoController
SerialDriver.cpp
00001 #include "SerialDriver.h" 00002 00003 SerialDriver::SerialDriver(PinName txPin, PinName rxPin, int txBufferLength_, int rxBufferLength_, unsigned char * txBuffer_, unsigned char * rxBuffer_) 00004 : RawSerial(txPin, rxPin), semTxBufferFull(0), semRxBufferEmpty(0) 00005 { 00006 // check buffer length 00007 txBufferLength= txBufferLength_; 00008 if(txBufferLength <= 1) 00009 error("TX buffer length must be > 1 !"); 00010 00011 rxBufferLength= rxBufferLength_; 00012 if(rxBufferLength <= 1) 00013 error("RX buffer length must be > 1 !"); 00014 00015 // take or allocate buffer 00016 txBuffer= txBuffer_; 00017 if(txBuffer == NULL) 00018 { 00019 txBuffer= new unsigned char[txBufferLength]; 00020 if(txBuffer == NULL) 00021 error("Cannot allocate TX buffer!"); 00022 } 00023 00024 rxBuffer= rxBuffer_; 00025 if(rxBuffer == NULL) 00026 { 00027 rxBuffer= new unsigned char[rxBufferLength]; 00028 if(rxBuffer == NULL) 00029 error("Cannot allocate RX buffer!"); 00030 } 00031 00032 00033 // reset cursors 00034 txIn= txOut= 0; 00035 rxIn= rxOut= 0; 00036 txCount= rxCount= 0; 00037 00038 // reset drop counters 00039 numTxDrops= 0; 00040 numRxDrops= 0; 00041 00042 // attach interrupt routines 00043 attach(this, &SerialDriver::onTxIrq, TxIrq); 00044 attach(this, &SerialDriver::onRxIrq, RxIrq); 00045 00046 // we need tx interrupt not yet 00047 disableTxInterrupt(); 00048 } 00049 00050 int SerialDriver::putc(int c, unsigned int timeoutMs) 00051 { 00052 // critical section, isr could modify cursors 00053 disableTxInterrupt(); 00054 00055 if(isTxBufferFull()) 00056 { 00057 // wait for free space 00058 while(semTxBufferFull.wait(0) > 0); // clear semaphore 00059 enableTxInterrupt(); 00060 00061 // let isr work 00062 semTxBufferFull.wait(timeoutMs); 00063 00064 disableTxInterrupt(); 00065 if(isTxBufferFull()) // still full? drop byte! 00066 { 00067 numTxDrops++; 00068 enableTxInterrupt(); 00069 return 0; 00070 } 00071 } 00072 00073 // write this byte to tx buffer 00074 txBuffer[txIn]= (unsigned char)c; 00075 txIn= (txIn+1) % txBufferLength; 00076 txCount++; 00077 00078 // its over, isr can come 00079 enableTxInterrupt(); 00080 00081 // Let's write (isr will check writeability itself) 00082 onTxIrq(); 00083 00084 return 1; 00085 } 00086 00087 void SerialDriver::onTxIrq() 00088 { 00089 // prevent fire another TxIrq now 00090 disableTxInterrupt(); 00091 00092 // write as long as you can 00093 bool wasFull= isTxBufferFull(); 00094 while(SerialBase::writeable() && !isTxBufferEmtpy()) 00095 { 00096 // take byte from tx buffer and put it out 00097 SerialBase::_base_putc(txBuffer[txOut]); 00098 txOut= (txOut+1) % txBufferLength; 00099 txCount--; 00100 } 00101 00102 if(wasFull && !isTxBufferFull()) // more bytes can come 00103 semTxBufferFull.release(); 00104 00105 // ok, let's wait for next writability, 00106 // if there is something to send, 00107 // else we need tx interrupt not yet 00108 if(!isTxBufferEmtpy()) 00109 enableTxInterrupt(); 00110 } 00111 00112 00113 int SerialDriver::getc(unsigned int timeoutMs) 00114 { 00115 // Let's read (isr will check readability itself) 00116 onRxIrq(); 00117 00118 // critical section, isr could modify cursors 00119 disableRxInterrupt(); 00120 00121 if(isRxBufferEmpty()) 00122 { 00123 // wait for new byte 00124 while(semRxBufferEmpty.wait(0) > 0); // clear semaphore 00125 enableRxInterrupt(); 00126 00127 // let isr work 00128 semRxBufferEmpty.wait(timeoutMs); 00129 00130 disableRxInterrupt(); 00131 if(isRxBufferEmpty()) // still empty? nothing received! 00132 { 00133 enableRxInterrupt(); 00134 return -1; 00135 } 00136 } 00137 00138 // get byte from rx buffer 00139 int c= (int)rxBuffer[rxOut]; 00140 rxOut= (rxOut+1) % rxBufferLength; 00141 rxCount--; 00142 00143 // its over, isr can come 00144 enableRxInterrupt(); 00145 00146 return c; 00147 } 00148 00149 void SerialDriver::onRxIrq() 00150 { 00151 // prevent fire another RxIrq now 00152 disableRxInterrupt(); 00153 00154 // read as long as you can 00155 bool wasEmpty= isRxBufferEmpty(); 00156 while(SerialBase::readable()) 00157 { 00158 // get byte and store it to the RX buffer 00159 int c= SerialBase::_base_getc(); 00160 if(!isRxBufferFull()) 00161 { 00162 rxBuffer[rxIn]= (unsigned char)c; 00163 rxIn= (rxIn+1) % rxBufferLength; 00164 rxCount++; 00165 } 00166 else // drop byte :( 00167 numRxDrops++; 00168 } 00169 00170 if(wasEmpty && !isRxBufferEmpty()) // more bytes can go 00171 semRxBufferEmpty.release(); 00172 00173 // ok, let's wait for next readability 00174 enableRxInterrupt(); 00175 } 00176 00177 00178 int SerialDriver::write(const unsigned char * buffer, const unsigned int length, bool block) 00179 { 00180 // try to put all bytes 00181 for(int i= 0; i < length; i++) 00182 if(!putc(buffer[i], block ? osWaitForever : 0)) 00183 return i; // putc failed, but already put i bytes 00184 00185 return length; // put all bytes 00186 } 00187 00188 int SerialDriver::read(unsigned char * buffer, const unsigned int length, bool block) 00189 { 00190 // try to get all bytes 00191 int c; 00192 for(int i= 0; i < length; i++) 00193 { 00194 c= getc(block ? osWaitForever : 0); 00195 if(c < 0) 00196 return i; // getc failed, but already got i bytes 00197 buffer[i]= (unsigned char)c; 00198 } 00199 00200 return length; // got all bytes 00201 } 00202 00203 00204 int SerialDriver::puts(const char * str, bool block) 00205 { 00206 // the same as write, but get length from strlen 00207 const int len= strlen(str); 00208 return write((const unsigned char *)str, len, block); 00209 } 00210 00211 int SerialDriver::printf(const char * format, ...) 00212 { 00213 // Parts of this are copied from mbed RawSerial ;) 00214 std::va_list arg; 00215 va_start(arg, format); 00216 00217 int length= vsnprintf(NULL, 0, format, arg); 00218 char *temp = new char[length + 1]; 00219 if(temp == NULL) 00220 return 0; // I can't work like this! 00221 00222 vsprintf(temp, format, arg); 00223 puts(temp, true); 00224 delete[] temp; 00225 00226 va_end(arg); 00227 return length; 00228 } 00229 00230 // still thinking of XTN 00231
Generated on Tue Jul 12 2022 15:12:29 by 1.7.2