Renesas GR-PEACH OpenCV Development / gr-peach-opencv-project-sd-card_update

Fork of gr-peach-opencv-project-sd-card by the do

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers UARTSerial.cpp Source File

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