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 gr-peach-opencv-project-sd-card by
UARTSerial.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2017 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 #if DEVICE_SERIAL 00018 00019 #include <errno.h> 00020 #include "UARTSerial.h" 00021 #include "platform/mbed_poll.h" 00022 #include "platform/mbed_wait_api.h" 00023 00024 namespace mbed { 00025 00026 UARTSerial::UARTSerial(PinName tx, PinName rx, int baud) : 00027 SerialBase(tx, rx, baud), 00028 _blocking(true), 00029 _tx_irq_enabled(false), 00030 _dcd_irq(NULL) 00031 { 00032 /* Attatch IRQ routines to the serial device. */ 00033 SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq); 00034 } 00035 00036 UARTSerial::~UARTSerial() 00037 { 00038 delete _dcd_irq; 00039 } 00040 00041 void UARTSerial::dcd_irq() 00042 { 00043 wake(); 00044 } 00045 00046 void UARTSerial::set_data_carrier_detect(PinName dcd_pin, bool active_high) 00047 { 00048 delete _dcd_irq; 00049 _dcd_irq = NULL; 00050 00051 if (dcd_pin != NC) { 00052 _dcd_irq = new InterruptIn(dcd_pin); 00053 if (active_high) { 00054 _dcd_irq->fall(callback(this, &UARTSerial::dcd_irq)); 00055 } else { 00056 _dcd_irq->rise(callback(this, &UARTSerial::dcd_irq)); 00057 } 00058 } 00059 } 00060 00061 int UARTSerial::close() 00062 { 00063 /* Does not let us pass a file descriptor. So how to close ? 00064 * Also, does it make sense to close a device type file descriptor*/ 00065 return 0; 00066 } 00067 00068 int UARTSerial::isatty() 00069 { 00070 return 1; 00071 00072 } 00073 00074 off_t UARTSerial::seek(off_t offset, int whence) 00075 { 00076 /*XXX lseek can be done theoratically, but is it sane to mark positions on a dynamically growing/shrinking 00077 * buffer system (from an interrupt context) */ 00078 return -ESPIPE; 00079 } 00080 00081 int UARTSerial::sync() 00082 { 00083 lock(); 00084 00085 while (!_txbuf.empty()) { 00086 unlock(); 00087 // Doing better than wait would require TxIRQ to also do wake() when becoming empty. Worth it? 00088 wait_ms(1); 00089 lock(); 00090 } 00091 00092 unlock(); 00093 00094 return 0; 00095 } 00096 00097 void UARTSerial::sigio(Callback<void()> func) { 00098 core_util_critical_section_enter(); 00099 _sigio_cb = func; 00100 if (_sigio_cb) { 00101 short current_events = poll(0x7FFF); 00102 if (current_events) { 00103 _sigio_cb(); 00104 } 00105 } 00106 core_util_critical_section_exit(); 00107 } 00108 00109 ssize_t UARTSerial::write(const void* buffer, size_t length) 00110 { 00111 size_t data_written = 0; 00112 const char *buf_ptr = static_cast<const char *>(buffer); 00113 00114 lock(); 00115 00116 while (_txbuf.full()) { 00117 if (!_blocking) { 00118 unlock(); 00119 return -EAGAIN; 00120 } 00121 unlock(); 00122 wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ? 00123 lock(); 00124 } 00125 00126 while (data_written < length && !_txbuf.full()) { 00127 _txbuf.push(*buf_ptr++); 00128 data_written++; 00129 } 00130 00131 core_util_critical_section_enter(); 00132 if (!_tx_irq_enabled) { 00133 UARTSerial::tx_irq(); // only write to hardware in one place 00134 if (!_txbuf.empty()) { 00135 SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq); 00136 _tx_irq_enabled = true; 00137 } 00138 } 00139 core_util_critical_section_exit(); 00140 00141 unlock(); 00142 00143 return data_written; 00144 } 00145 00146 ssize_t UARTSerial::read(void* buffer, size_t length) 00147 { 00148 size_t data_read = 0; 00149 00150 char *ptr = static_cast<char *>(buffer); 00151 00152 lock(); 00153 00154 while (_rxbuf.empty()) { 00155 if (!_blocking) { 00156 unlock(); 00157 return -EAGAIN; 00158 } 00159 unlock(); 00160 wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ? 00161 lock(); 00162 } 00163 00164 while (data_read < length && !_rxbuf.empty()) { 00165 _rxbuf.pop(*ptr++); 00166 data_read++; 00167 } 00168 00169 unlock(); 00170 00171 return data_read; 00172 } 00173 00174 bool UARTSerial::hup() const 00175 { 00176 return _dcd_irq && _dcd_irq->read() != 0; 00177 } 00178 00179 void UARTSerial::wake() 00180 { 00181 if (_sigio_cb) { 00182 _sigio_cb(); 00183 } 00184 } 00185 00186 short UARTSerial::poll(short events) const { 00187 00188 short revents = 0; 00189 /* Check the Circular Buffer if space available for writing out */ 00190 00191 00192 if (!_rxbuf.empty()) { 00193 revents |= POLLIN; 00194 } 00195 00196 /* POLLHUP and POLLOUT are mutually exclusive */ 00197 if (hup()) { 00198 revents |= POLLHUP; 00199 } else if (!_txbuf.full()) { 00200 revents |= POLLOUT; 00201 } 00202 00203 /*TODO Handle other event types */ 00204 00205 return revents; 00206 } 00207 00208 void UARTSerial::lock(void) 00209 { 00210 _mutex.lock(); 00211 } 00212 00213 void UARTSerial::unlock(void) 00214 { 00215 _mutex.unlock(); 00216 } 00217 00218 void UARTSerial::rx_irq(void) 00219 { 00220 bool was_empty = _rxbuf.empty(); 00221 00222 /* Fill in the receive buffer if the peripheral is readable 00223 * and receive buffer is not full. */ 00224 while (SerialBase::readable()) { 00225 char data = SerialBase::_base_getc(); 00226 if (!_rxbuf.full()) { 00227 _rxbuf.push(data); 00228 } else { 00229 /* Drop - can we report in some way? */ 00230 } 00231 } 00232 00233 /* Report the File handler that data is ready to be read from the buffer. */ 00234 if (was_empty && !_rxbuf.empty()) { 00235 wake(); 00236 } 00237 } 00238 00239 // Also called from write to start transfer 00240 void UARTSerial::tx_irq(void) 00241 { 00242 bool was_full = _txbuf.full(); 00243 00244 /* Write to the peripheral if there is something to write 00245 * and if the peripheral is available to write. */ 00246 while (!_txbuf.empty() && SerialBase::writeable()) { 00247 char data; 00248 _txbuf.pop(data); 00249 SerialBase::_base_putc(data); 00250 } 00251 00252 if (_tx_irq_enabled && _txbuf.empty()) { 00253 SerialBase::attach(NULL, TxIrq); 00254 _tx_irq_enabled = false; 00255 } 00256 00257 /* Report the File handler that data can be written to peripheral. */ 00258 if (was_full && !_txbuf.full() && !hup()) { 00259 wake(); 00260 } 00261 } 00262 00263 } //namespace mbed 00264 00265 #endif //DEVICE_SERIAL 00266
Generated on Tue Jul 12 2022 14:47:44 by
1.7.2
