Asynchronous Serial Library with flow control and tag detection.
Embed:
(wiki syntax)
Show/hide line numbers
AsyncSerial.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2015 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #include "AsyncSerial/AsyncSerial.h" 00018 00019 #include "mbed.h" 00020 00021 #define MINIMUM_TIMEOUT 1 00022 00023 00024 AsyncSerial::AsyncSerial(PinName tx, PinName rx, PinName rts, PinName cts) 00025 : SerialBase(tx, rx), 00026 00027 sendBuffer(NULL), 00028 sendLength(0), 00029 sendIndex(0), 00030 00031 receiveBuffer(NULL), 00032 receiveMaxLength(0), 00033 receiveIndex(0), 00034 receiveStatus(AsyncSerial::RECEIVE_TIMEOUT), 00035 receiveResult(), 00036 timeout(), 00037 00038 insideCondition(false), 00039 conditionStartBuffer(NULL), 00040 conditionStartLength(0), 00041 conditionEndBuffer(NULL), 00042 conditionEndLength(0), 00043 conditionIndex(0), 00044 00045 sendHandler(), 00046 receiveHandler(), 00047 waitHandler() 00048 { 00049 #if DEVICE_SERIAL_FC 00050 if ((rts != NC) && (cts != NC)) 00051 { 00052 SerialBase::set_flow_control(SerialBase::RTSCTS, rts, cts); 00053 } 00054 #endif 00055 } 00056 00057 AsyncSerial::~AsyncSerial() 00058 { 00059 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); 00060 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq); 00061 } 00062 00063 /* Tx ISR 00064 */ 00065 void AsyncSerial::putDone() 00066 { 00067 // fill Tx buffers (in case the buffer can contain more than 1 byte) 00068 while(SerialBase::writeable()) 00069 { 00070 if(sendIndex < sendLength) 00071 { 00072 // send next character if there is still more to send 00073 SerialBase::_base_putc(sendBuffer[sendIndex]); 00074 00075 // sendIndex points to the next byte to send 00076 sendIndex++; 00077 } 00078 else 00079 { 00080 // disable the TX interrupt when there is nothing left to send 00081 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq); 00082 00083 // signal callback function 00084 sendHandler.call(); 00085 break; 00086 } 00087 } 00088 } 00089 00090 /* Rx ISR 00091 */ 00092 void AsyncSerial::getReady() 00093 { 00094 // read while there are characters in buffer 00095 while(SerialBase::readable()) 00096 { 00097 // read single character from buffer 00098 uint8_t input = SerialBase::_base_getc(); 00099 00100 DEBUG("%c", input); 00101 00102 // check if start condition has been met 00103 if (insideCondition) 00104 { 00105 /* If stop condition has been set, check if the 00106 character matches. If it does increment counter 00107 to point to next character in sequence. Otherwise 00108 reset sequence search. 00109 */ 00110 if (conditionEndBuffer != NULL) 00111 { 00112 if (input == conditionEndBuffer[conditionIndex]) 00113 { 00114 conditionIndex++; 00115 00116 /* End condition has been met. 00117 Set receive status to indicate sequence has been found 00118 and re-arm timer. The timeout is responsible for 00119 signaling the callback function and is useful for 00120 decoupling the callback from the receive ISR. 00121 */ 00122 if (conditionIndex == conditionEndLength) 00123 { 00124 // Disable Rx interrupt 00125 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); 00126 00127 // Fire timeout to signal callback 00128 receiveStatus = AsyncSerial::RECEIVE_FOUND; 00129 timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); 00130 break; 00131 } 00132 } 00133 else 00134 { 00135 // Character didn't match sequence. Start over. 00136 conditionIndex = 0; 00137 } 00138 } 00139 00140 /* A receive buffer is available. 00141 Store character in buffer and check if buffer is full, 00142 set receive status and re-arm timeout if it is. 00143 */ 00144 if (receiveBuffer != NULL) 00145 { 00146 receiveBuffer[receiveIndex] = input; 00147 receiveIndex++; 00148 00149 /* If end condition has been met we still store the character 00150 but we do not change the receive status nor re-arm the timer. 00151 */ 00152 if ((receiveIndex == receiveMaxLength) && (receiveStatus != AsyncSerial::RECEIVE_FOUND)) 00153 { 00154 // Disable Rx interrupt 00155 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); 00156 00157 // Fire timeout to signal callback 00158 receiveStatus = AsyncSerial::RECEIVE_FULL; 00159 timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, MINIMUM_TIMEOUT); 00160 break; 00161 } 00162 } 00163 } 00164 /* Start condition has not been met. 00165 */ 00166 else 00167 { 00168 if (conditionStartBuffer != NULL) 00169 { 00170 if (input == conditionStartBuffer[conditionIndex]) 00171 { 00172 conditionIndex++; 00173 00174 /* Set condition flag and reset index since it is reused. 00175 */ 00176 if (conditionIndex == conditionStartLength) 00177 { 00178 insideCondition = true; 00179 conditionIndex = 0; 00180 } 00181 } 00182 else 00183 { 00184 // Character didn't match sequence. Start over. 00185 conditionIndex = 0; 00186 } 00187 } 00188 } 00189 } 00190 } 00191 00192 /* Common function for signaling receive done handler or wait done handler. 00193 */ 00194 void AsyncSerial::getDone(uint8_t status) 00195 { 00196 DEBUG("getDone: %d\r\n", status); 00197 00198 /* Check whether to call the wait handler or the receive handler. 00199 */ 00200 if (receiveBuffer == NULL) 00201 { 00202 waitHandler.call(status); 00203 } 00204 else 00205 { 00206 receiveResult.buffer = receiveBuffer; 00207 receiveResult.length = receiveIndex; 00208 receiveResult.status = status; 00209 00210 receiveHandler.call(&receiveResult); 00211 } 00212 } 00213 00214 /* Send block of data. Function pointer interface. 00215 */ 00216 void AsyncSerial::send(send_done_t handler, const char* buffer, uint16_t length) 00217 { 00218 sendHandler.attach(handler); 00219 send(buffer, length); 00220 } 00221 00222 /* Common send block of data function. 00223 */ 00224 void AsyncSerial::send(const char* buffer, uint16_t length) 00225 { 00226 /* Signal callback function immediately if there is nothing to send. 00227 */ 00228 if ((buffer != NULL) && (length != 0)) 00229 { 00230 // Store book keeping variables 00231 sendBuffer = buffer; 00232 sendLength = length; 00233 sendIndex = 0; 00234 00235 if(SerialBase::writeable()) 00236 { 00237 // make sure not to cause contention in the irq 00238 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::TxIrq); 00239 00240 // only write to hardware in one place 00241 AsyncSerial::putDone(); 00242 00243 // enable TX interrupts 00244 SerialBase::attach<AsyncSerial>(this, &AsyncSerial::putDone, SerialBase::TxIrq); 00245 } 00246 00247 DEBUG("send: %p %d\r\n", buffer, length); 00248 } 00249 else 00250 { 00251 sendHandler.call(); 00252 } 00253 } 00254 00255 00256 /* Receiving block of data. Function pointer interface. 00257 */ 00258 void AsyncSerial::receive(receive_done_t _handler, 00259 uint8_t* _receiveBuffer, uint16_t _maxLength, 00260 const char* _conditionStartBuffer, uint16_t _conditionStartLength, 00261 const char* _conditionEndBuffer, uint16_t _conditionEndLength, 00262 uint32_t _timeoutMilli) 00263 { 00264 receiveHandler.attach(_handler); 00265 00266 /* Signal callback function immediately if buffer and maxLength are invalid. 00267 */ 00268 if ((_receiveBuffer == NULL) || (_maxLength == 0)) 00269 { 00270 receiveResult.buffer = NULL; 00271 receiveResult.length = 0; 00272 receiveResult.status = AsyncSerial::RECEIVE_FULL; 00273 00274 receiveHandler.call(&receiveResult); 00275 } 00276 else 00277 { 00278 receive(_receiveBuffer, _maxLength, 00279 _conditionStartBuffer, _conditionStartLength, 00280 _conditionEndBuffer, _conditionEndLength, 00281 _timeoutMilli); 00282 } 00283 } 00284 00285 /* Common receive function. 00286 */ 00287 void AsyncSerial::receive(uint8_t* _receiveBuffer, uint16_t _maxLength, 00288 const char* _conditionStartBuffer, uint16_t _conditionStartLength, 00289 const char* _conditionEndBuffer, uint16_t _conditionEndLength, 00290 uint32_t _timeoutMilli) 00291 { 00292 // Book keeping variables for reception 00293 receiveBuffer = _receiveBuffer; 00294 receiveMaxLength = _maxLength; 00295 receiveIndex = 0; 00296 receiveStatus = AsyncSerial::RECEIVE_TIMEOUT; 00297 00298 // Book keeping variables for conditions 00299 conditionStartBuffer = _conditionStartBuffer; 00300 conditionStartLength = _conditionStartLength; 00301 conditionEndBuffer = _conditionEndBuffer; 00302 conditionEndLength = _conditionEndLength; 00303 conditionIndex = 0; 00304 00305 // Check if optional start condition is set 00306 if ((_conditionStartBuffer != NULL) && (_conditionStartLength != 0)) 00307 { 00308 insideCondition = false; 00309 } 00310 else 00311 { 00312 insideCondition = true; 00313 } 00314 00315 // Arm timer 00316 timeout.attach_us<AsyncSerial>(this, &AsyncSerial::receiveTimeout, _timeoutMilli * 1000); 00317 00318 // Arm Rx interrupts and start receiving 00319 SerialBase::attach<AsyncSerial>(this, &AsyncSerial::getReady, SerialBase::RxIrq); 00320 00321 DEBUG("receive: %p\r\n", _receiveBuffer); 00322 } 00323 00324 /* Wait until timeout or sequence is detected. 00325 */ 00326 void AsyncSerial::wait(wait_done_t handler, 00327 const char* conditionEndBuffer, uint16_t conditionEndLength, 00328 uint32_t timeoutMilli) 00329 { 00330 waitHandler.attach(handler); 00331 00332 receive(NULL, 0, 00333 NULL, 0, 00334 conditionEndBuffer, conditionEndLength, 00335 timeoutMilli); 00336 } 00337 00338 /* Timeout fired. Call common receive done function. 00339 */ 00340 void AsyncSerial::receiveTimeout() 00341 { 00342 DEBUG("timeout\r\n"); 00343 00344 // Disable Rx interrupt (interrupts are not disabled if Rx timeouts) 00345 if (receiveStatus == AsyncSerial::RECEIVE_TIMEOUT) 00346 { 00347 SerialBase::attach<AsyncSerial>(NULL, NULL, SerialBase::RxIrq); 00348 } 00349 00350 getDone(receiveStatus); 00351 } 00352
Generated on Tue Jul 12 2022 18:48:23 by 1.7.2