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.
BufferedSerial.cpp
00001 /** 00002 * @file BufferedSerial.cpp 00003 * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX 00004 * @author sam grove 00005 * @version 1.0 00006 * @see 00007 * 00008 * Copyright (c) 2013 00009 * 00010 * Licensed under the Apache License, Version 2.0 (the "License"); 00011 * you may not use this file except in compliance with the License. 00012 * You may obtain a copy of the License at 00013 * 00014 * http://www.apache.org/licenses/LICENSE-2.0 00015 * 00016 * Unless required by applicable law or agreed to in writing, software 00017 * distributed under the License is distributed on an "AS IS" BASIS, 00018 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00019 * See the License for the specific language governing permissions and 00020 * limitations under the License. 00021 */ 00022 00023 #include "BufferedSerial.h" 00024 #include <stdarg.h> 00025 00026 BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name) 00027 : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size)) 00028 { 00029 RawSerial::attach(callback(this, &BufferedSerial::rxIrq), Serial::RxIrq); 00030 this->_buf_size = buf_size; 00031 this->_tx_multiple = tx_multiple; 00032 return; 00033 } 00034 00035 void BufferedSerial::attach(Callback<void()> func) 00036 { 00037 if(func) { 00038 this->_rx.attach(func); 00039 } 00040 } 00041 00042 BufferedSerial::~BufferedSerial(void) 00043 { 00044 RawSerial::attach(NULL, RawSerial::RxIrq); 00045 RawSerial::attach(NULL, RawSerial::TxIrq); 00046 00047 return; 00048 } 00049 00050 int BufferedSerial::readable(void) 00051 { 00052 return _rxbuf.available(); // note: look if things are in the buffer 00053 } 00054 00055 int BufferedSerial::writeable(void) 00056 { 00057 return 1; // buffer allows overwriting by design, always true 00058 } 00059 00060 int BufferedSerial::getc(void) 00061 { 00062 return _rxbuf; 00063 } 00064 00065 int BufferedSerial::putc(int c) 00066 { 00067 _txbuf = (char)c; 00068 BufferedSerial::prime(); 00069 00070 return c; 00071 } 00072 00073 int BufferedSerial::puts(const char *s) 00074 { 00075 if (s != NULL) { 00076 const char* ptr = s; 00077 00078 while(*(ptr) != 0) { 00079 _txbuf = *(ptr++); 00080 } 00081 _txbuf = '\n'; // done per puts definition 00082 BufferedSerial::prime(); 00083 00084 return (ptr - s) + 1; 00085 } 00086 return 0; 00087 } 00088 00089 int BufferedSerial::printf(const char* format, ...) 00090 { 00091 char buffer[this->_buf_size]; 00092 memset(buffer,0,this->_buf_size); 00093 int r = 0; 00094 00095 va_list arg; 00096 va_start(arg, format); 00097 r = vsprintf(buffer, format, arg); 00098 // this may not hit the heap but should alert the user anyways 00099 if(r > this->_buf_size) { 00100 error("%s %d buffer overwrite (max_buf_size: %d exceeded: %d)!\r\n", __FILE__, __LINE__,this->_buf_size,r); 00101 va_end(arg); 00102 return 0; 00103 } 00104 va_end(arg); 00105 r = BufferedSerial::write(buffer, r); 00106 00107 return r; 00108 } 00109 00110 ssize_t BufferedSerial::write(const void *s, size_t length) 00111 { 00112 if (s != NULL && length > 0) { 00113 const char* ptr = (const char*)s; 00114 const char* end = ptr + length; 00115 00116 while (ptr != end) { 00117 _txbuf = *(ptr++); 00118 } 00119 BufferedSerial::prime(); 00120 00121 return ptr - (const char*)s; 00122 } 00123 return 0; 00124 } 00125 00126 00127 void BufferedSerial::rxIrq(void) 00128 { 00129 // read from the peripheral and make sure something is available 00130 if(serial_readable(&_serial)) { 00131 _rxbuf = serial_getc(&_serial); // if so load them into a buffer 00132 _rx.call(); 00133 } 00134 00135 return; 00136 } 00137 00138 void BufferedSerial::txIrq(void) 00139 { 00140 // see if there is room in the hardware fifo and if something is in the software fifo 00141 while(serial_writable(&_serial)) { 00142 if(_txbuf.available()) { 00143 serial_putc(&_serial, (int)_txbuf.get()); 00144 } else { 00145 // disable the TX interrupt when there is nothing left to send 00146 RawSerial::attach(NULL, RawSerial::TxIrq); 00147 break; 00148 } 00149 } 00150 00151 return; 00152 } 00153 00154 void BufferedSerial::prime(void) 00155 { 00156 // if already busy then the irq will pick this up 00157 if(serial_writable(&_serial)) { 00158 RawSerial::attach(NULL, RawSerial::TxIrq); // make sure not to cause contention in the irq 00159 BufferedSerial::txIrq(); // only write to hardware in one place 00160 RawSerial::attach(callback(this, &BufferedSerial::txIrq), RawSerial::TxIrq); 00161 } 00162 00163 return; 00164 } 00165 00166
Generated on Mon Aug 15 2022 08:25:25 by
 1.7.2
 1.7.2