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 extern "C" int BufferedPrintfC(void *stream, int size, const char* format, va_list arg); 00027 00028 BufferedSerial::BufferedSerial(PinName tx, PinName rx, uint32_t buf_size, uint32_t tx_multiple, const char* name) 00029 : RawSerial(tx, rx) , _rxbuf(buf_size), _txbuf((uint32_t)(tx_multiple*buf_size)) 00030 { 00031 RawSerial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq); 00032 this->_buf_size = buf_size; 00033 this->_tx_multiple = tx_multiple; 00034 return; 00035 } 00036 00037 BufferedSerial::~BufferedSerial(void) 00038 { 00039 RawSerial::attach(NULL, RawSerial::RxIrq); 00040 RawSerial::attach(NULL, RawSerial::TxIrq); 00041 00042 return; 00043 } 00044 00045 int BufferedSerial::readable(void) 00046 { 00047 return _rxbuf.available(); // note: look if things are in the buffer 00048 } 00049 00050 int BufferedSerial::writeable(void) 00051 { 00052 return 1; // buffer allows overwriting by design, always true 00053 } 00054 00055 int BufferedSerial::getc(void) 00056 { 00057 return _rxbuf; 00058 } 00059 00060 int BufferedSerial::putc(int c) 00061 { 00062 _txbuf = (char)c; 00063 BufferedSerial::prime(); 00064 00065 return c; 00066 } 00067 00068 int BufferedSerial::puts(const char *s) 00069 { 00070 if (s != NULL) { 00071 const char* ptr = s; 00072 00073 while(*(ptr) != 0) { 00074 _txbuf = *(ptr++); 00075 } 00076 _txbuf = '\n'; // done per puts definition 00077 BufferedSerial::prime(); 00078 00079 return (ptr - s) + 1; 00080 } 00081 return 0; 00082 } 00083 00084 extern "C" size_t BufferedSerialThunk(void *buf_serial, const void *s, size_t length) 00085 { 00086 BufferedSerial *buffered_serial = (BufferedSerial *)buf_serial; 00087 return buffered_serial->write(s, length); 00088 } 00089 00090 int BufferedSerial::printf(const char* format, ...) 00091 { 00092 va_list arg; 00093 va_start(arg, format); 00094 int r = BufferedPrintfC((void*)this, this->_buf_size, format, arg); 00095 va_end(arg); 00096 return r; 00097 } 00098 00099 ssize_t BufferedSerial::write(const void *s, size_t length) 00100 { 00101 if (s != NULL && length > 0) { 00102 const char* ptr = (const char*)s; 00103 const char* end = ptr + length; 00104 00105 while (ptr != end) { 00106 _txbuf = *(ptr++); 00107 } 00108 BufferedSerial::prime(); 00109 00110 return ptr - (const char*)s; 00111 } 00112 return 0; 00113 } 00114 00115 00116 void BufferedSerial::rxIrq(void) 00117 { 00118 // read from the peripheral and make sure something is available 00119 if(serial_readable(&_serial)) { 00120 _rxbuf = serial_getc(&_serial); // if so load them into a buffer 00121 // trigger callback if necessary 00122 if (_cbs[RxIrq]) { 00123 _cbs[RxIrq](); 00124 } 00125 } 00126 00127 return; 00128 } 00129 00130 void BufferedSerial::txIrq(void) 00131 { 00132 // see if there is room in the hardware fifo and if something is in the software fifo 00133 while(serial_writable(&_serial)) { 00134 if(_txbuf.available()) { 00135 serial_putc(&_serial, (int)_txbuf.get()); 00136 } else { 00137 // disable the TX interrupt when there is nothing left to send 00138 RawSerial::attach(NULL, RawSerial::TxIrq); 00139 // trigger callback if necessary 00140 if (_cbs[TxIrq]) { 00141 _cbs[TxIrq](); 00142 } 00143 break; 00144 } 00145 } 00146 00147 return; 00148 } 00149 00150 void BufferedSerial::prime(void) 00151 { 00152 // if already busy then the irq will pick this up 00153 if(serial_writable(&_serial)) { 00154 RawSerial::attach(NULL, RawSerial::TxIrq); // make sure not to cause contention in the irq 00155 BufferedSerial::txIrq(); // only write to hardware in one place 00156 RawSerial::attach(this, &BufferedSerial::txIrq, RawSerial::TxIrq); 00157 } 00158 00159 return; 00160 } 00161 00162 void BufferedSerial::attach(Callback<void()> func, IrqType type) 00163 { 00164 _cbs[type] = func; 00165 } 00166
Generated on Tue Jul 12 2022 15:14:29 by
