Jonathan Cacace / RoboClaw
Committer:
anfontanelli
Date:
Wed Nov 06 10:57:21 2019 +0000
Revision:
11:04d8899b5d82
Child:
12:b423b3cbec47
Classe hyfliers

Who changed what in which revision?

UserRevisionLine numberNew contents of line
anfontanelli 11:04d8899b5d82 1 /* mbed Microcontroller Library
anfontanelli 11:04d8899b5d82 2 * Copyright (c) 2006-2017 ARM Limited
anfontanelli 11:04d8899b5d82 3 * SPDX-License-Identifier: Apache-2.0
anfontanelli 11:04d8899b5d82 4 *
anfontanelli 11:04d8899b5d82 5 * Licensed under the Apache License, Version 2.0 (the "License");
anfontanelli 11:04d8899b5d82 6 * you may not use this file except in compliance with the License.
anfontanelli 11:04d8899b5d82 7 * You may obtain a copy of the License at
anfontanelli 11:04d8899b5d82 8 *
anfontanelli 11:04d8899b5d82 9 * http://www.apache.org/licenses/LICENSE-2.0
anfontanelli 11:04d8899b5d82 10 *
anfontanelli 11:04d8899b5d82 11 * Unless required by applicable law or agreed to in writing, software
anfontanelli 11:04d8899b5d82 12 * distributed under the License is distributed on an "AS IS" BASIS,
anfontanelli 11:04d8899b5d82 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
anfontanelli 11:04d8899b5d82 14 * See the License for the specific language governing permissions and
anfontanelli 11:04d8899b5d82 15 * limitations under the License.
anfontanelli 11:04d8899b5d82 16 */
anfontanelli 11:04d8899b5d82 17 #include "UARTSerial_mio.h"
anfontanelli 11:04d8899b5d82 18
anfontanelli 11:04d8899b5d82 19 #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN)
anfontanelli 11:04d8899b5d82 20
anfontanelli 11:04d8899b5d82 21 #include "platform/mbed_poll.h"
anfontanelli 11:04d8899b5d82 22
anfontanelli 11:04d8899b5d82 23 #if MBED_CONF_RTOS_PRESENT
anfontanelli 11:04d8899b5d82 24 #include "rtos/ThisThread.h"
anfontanelli 11:04d8899b5d82 25 #else
anfontanelli 11:04d8899b5d82 26 #include "platform/mbed_wait_api.h"
anfontanelli 11:04d8899b5d82 27 #endif
anfontanelli 11:04d8899b5d82 28
anfontanelli 11:04d8899b5d82 29 namespace mbed {
anfontanelli 11:04d8899b5d82 30
anfontanelli 11:04d8899b5d82 31 UARTSerial_mio::UARTSerial_mio(PinName tx, PinName rx, int baud) :
anfontanelli 11:04d8899b5d82 32 SerialBase(tx, rx, baud),
anfontanelli 11:04d8899b5d82 33 _blocking(true),
anfontanelli 11:04d8899b5d82 34 _tx_irq_enabled(false),
anfontanelli 11:04d8899b5d82 35 _rx_irq_enabled(false),
anfontanelli 11:04d8899b5d82 36 _tx_enabled(true),
anfontanelli 11:04d8899b5d82 37 _rx_enabled(true),
anfontanelli 11:04d8899b5d82 38 _dcd_irq(NULL)
anfontanelli 11:04d8899b5d82 39 {
anfontanelli 11:04d8899b5d82 40 /* Attatch IRQ routines to the serial device. */
anfontanelli 11:04d8899b5d82 41 enable_rx_irq();
anfontanelli 11:04d8899b5d82 42 }
anfontanelli 11:04d8899b5d82 43
anfontanelli 11:04d8899b5d82 44 UARTSerial_mio::~UARTSerial_mio()
anfontanelli 11:04d8899b5d82 45 {
anfontanelli 11:04d8899b5d82 46 delete _dcd_irq;
anfontanelli 11:04d8899b5d82 47 }
anfontanelli 11:04d8899b5d82 48
anfontanelli 11:04d8899b5d82 49 void UARTSerial_mio::dcd_irq()
anfontanelli 11:04d8899b5d82 50 {
anfontanelli 11:04d8899b5d82 51 wake();
anfontanelli 11:04d8899b5d82 52 }
anfontanelli 11:04d8899b5d82 53
anfontanelli 11:04d8899b5d82 54 void UARTSerial_mio::set_baud(int baud)
anfontanelli 11:04d8899b5d82 55 {
anfontanelli 11:04d8899b5d82 56 SerialBase::baud(baud);
anfontanelli 11:04d8899b5d82 57 }
anfontanelli 11:04d8899b5d82 58
anfontanelli 11:04d8899b5d82 59 void UARTSerial_mio::set_format(int bits, Parity parity, int stop_bits)
anfontanelli 11:04d8899b5d82 60 {
anfontanelli 11:04d8899b5d82 61 api_lock();
anfontanelli 11:04d8899b5d82 62 SerialBase::format(bits, parity, stop_bits);
anfontanelli 11:04d8899b5d82 63 api_unlock();
anfontanelli 11:04d8899b5d82 64 }
anfontanelli 11:04d8899b5d82 65
anfontanelli 11:04d8899b5d82 66 #if DEVICE_SERIAL_FC
anfontanelli 11:04d8899b5d82 67 void UARTSerial_mio::set_flow_control(Flow type, PinName flow1, PinName flow2)
anfontanelli 11:04d8899b5d82 68 {
anfontanelli 11:04d8899b5d82 69 api_lock();
anfontanelli 11:04d8899b5d82 70 SerialBase::set_flow_control(type, flow1, flow2);
anfontanelli 11:04d8899b5d82 71 api_unlock();
anfontanelli 11:04d8899b5d82 72 }
anfontanelli 11:04d8899b5d82 73 #endif
anfontanelli 11:04d8899b5d82 74
anfontanelli 11:04d8899b5d82 75 int UARTSerial_mio::close(){return 0;}
anfontanelli 11:04d8899b5d82 76
anfontanelli 11:04d8899b5d82 77 int UARTSerial_mio::isatty(){return 1;}
anfontanelli 11:04d8899b5d82 78
anfontanelli 11:04d8899b5d82 79
anfontanelli 11:04d8899b5d82 80 off_t UARTSerial_mio::seek(off_t offset, int whence)
anfontanelli 11:04d8899b5d82 81 {
anfontanelli 11:04d8899b5d82 82 /*XXX lseek can be done theoratically, but is it sane to mark positions on a dynamically growing/shrinking
anfontanelli 11:04d8899b5d82 83 * buffer system (from an interrupt context) */
anfontanelli 11:04d8899b5d82 84 return -ESPIPE;
anfontanelli 11:04d8899b5d82 85 }
anfontanelli 11:04d8899b5d82 86
anfontanelli 11:04d8899b5d82 87 int UARTSerial_mio::sync()
anfontanelli 11:04d8899b5d82 88 {
anfontanelli 11:04d8899b5d82 89 api_lock();
anfontanelli 11:04d8899b5d82 90 while (!_txbuf.empty()) {
anfontanelli 11:04d8899b5d82 91 api_unlock();
anfontanelli 11:04d8899b5d82 92 // Doing better than wait would require TxIRQ to also do wake() when becoming empty. Worth it?
anfontanelli 11:04d8899b5d82 93 wait_us(500);
anfontanelli 11:04d8899b5d82 94 api_lock();
anfontanelli 11:04d8899b5d82 95 }
anfontanelli 11:04d8899b5d82 96
anfontanelli 11:04d8899b5d82 97 api_unlock();
anfontanelli 11:04d8899b5d82 98
anfontanelli 11:04d8899b5d82 99 return 0;
anfontanelli 11:04d8899b5d82 100 }
anfontanelli 11:04d8899b5d82 101
anfontanelli 11:04d8899b5d82 102 int UARTSerial_mio::flush()
anfontanelli 11:04d8899b5d82 103 {
anfontanelli 11:04d8899b5d82 104 api_lock();
anfontanelli 11:04d8899b5d82 105 char c;
anfontanelli 11:04d8899b5d82 106
anfontanelli 11:04d8899b5d82 107 while (!_rxbuf.empty()) {
anfontanelli 11:04d8899b5d82 108 api_unlock();
anfontanelli 11:04d8899b5d82 109 // Doing better than wait would require TxIRQ to also do wake() when becoming empty. Worth it?
anfontanelli 11:04d8899b5d82 110 wait_us(500);
anfontanelli 11:04d8899b5d82 111 _rxbuf.pop(c);
anfontanelli 11:04d8899b5d82 112 api_lock();
anfontanelli 11:04d8899b5d82 113 }
anfontanelli 11:04d8899b5d82 114
anfontanelli 11:04d8899b5d82 115 api_unlock();
anfontanelli 11:04d8899b5d82 116
anfontanelli 11:04d8899b5d82 117 return 0;
anfontanelli 11:04d8899b5d82 118 }
anfontanelli 11:04d8899b5d82 119
anfontanelli 11:04d8899b5d82 120 void UARTSerial_mio::sigio(Callback<void()> func)
anfontanelli 11:04d8899b5d82 121 {
anfontanelli 11:04d8899b5d82 122 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 123 _sigio_cb = func;
anfontanelli 11:04d8899b5d82 124 if (_sigio_cb) {
anfontanelli 11:04d8899b5d82 125 short current_events = poll(0x7FFF);
anfontanelli 11:04d8899b5d82 126 if (current_events) {
anfontanelli 11:04d8899b5d82 127 _sigio_cb();
anfontanelli 11:04d8899b5d82 128 }
anfontanelli 11:04d8899b5d82 129 }
anfontanelli 11:04d8899b5d82 130 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 131 }
anfontanelli 11:04d8899b5d82 132
anfontanelli 11:04d8899b5d82 133 /* Special synchronous write designed to work from critical section, such
anfontanelli 11:04d8899b5d82 134 * as in mbed_error_vprintf.
anfontanelli 11:04d8899b5d82 135 */
anfontanelli 11:04d8899b5d82 136 ssize_t UARTSerial_mio::write_unbuffered(const char *buf_ptr, size_t length)
anfontanelli 11:04d8899b5d82 137 {
anfontanelli 11:04d8899b5d82 138 while (!_txbuf.empty()) {
anfontanelli 11:04d8899b5d82 139 tx_irq();
anfontanelli 11:04d8899b5d82 140 }
anfontanelli 11:04d8899b5d82 141
anfontanelli 11:04d8899b5d82 142 for (size_t data_written = 0; data_written < length; data_written++) {
anfontanelli 11:04d8899b5d82 143 SerialBase::_base_putc(*buf_ptr++);
anfontanelli 11:04d8899b5d82 144 }
anfontanelli 11:04d8899b5d82 145
anfontanelli 11:04d8899b5d82 146 return length;
anfontanelli 11:04d8899b5d82 147 }
anfontanelli 11:04d8899b5d82 148
anfontanelli 11:04d8899b5d82 149 ssize_t UARTSerial_mio::write(const void *buffer, size_t length)
anfontanelli 11:04d8899b5d82 150 {
anfontanelli 11:04d8899b5d82 151 size_t data_written = 0;
anfontanelli 11:04d8899b5d82 152 const char *buf_ptr = static_cast<const char *>(buffer);
anfontanelli 11:04d8899b5d82 153
anfontanelli 11:04d8899b5d82 154 if (length == 0) {
anfontanelli 11:04d8899b5d82 155 return 0;
anfontanelli 11:04d8899b5d82 156 }
anfontanelli 11:04d8899b5d82 157
anfontanelli 11:04d8899b5d82 158 if (core_util_in_critical_section()) {
anfontanelli 11:04d8899b5d82 159 return write_unbuffered(buf_ptr, length);
anfontanelli 11:04d8899b5d82 160 }
anfontanelli 11:04d8899b5d82 161
anfontanelli 11:04d8899b5d82 162 api_lock();
anfontanelli 11:04d8899b5d82 163
anfontanelli 11:04d8899b5d82 164 // Unlike read, we should write the whole thing if blocking. POSIX only
anfontanelli 11:04d8899b5d82 165 // allows partial as a side-effect of signal handling; it normally tries to
anfontanelli 11:04d8899b5d82 166 // write everything if blocking. Without signals we can always write all.
anfontanelli 11:04d8899b5d82 167 while (data_written < length) {
anfontanelli 11:04d8899b5d82 168
anfontanelli 11:04d8899b5d82 169 if (_txbuf.full()) {
anfontanelli 11:04d8899b5d82 170 if (!_blocking) {
anfontanelli 11:04d8899b5d82 171 break;
anfontanelli 11:04d8899b5d82 172 }
anfontanelli 11:04d8899b5d82 173 do {
anfontanelli 11:04d8899b5d82 174 api_unlock();
anfontanelli 11:04d8899b5d82 175 wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
anfontanelli 11:04d8899b5d82 176 api_lock();
anfontanelli 11:04d8899b5d82 177 } while (_txbuf.full());
anfontanelli 11:04d8899b5d82 178 }
anfontanelli 11:04d8899b5d82 179
anfontanelli 11:04d8899b5d82 180 while (data_written < length && !_txbuf.full()) {
anfontanelli 11:04d8899b5d82 181 _txbuf.push(*buf_ptr++);
anfontanelli 11:04d8899b5d82 182 data_written++;
anfontanelli 11:04d8899b5d82 183 }
anfontanelli 11:04d8899b5d82 184
anfontanelli 11:04d8899b5d82 185 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 186 if (_tx_enabled && !_tx_irq_enabled) {
anfontanelli 11:04d8899b5d82 187 UARTSerial_mio::tx_irq(); // only write to hardware in one place
anfontanelli 11:04d8899b5d82 188 if (!_txbuf.empty()) {
anfontanelli 11:04d8899b5d82 189 enable_tx_irq();
anfontanelli 11:04d8899b5d82 190 }
anfontanelli 11:04d8899b5d82 191 }
anfontanelli 11:04d8899b5d82 192 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 193 }
anfontanelli 11:04d8899b5d82 194
anfontanelli 11:04d8899b5d82 195 api_unlock();
anfontanelli 11:04d8899b5d82 196
anfontanelli 11:04d8899b5d82 197 return data_written != 0 ? (ssize_t) data_written : (ssize_t) - EAGAIN;
anfontanelli 11:04d8899b5d82 198 }
anfontanelli 11:04d8899b5d82 199
anfontanelli 11:04d8899b5d82 200 ssize_t UARTSerial_mio::read(void *buffer, size_t length)
anfontanelli 11:04d8899b5d82 201 {
anfontanelli 11:04d8899b5d82 202 size_t data_read = 0;
anfontanelli 11:04d8899b5d82 203
anfontanelli 11:04d8899b5d82 204 float timeout = 1.0; //ms
anfontanelli 11:04d8899b5d82 205 float tm = 0.0;
anfontanelli 11:04d8899b5d82 206
anfontanelli 11:04d8899b5d82 207 char *ptr = static_cast<char *>(buffer);
anfontanelli 11:04d8899b5d82 208
anfontanelli 11:04d8899b5d82 209 if (length == 0) {
anfontanelli 11:04d8899b5d82 210 return 0;
anfontanelli 11:04d8899b5d82 211 }
anfontanelli 11:04d8899b5d82 212
anfontanelli 11:04d8899b5d82 213 api_lock();
anfontanelli 11:04d8899b5d82 214
anfontanelli 11:04d8899b5d82 215 while (_rxbuf.size()!=length && tm <= timeout) {
anfontanelli 11:04d8899b5d82 216 if (!_blocking) {
anfontanelli 11:04d8899b5d82 217 api_unlock();
anfontanelli 11:04d8899b5d82 218 return -EAGAIN;
anfontanelli 11:04d8899b5d82 219 }
anfontanelli 11:04d8899b5d82 220 api_unlock();
anfontanelli 11:04d8899b5d82 221 wait_us(10); // XXX todo - proper wait, WFE for non-rtos ?
anfontanelli 11:04d8899b5d82 222 api_lock();
anfontanelli 11:04d8899b5d82 223 tm = tm + 0.01; //10/1000
anfontanelli 11:04d8899b5d82 224 }
anfontanelli 11:04d8899b5d82 225
anfontanelli 11:04d8899b5d82 226 while (data_read < length && !_rxbuf.empty()) {
anfontanelli 11:04d8899b5d82 227 _rxbuf.pop(*ptr++);
anfontanelli 11:04d8899b5d82 228 data_read++;
anfontanelli 11:04d8899b5d82 229 }
anfontanelli 11:04d8899b5d82 230
anfontanelli 11:04d8899b5d82 231 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 232 if (_rx_enabled && !_rx_irq_enabled) {
anfontanelli 11:04d8899b5d82 233 UARTSerial_mio::rx_irq(); // only read from hardware in one place
anfontanelli 11:04d8899b5d82 234 if (!_rxbuf.full()) {
anfontanelli 11:04d8899b5d82 235 enable_rx_irq();
anfontanelli 11:04d8899b5d82 236 }
anfontanelli 11:04d8899b5d82 237 }
anfontanelli 11:04d8899b5d82 238 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 239
anfontanelli 11:04d8899b5d82 240 api_unlock();
anfontanelli 11:04d8899b5d82 241
anfontanelli 11:04d8899b5d82 242 return data_read;
anfontanelli 11:04d8899b5d82 243 }
anfontanelli 11:04d8899b5d82 244
anfontanelli 11:04d8899b5d82 245 ssize_t UARTSerial_mio::read_timeout(void *buffer, size_t length, double _timeOut)
anfontanelli 11:04d8899b5d82 246 {
anfontanelli 11:04d8899b5d82 247 size_t data_read = 0;
anfontanelli 11:04d8899b5d82 248
anfontanelli 11:04d8899b5d82 249 double timeout = _timeOut; //ms
anfontanelli 11:04d8899b5d82 250 double tm = 0.0;
anfontanelli 11:04d8899b5d82 251
anfontanelli 11:04d8899b5d82 252 char *ptr = static_cast<char *>(buffer);
anfontanelli 11:04d8899b5d82 253
anfontanelli 11:04d8899b5d82 254 if (length == 0) {
anfontanelli 11:04d8899b5d82 255 return 0;
anfontanelli 11:04d8899b5d82 256 }
anfontanelli 11:04d8899b5d82 257
anfontanelli 11:04d8899b5d82 258 api_lock();
anfontanelli 11:04d8899b5d82 259
anfontanelli 11:04d8899b5d82 260 while (_rxbuf.size()!=length) {
anfontanelli 11:04d8899b5d82 261 if (!_blocking) {
anfontanelli 11:04d8899b5d82 262 api_unlock();
anfontanelli 11:04d8899b5d82 263 return -EAGAIN;
anfontanelli 11:04d8899b5d82 264 }
anfontanelli 11:04d8899b5d82 265 api_unlock();
anfontanelli 11:04d8899b5d82 266 wait_us(1); // XXX todo - proper wait, WFE for non-rtos ?
anfontanelli 11:04d8899b5d82 267 api_lock();
anfontanelli 11:04d8899b5d82 268 tm = tm + 0.001; //10/1000
anfontanelli 11:04d8899b5d82 269
anfontanelli 11:04d8899b5d82 270 }
anfontanelli 11:04d8899b5d82 271
anfontanelli 11:04d8899b5d82 272 //printf("tm: %f\r\n",tm);
anfontanelli 11:04d8899b5d82 273
anfontanelli 11:04d8899b5d82 274 while (data_read < length && !_rxbuf.empty()) {
anfontanelli 11:04d8899b5d82 275 _rxbuf.pop(*ptr++);
anfontanelli 11:04d8899b5d82 276 data_read++;
anfontanelli 11:04d8899b5d82 277 }
anfontanelli 11:04d8899b5d82 278
anfontanelli 11:04d8899b5d82 279 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 280 if (_rx_enabled && !_rx_irq_enabled) {
anfontanelli 11:04d8899b5d82 281 UARTSerial_mio::rx_irq(); // only read from hardware in one place
anfontanelli 11:04d8899b5d82 282 if (!_rxbuf.full()) {
anfontanelli 11:04d8899b5d82 283 enable_rx_irq();
anfontanelli 11:04d8899b5d82 284 }
anfontanelli 11:04d8899b5d82 285 }
anfontanelli 11:04d8899b5d82 286 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 287
anfontanelli 11:04d8899b5d82 288 api_unlock();
anfontanelli 11:04d8899b5d82 289
anfontanelli 11:04d8899b5d82 290 return data_read;
anfontanelli 11:04d8899b5d82 291 }
anfontanelli 11:04d8899b5d82 292
anfontanelli 11:04d8899b5d82 293 bool UARTSerial_mio::hup() const
anfontanelli 11:04d8899b5d82 294 {
anfontanelli 11:04d8899b5d82 295 return _dcd_irq && _dcd_irq->read() != 0;
anfontanelli 11:04d8899b5d82 296 }
anfontanelli 11:04d8899b5d82 297
anfontanelli 11:04d8899b5d82 298 void UARTSerial_mio::wake()
anfontanelli 11:04d8899b5d82 299 {
anfontanelli 11:04d8899b5d82 300 if (_sigio_cb) {
anfontanelli 11:04d8899b5d82 301 _sigio_cb();
anfontanelli 11:04d8899b5d82 302 }
anfontanelli 11:04d8899b5d82 303 }
anfontanelli 11:04d8899b5d82 304
anfontanelli 11:04d8899b5d82 305 short UARTSerial_mio::poll(short events) const
anfontanelli 11:04d8899b5d82 306 {
anfontanelli 11:04d8899b5d82 307
anfontanelli 11:04d8899b5d82 308 short revents = 0;
anfontanelli 11:04d8899b5d82 309 /* Check the Circular Buffer if space available for writing out */
anfontanelli 11:04d8899b5d82 310
anfontanelli 11:04d8899b5d82 311
anfontanelli 11:04d8899b5d82 312 if (!_rxbuf.empty()) {
anfontanelli 11:04d8899b5d82 313 revents |= POLLIN;
anfontanelli 11:04d8899b5d82 314 }
anfontanelli 11:04d8899b5d82 315
anfontanelli 11:04d8899b5d82 316 /* POLLHUP and POLLOUT are mutually exclusive */
anfontanelli 11:04d8899b5d82 317 if (hup()) {
anfontanelli 11:04d8899b5d82 318 revents |= POLLHUP;
anfontanelli 11:04d8899b5d82 319 } else if (!_txbuf.full()) {
anfontanelli 11:04d8899b5d82 320 revents |= POLLOUT;
anfontanelli 11:04d8899b5d82 321 }
anfontanelli 11:04d8899b5d82 322
anfontanelli 11:04d8899b5d82 323 /*TODO Handle other event types */
anfontanelli 11:04d8899b5d82 324
anfontanelli 11:04d8899b5d82 325 return revents;
anfontanelli 11:04d8899b5d82 326 }
anfontanelli 11:04d8899b5d82 327
anfontanelli 11:04d8899b5d82 328 void UARTSerial_mio::lock()
anfontanelli 11:04d8899b5d82 329 {
anfontanelli 11:04d8899b5d82 330 // This is the override for SerialBase.
anfontanelli 11:04d8899b5d82 331 // No lock required as we only use SerialBase from interrupt or from
anfontanelli 11:04d8899b5d82 332 // inside our own critical section.
anfontanelli 11:04d8899b5d82 333 }
anfontanelli 11:04d8899b5d82 334
anfontanelli 11:04d8899b5d82 335 void UARTSerial_mio::unlock()
anfontanelli 11:04d8899b5d82 336 {
anfontanelli 11:04d8899b5d82 337 // This is the override for SerialBase.
anfontanelli 11:04d8899b5d82 338 }
anfontanelli 11:04d8899b5d82 339
anfontanelli 11:04d8899b5d82 340 void UARTSerial_mio::api_lock(void)
anfontanelli 11:04d8899b5d82 341 {
anfontanelli 11:04d8899b5d82 342 //_mutex.lock();
anfontanelli 11:04d8899b5d82 343 }
anfontanelli 11:04d8899b5d82 344
anfontanelli 11:04d8899b5d82 345 void UARTSerial_mio::api_unlock(void)
anfontanelli 11:04d8899b5d82 346 {
anfontanelli 11:04d8899b5d82 347 //_mutex.unlock();
anfontanelli 11:04d8899b5d82 348 }
anfontanelli 11:04d8899b5d82 349
anfontanelli 11:04d8899b5d82 350 void UARTSerial_mio::rx_irq(void)
anfontanelli 11:04d8899b5d82 351 {
anfontanelli 11:04d8899b5d82 352 bool was_empty = _rxbuf.empty();
anfontanelli 11:04d8899b5d82 353
anfontanelli 11:04d8899b5d82 354 /* Fill in the receive buffer if the peripheral is readable
anfontanelli 11:04d8899b5d82 355 * and receive buffer is not full. */
anfontanelli 11:04d8899b5d82 356 while (!_rxbuf.full() && SerialBase::readable()) {
anfontanelli 11:04d8899b5d82 357 char data = SerialBase::_base_getc();
anfontanelli 11:04d8899b5d82 358 _rxbuf.push(data);
anfontanelli 11:04d8899b5d82 359 }
anfontanelli 11:04d8899b5d82 360
anfontanelli 11:04d8899b5d82 361 if (_rx_irq_enabled && _rxbuf.full()) {
anfontanelli 11:04d8899b5d82 362 disable_rx_irq();
anfontanelli 11:04d8899b5d82 363 }
anfontanelli 11:04d8899b5d82 364
anfontanelli 11:04d8899b5d82 365 /* Report the File handler that data is ready to be read from the buffer. */
anfontanelli 11:04d8899b5d82 366 if (was_empty && !_rxbuf.empty()) {
anfontanelli 11:04d8899b5d82 367 wake();
anfontanelli 11:04d8899b5d82 368 }
anfontanelli 11:04d8899b5d82 369 }
anfontanelli 11:04d8899b5d82 370
anfontanelli 11:04d8899b5d82 371 // Also called from write to start transfer
anfontanelli 11:04d8899b5d82 372 void UARTSerial_mio::tx_irq(void)
anfontanelli 11:04d8899b5d82 373 {
anfontanelli 11:04d8899b5d82 374 bool was_full = _txbuf.full();
anfontanelli 11:04d8899b5d82 375 char data;
anfontanelli 11:04d8899b5d82 376
anfontanelli 11:04d8899b5d82 377 /* Write to the peripheral if there is something to write
anfontanelli 11:04d8899b5d82 378 * and if the peripheral is available to write. */
anfontanelli 11:04d8899b5d82 379 while (SerialBase::writeable() && _txbuf.pop(data)) {
anfontanelli 11:04d8899b5d82 380 SerialBase::_base_putc(data);
anfontanelli 11:04d8899b5d82 381 }
anfontanelli 11:04d8899b5d82 382
anfontanelli 11:04d8899b5d82 383 if (_tx_irq_enabled && _txbuf.empty()) {
anfontanelli 11:04d8899b5d82 384 disable_tx_irq();
anfontanelli 11:04d8899b5d82 385 }
anfontanelli 11:04d8899b5d82 386
anfontanelli 11:04d8899b5d82 387 /* Report the File handler that data can be written to peripheral. */
anfontanelli 11:04d8899b5d82 388 if (was_full && !_txbuf.full() && !hup()) {
anfontanelli 11:04d8899b5d82 389 wake();
anfontanelli 11:04d8899b5d82 390 }
anfontanelli 11:04d8899b5d82 391 }
anfontanelli 11:04d8899b5d82 392
anfontanelli 11:04d8899b5d82 393 /* These are all called from critical section */
anfontanelli 11:04d8899b5d82 394 void UARTSerial_mio::enable_rx_irq()
anfontanelli 11:04d8899b5d82 395 {
anfontanelli 11:04d8899b5d82 396 SerialBase::attach(callback(this, &UARTSerial_mio::rx_irq), RxIrq);
anfontanelli 11:04d8899b5d82 397 _rx_irq_enabled = true;
anfontanelli 11:04d8899b5d82 398 }
anfontanelli 11:04d8899b5d82 399
anfontanelli 11:04d8899b5d82 400 void UARTSerial_mio::disable_rx_irq()
anfontanelli 11:04d8899b5d82 401 {
anfontanelli 11:04d8899b5d82 402 SerialBase::attach(NULL, RxIrq);
anfontanelli 11:04d8899b5d82 403 _rx_irq_enabled = false;
anfontanelli 11:04d8899b5d82 404 }
anfontanelli 11:04d8899b5d82 405
anfontanelli 11:04d8899b5d82 406 void UARTSerial_mio::enable_tx_irq()
anfontanelli 11:04d8899b5d82 407 {
anfontanelli 11:04d8899b5d82 408 SerialBase::attach(callback(this, &UARTSerial_mio::tx_irq), TxIrq);
anfontanelli 11:04d8899b5d82 409 _tx_irq_enabled = true;
anfontanelli 11:04d8899b5d82 410 }
anfontanelli 11:04d8899b5d82 411
anfontanelli 11:04d8899b5d82 412 void UARTSerial_mio::disable_tx_irq()
anfontanelli 11:04d8899b5d82 413 {
anfontanelli 11:04d8899b5d82 414 SerialBase::attach(NULL, TxIrq);
anfontanelli 11:04d8899b5d82 415 _tx_irq_enabled = false;
anfontanelli 11:04d8899b5d82 416 }
anfontanelli 11:04d8899b5d82 417
anfontanelli 11:04d8899b5d82 418 int UARTSerial_mio::enable_input(bool enabled)
anfontanelli 11:04d8899b5d82 419 {
anfontanelli 11:04d8899b5d82 420 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 421 if (_rx_enabled != enabled) {
anfontanelli 11:04d8899b5d82 422 if (enabled) {
anfontanelli 11:04d8899b5d82 423 UARTSerial_mio::rx_irq();
anfontanelli 11:04d8899b5d82 424 if (!_rxbuf.full()) {
anfontanelli 11:04d8899b5d82 425 enable_rx_irq();
anfontanelli 11:04d8899b5d82 426 }
anfontanelli 11:04d8899b5d82 427 } else {
anfontanelli 11:04d8899b5d82 428 disable_rx_irq();
anfontanelli 11:04d8899b5d82 429 }
anfontanelli 11:04d8899b5d82 430 _rx_enabled = enabled;
anfontanelli 11:04d8899b5d82 431 }
anfontanelli 11:04d8899b5d82 432 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 433
anfontanelli 11:04d8899b5d82 434 return 0;
anfontanelli 11:04d8899b5d82 435 }
anfontanelli 11:04d8899b5d82 436
anfontanelli 11:04d8899b5d82 437 int UARTSerial_mio::enable_output(bool enabled)
anfontanelli 11:04d8899b5d82 438 {
anfontanelli 11:04d8899b5d82 439 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 440 if (_tx_enabled != enabled) {
anfontanelli 11:04d8899b5d82 441 if (enabled) {
anfontanelli 11:04d8899b5d82 442 UARTSerial_mio::tx_irq();
anfontanelli 11:04d8899b5d82 443 if (!_txbuf.empty()) {
anfontanelli 11:04d8899b5d82 444 enable_tx_irq();
anfontanelli 11:04d8899b5d82 445 }
anfontanelli 11:04d8899b5d82 446 } else {
anfontanelli 11:04d8899b5d82 447 disable_tx_irq();
anfontanelli 11:04d8899b5d82 448 }
anfontanelli 11:04d8899b5d82 449 _tx_enabled = enabled;
anfontanelli 11:04d8899b5d82 450 }
anfontanelli 11:04d8899b5d82 451 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 452
anfontanelli 11:04d8899b5d82 453 return 0;
anfontanelli 11:04d8899b5d82 454 }
anfontanelli 11:04d8899b5d82 455
anfontanelli 11:04d8899b5d82 456 void UARTSerial_mio::wait_ms(uint32_t millisec)
anfontanelli 11:04d8899b5d82 457 {
anfontanelli 11:04d8899b5d82 458 /* wait_ms implementation for RTOS spins until exact microseconds - we
anfontanelli 11:04d8899b5d82 459 * want to just sleep until next tick.
anfontanelli 11:04d8899b5d82 460 */
anfontanelli 11:04d8899b5d82 461 #if MBED_CONF_RTOS_PRESENT
anfontanelli 11:04d8899b5d82 462 rtos::ThisThread::sleep_for(millisec);
anfontanelli 11:04d8899b5d82 463 #else
anfontanelli 11:04d8899b5d82 464 ::wait_ms(millisec);
anfontanelli 11:04d8899b5d82 465 #endif
anfontanelli 11:04d8899b5d82 466 }
anfontanelli 11:04d8899b5d82 467
anfontanelli 11:04d8899b5d82 468 void UARTSerial_mio::wait_us(uint32_t microseconds)
anfontanelli 11:04d8899b5d82 469 {
anfontanelli 11:04d8899b5d82 470 /* wait_ms implementation for RTOS spins until exact microseconds - we
anfontanelli 11:04d8899b5d82 471 * want to just sleep until next tick.
anfontanelli 11:04d8899b5d82 472 */
anfontanelli 11:04d8899b5d82 473 #if MBED_CONF_RTOS_PRESENT
anfontanelli 11:04d8899b5d82 474 rtos::ThisThread::sleep_for(microseconds/1000);
anfontanelli 11:04d8899b5d82 475 #else
anfontanelli 11:04d8899b5d82 476 ::wait_us(microseconds);
anfontanelli 11:04d8899b5d82 477 #endif
anfontanelli 11:04d8899b5d82 478 }
anfontanelli 11:04d8899b5d82 479 } //namespace mbed
anfontanelli 11:04d8899b5d82 480
anfontanelli 11:04d8899b5d82 481 #endif //(DEVICE_SERIAL && DEVICE_INTERRUPTIN)