Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of SerialDriver by
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 : SerialBase(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 00047 int SerialDriver::putc(int c, unsigned int timeoutMs) 00048 { 00049 // critical section, isr could modify cursors 00050 disableTxInterrupt(); 00051 00052 if(isTxBufferFull()) 00053 { 00054 // wait for free space 00055 while(semTxBufferFull.wait(0) > 0); // clear semaphore 00056 enableTxInterrupt(); 00057 00058 // let isr work 00059 semTxBufferFull.wait(timeoutMs); 00060 00061 disableTxInterrupt(); 00062 if(isTxBufferFull()) // still full? drop byte! 00063 { 00064 numTxDrops++; 00065 enableTxInterrupt(); 00066 return 0; 00067 } 00068 } 00069 00070 // write this byte to tx buffer 00071 txBuffer[txIn]= (unsigned char)c; 00072 txIn= (txIn+1) % txBufferLength; 00073 txCount++; 00074 00075 // its over, isr can come 00076 enableTxInterrupt(); 00077 00078 // Let's write (isr will check writeability itself) 00079 onTxIrq(); 00080 00081 return 1; 00082 } 00083 00084 void SerialDriver::onTxIrq() 00085 { 00086 // prevent fire another TxIrq now 00087 disableTxInterrupt(); 00088 00089 // write as long as you can 00090 bool wasFull= isTxBufferFull(); 00091 while(SerialBase::writeable() && !isTxBufferEmtpy()) 00092 { 00093 // take byte from tx buffer and put it out 00094 SerialBase::_base_putc(txBuffer[txOut]); 00095 txOut= (txOut+1) % txBufferLength; 00096 txCount--; 00097 } 00098 00099 if(wasFull && !isTxBufferFull()) // more bytes can come 00100 semTxBufferFull.release(); 00101 00102 // ok, let's wait for next writability 00103 enableTxInterrupt(); 00104 } 00105 00106 00107 int SerialDriver::getc(unsigned int timeoutMs) 00108 { 00109 // Let's read (isr will check readability itself) 00110 onRxIrq(); 00111 00112 // critical section, isr could modify cursors 00113 disableRxInterrupt(); 00114 00115 if(isRxBufferEmpty()) 00116 { 00117 // wait for new byte 00118 while(semRxBufferEmpty.wait(0) > 0); // clear semaphore 00119 enableRxInterrupt(); 00120 00121 // let isr work 00122 semRxBufferEmpty.wait(timeoutMs); 00123 00124 disableRxInterrupt(); 00125 if(isRxBufferEmpty()) // still empty? nothing received! 00126 { 00127 enableRxInterrupt(); 00128 return -1; 00129 } 00130 } 00131 00132 // get byte from rx buffer 00133 int c= (int)rxBuffer[rxOut]; 00134 rxOut= (rxOut+1) % rxBufferLength; 00135 rxCount--; 00136 00137 // its over, isr can come 00138 enableRxInterrupt(); 00139 00140 return c; 00141 } 00142 00143 void SerialDriver::onRxIrq() 00144 { 00145 // prevent fire another RxIrq now 00146 disableRxInterrupt(); 00147 00148 // read as long as you can 00149 bool wasEmpty= isRxBufferEmpty(); 00150 while(SerialBase::readable()) 00151 { 00152 // get byte and store it to the RX buffer 00153 int c= SerialBase::_base_getc(); 00154 if(!isRxBufferFull()) 00155 { 00156 rxBuffer[rxIn]= (unsigned char)c; 00157 rxIn= (rxIn+1) % rxBufferLength; 00158 rxCount++; 00159 if ('\n' == c) { 00160 _callback_auto_detect.call(); 00161 } 00162 } 00163 else { // drop byte :( 00164 numRxDrops++; 00165 _callback_rx_overflow.call(); 00166 } 00167 } 00168 00169 if(wasEmpty && !isRxBufferEmpty()) // more bytes can go 00170 semRxBufferEmpty.release(); 00171 00172 // ok, let's wait for next readability 00173 enableRxInterrupt(); 00174 } 00175 00176 00177 int SerialDriver::write(const unsigned char * buffer, const unsigned int length, bool block) 00178 { 00179 // try to put all bytes 00180 for(int i= 0; i < length; i++) 00181 if(!putc(buffer[i], block ? osWaitForever : 0)) 00182 return i; // putc failed, but already put i bytes 00183 00184 return length; // put all bytes 00185 } 00186 00187 int SerialDriver::read(unsigned char * buffer, const unsigned int length, bool block) 00188 { 00189 // try to get all bytes 00190 int c; 00191 for(int i= 0; i < length; i++) 00192 { 00193 c= getc(block ? osWaitForever : 0); 00194 if(c < 0) 00195 return i; // getc failed, but already got i bytes 00196 buffer[i]= (unsigned char)c; 00197 } 00198 00199 return length; // got all bytes 00200 } 00201 00202 00203 int SerialDriver::puts(const char * str, bool block) 00204 { 00205 // the same as write, but get length from strlen 00206 const int len= strlen(str); 00207 return write((const unsigned char *)str, len, block); 00208 } 00209 00210 int SerialDriver::printf(const char * format, ...) 00211 { 00212 // Parts of this are copied from mbed RawSerial ;) 00213 std::va_list arg; 00214 va_start(arg, format); 00215 00216 int length= vsnprintf(NULL, 0, format, arg); 00217 char *temp = new char[length + 1]; 00218 vsprintf(temp, format, arg); 00219 puts(temp, true); 00220 delete[] temp; 00221 00222 va_end(arg); 00223 return length; 00224 } 00225 00226 // still thinking of XTN
Generated on Sat Jul 16 2022 05:44:44 by
1.7.2
