Jonathan Cacace / RoboClaw
Committer:
anfontanelli
Date:
Tue Sep 14 11:15:45 2021 +0000
Revision:
12:b423b3cbec47
Parent:
11:04d8899b5d82
A

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 12:b423b3cbec47 260 while (_rxbuf.size()!=length && tm<=timeout) {
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 12:b423b3cbec47 273 tm = 0.0;
anfontanelli 12:b423b3cbec47 274 while (data_read < length && !_rxbuf.empty() && tm<=timeout) {
anfontanelli 11:04d8899b5d82 275 _rxbuf.pop(*ptr++);
anfontanelli 11:04d8899b5d82 276 data_read++;
anfontanelli 12:b423b3cbec47 277 tm = tm + 0.001; //10/1000
anfontanelli 11:04d8899b5d82 278 }
anfontanelli 11:04d8899b5d82 279
anfontanelli 11:04d8899b5d82 280 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 281 if (_rx_enabled && !_rx_irq_enabled) {
anfontanelli 11:04d8899b5d82 282 UARTSerial_mio::rx_irq(); // only read from hardware in one place
anfontanelli 11:04d8899b5d82 283 if (!_rxbuf.full()) {
anfontanelli 11:04d8899b5d82 284 enable_rx_irq();
anfontanelli 11:04d8899b5d82 285 }
anfontanelli 11:04d8899b5d82 286 }
anfontanelli 11:04d8899b5d82 287 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 288
anfontanelli 11:04d8899b5d82 289 api_unlock();
anfontanelli 11:04d8899b5d82 290
anfontanelli 11:04d8899b5d82 291 return data_read;
anfontanelli 11:04d8899b5d82 292 }
anfontanelli 11:04d8899b5d82 293
anfontanelli 11:04d8899b5d82 294 bool UARTSerial_mio::hup() const
anfontanelli 11:04d8899b5d82 295 {
anfontanelli 11:04d8899b5d82 296 return _dcd_irq && _dcd_irq->read() != 0;
anfontanelli 11:04d8899b5d82 297 }
anfontanelli 11:04d8899b5d82 298
anfontanelli 11:04d8899b5d82 299 void UARTSerial_mio::wake()
anfontanelli 11:04d8899b5d82 300 {
anfontanelli 11:04d8899b5d82 301 if (_sigio_cb) {
anfontanelli 11:04d8899b5d82 302 _sigio_cb();
anfontanelli 11:04d8899b5d82 303 }
anfontanelli 11:04d8899b5d82 304 }
anfontanelli 11:04d8899b5d82 305
anfontanelli 11:04d8899b5d82 306 short UARTSerial_mio::poll(short events) const
anfontanelli 11:04d8899b5d82 307 {
anfontanelli 11:04d8899b5d82 308
anfontanelli 11:04d8899b5d82 309 short revents = 0;
anfontanelli 11:04d8899b5d82 310 /* Check the Circular Buffer if space available for writing out */
anfontanelli 11:04d8899b5d82 311
anfontanelli 11:04d8899b5d82 312
anfontanelli 11:04d8899b5d82 313 if (!_rxbuf.empty()) {
anfontanelli 11:04d8899b5d82 314 revents |= POLLIN;
anfontanelli 11:04d8899b5d82 315 }
anfontanelli 11:04d8899b5d82 316
anfontanelli 11:04d8899b5d82 317 /* POLLHUP and POLLOUT are mutually exclusive */
anfontanelli 11:04d8899b5d82 318 if (hup()) {
anfontanelli 11:04d8899b5d82 319 revents |= POLLHUP;
anfontanelli 11:04d8899b5d82 320 } else if (!_txbuf.full()) {
anfontanelli 11:04d8899b5d82 321 revents |= POLLOUT;
anfontanelli 11:04d8899b5d82 322 }
anfontanelli 11:04d8899b5d82 323
anfontanelli 11:04d8899b5d82 324 /*TODO Handle other event types */
anfontanelli 11:04d8899b5d82 325
anfontanelli 11:04d8899b5d82 326 return revents;
anfontanelli 11:04d8899b5d82 327 }
anfontanelli 11:04d8899b5d82 328
anfontanelli 11:04d8899b5d82 329 void UARTSerial_mio::lock()
anfontanelli 11:04d8899b5d82 330 {
anfontanelli 11:04d8899b5d82 331 // This is the override for SerialBase.
anfontanelli 11:04d8899b5d82 332 // No lock required as we only use SerialBase from interrupt or from
anfontanelli 11:04d8899b5d82 333 // inside our own critical section.
anfontanelli 11:04d8899b5d82 334 }
anfontanelli 11:04d8899b5d82 335
anfontanelli 11:04d8899b5d82 336 void UARTSerial_mio::unlock()
anfontanelli 11:04d8899b5d82 337 {
anfontanelli 11:04d8899b5d82 338 // This is the override for SerialBase.
anfontanelli 11:04d8899b5d82 339 }
anfontanelli 11:04d8899b5d82 340
anfontanelli 11:04d8899b5d82 341 void UARTSerial_mio::api_lock(void)
anfontanelli 11:04d8899b5d82 342 {
anfontanelli 11:04d8899b5d82 343 //_mutex.lock();
anfontanelli 11:04d8899b5d82 344 }
anfontanelli 11:04d8899b5d82 345
anfontanelli 11:04d8899b5d82 346 void UARTSerial_mio::api_unlock(void)
anfontanelli 11:04d8899b5d82 347 {
anfontanelli 11:04d8899b5d82 348 //_mutex.unlock();
anfontanelli 11:04d8899b5d82 349 }
anfontanelli 11:04d8899b5d82 350
anfontanelli 11:04d8899b5d82 351 void UARTSerial_mio::rx_irq(void)
anfontanelli 11:04d8899b5d82 352 {
anfontanelli 11:04d8899b5d82 353 bool was_empty = _rxbuf.empty();
anfontanelli 11:04d8899b5d82 354
anfontanelli 11:04d8899b5d82 355 /* Fill in the receive buffer if the peripheral is readable
anfontanelli 11:04d8899b5d82 356 * and receive buffer is not full. */
anfontanelli 11:04d8899b5d82 357 while (!_rxbuf.full() && SerialBase::readable()) {
anfontanelli 11:04d8899b5d82 358 char data = SerialBase::_base_getc();
anfontanelli 11:04d8899b5d82 359 _rxbuf.push(data);
anfontanelli 11:04d8899b5d82 360 }
anfontanelli 11:04d8899b5d82 361
anfontanelli 11:04d8899b5d82 362 if (_rx_irq_enabled && _rxbuf.full()) {
anfontanelli 11:04d8899b5d82 363 disable_rx_irq();
anfontanelli 11:04d8899b5d82 364 }
anfontanelli 11:04d8899b5d82 365
anfontanelli 11:04d8899b5d82 366 /* Report the File handler that data is ready to be read from the buffer. */
anfontanelli 11:04d8899b5d82 367 if (was_empty && !_rxbuf.empty()) {
anfontanelli 11:04d8899b5d82 368 wake();
anfontanelli 11:04d8899b5d82 369 }
anfontanelli 11:04d8899b5d82 370 }
anfontanelli 11:04d8899b5d82 371
anfontanelli 11:04d8899b5d82 372 // Also called from write to start transfer
anfontanelli 11:04d8899b5d82 373 void UARTSerial_mio::tx_irq(void)
anfontanelli 11:04d8899b5d82 374 {
anfontanelli 11:04d8899b5d82 375 bool was_full = _txbuf.full();
anfontanelli 11:04d8899b5d82 376 char data;
anfontanelli 11:04d8899b5d82 377
anfontanelli 11:04d8899b5d82 378 /* Write to the peripheral if there is something to write
anfontanelli 11:04d8899b5d82 379 * and if the peripheral is available to write. */
anfontanelli 11:04d8899b5d82 380 while (SerialBase::writeable() && _txbuf.pop(data)) {
anfontanelli 11:04d8899b5d82 381 SerialBase::_base_putc(data);
anfontanelli 11:04d8899b5d82 382 }
anfontanelli 11:04d8899b5d82 383
anfontanelli 11:04d8899b5d82 384 if (_tx_irq_enabled && _txbuf.empty()) {
anfontanelli 11:04d8899b5d82 385 disable_tx_irq();
anfontanelli 11:04d8899b5d82 386 }
anfontanelli 11:04d8899b5d82 387
anfontanelli 11:04d8899b5d82 388 /* Report the File handler that data can be written to peripheral. */
anfontanelli 11:04d8899b5d82 389 if (was_full && !_txbuf.full() && !hup()) {
anfontanelli 11:04d8899b5d82 390 wake();
anfontanelli 11:04d8899b5d82 391 }
anfontanelli 11:04d8899b5d82 392 }
anfontanelli 11:04d8899b5d82 393
anfontanelli 11:04d8899b5d82 394 /* These are all called from critical section */
anfontanelli 11:04d8899b5d82 395 void UARTSerial_mio::enable_rx_irq()
anfontanelli 11:04d8899b5d82 396 {
anfontanelli 11:04d8899b5d82 397 SerialBase::attach(callback(this, &UARTSerial_mio::rx_irq), RxIrq);
anfontanelli 11:04d8899b5d82 398 _rx_irq_enabled = true;
anfontanelli 11:04d8899b5d82 399 }
anfontanelli 11:04d8899b5d82 400
anfontanelli 11:04d8899b5d82 401 void UARTSerial_mio::disable_rx_irq()
anfontanelli 11:04d8899b5d82 402 {
anfontanelli 11:04d8899b5d82 403 SerialBase::attach(NULL, RxIrq);
anfontanelli 11:04d8899b5d82 404 _rx_irq_enabled = false;
anfontanelli 11:04d8899b5d82 405 }
anfontanelli 11:04d8899b5d82 406
anfontanelli 11:04d8899b5d82 407 void UARTSerial_mio::enable_tx_irq()
anfontanelli 11:04d8899b5d82 408 {
anfontanelli 11:04d8899b5d82 409 SerialBase::attach(callback(this, &UARTSerial_mio::tx_irq), TxIrq);
anfontanelli 11:04d8899b5d82 410 _tx_irq_enabled = true;
anfontanelli 11:04d8899b5d82 411 }
anfontanelli 11:04d8899b5d82 412
anfontanelli 11:04d8899b5d82 413 void UARTSerial_mio::disable_tx_irq()
anfontanelli 11:04d8899b5d82 414 {
anfontanelli 11:04d8899b5d82 415 SerialBase::attach(NULL, TxIrq);
anfontanelli 11:04d8899b5d82 416 _tx_irq_enabled = false;
anfontanelli 11:04d8899b5d82 417 }
anfontanelli 11:04d8899b5d82 418
anfontanelli 11:04d8899b5d82 419 int UARTSerial_mio::enable_input(bool enabled)
anfontanelli 11:04d8899b5d82 420 {
anfontanelli 11:04d8899b5d82 421 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 422 if (_rx_enabled != enabled) {
anfontanelli 11:04d8899b5d82 423 if (enabled) {
anfontanelli 11:04d8899b5d82 424 UARTSerial_mio::rx_irq();
anfontanelli 11:04d8899b5d82 425 if (!_rxbuf.full()) {
anfontanelli 11:04d8899b5d82 426 enable_rx_irq();
anfontanelli 11:04d8899b5d82 427 }
anfontanelli 11:04d8899b5d82 428 } else {
anfontanelli 11:04d8899b5d82 429 disable_rx_irq();
anfontanelli 11:04d8899b5d82 430 }
anfontanelli 11:04d8899b5d82 431 _rx_enabled = enabled;
anfontanelli 11:04d8899b5d82 432 }
anfontanelli 11:04d8899b5d82 433 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 434
anfontanelli 11:04d8899b5d82 435 return 0;
anfontanelli 11:04d8899b5d82 436 }
anfontanelli 11:04d8899b5d82 437
anfontanelli 11:04d8899b5d82 438 int UARTSerial_mio::enable_output(bool enabled)
anfontanelli 11:04d8899b5d82 439 {
anfontanelli 11:04d8899b5d82 440 core_util_critical_section_enter();
anfontanelli 11:04d8899b5d82 441 if (_tx_enabled != enabled) {
anfontanelli 11:04d8899b5d82 442 if (enabled) {
anfontanelli 11:04d8899b5d82 443 UARTSerial_mio::tx_irq();
anfontanelli 11:04d8899b5d82 444 if (!_txbuf.empty()) {
anfontanelli 11:04d8899b5d82 445 enable_tx_irq();
anfontanelli 11:04d8899b5d82 446 }
anfontanelli 11:04d8899b5d82 447 } else {
anfontanelli 11:04d8899b5d82 448 disable_tx_irq();
anfontanelli 11:04d8899b5d82 449 }
anfontanelli 11:04d8899b5d82 450 _tx_enabled = enabled;
anfontanelli 11:04d8899b5d82 451 }
anfontanelli 11:04d8899b5d82 452 core_util_critical_section_exit();
anfontanelli 11:04d8899b5d82 453
anfontanelli 11:04d8899b5d82 454 return 0;
anfontanelli 11:04d8899b5d82 455 }
anfontanelli 11:04d8899b5d82 456
anfontanelli 11:04d8899b5d82 457 void UARTSerial_mio::wait_ms(uint32_t millisec)
anfontanelli 11:04d8899b5d82 458 {
anfontanelli 11:04d8899b5d82 459 /* wait_ms implementation for RTOS spins until exact microseconds - we
anfontanelli 11:04d8899b5d82 460 * want to just sleep until next tick.
anfontanelli 11:04d8899b5d82 461 */
anfontanelli 11:04d8899b5d82 462 #if MBED_CONF_RTOS_PRESENT
anfontanelli 11:04d8899b5d82 463 rtos::ThisThread::sleep_for(millisec);
anfontanelli 11:04d8899b5d82 464 #else
anfontanelli 11:04d8899b5d82 465 ::wait_ms(millisec);
anfontanelli 11:04d8899b5d82 466 #endif
anfontanelli 11:04d8899b5d82 467 }
anfontanelli 11:04d8899b5d82 468
anfontanelli 11:04d8899b5d82 469 void UARTSerial_mio::wait_us(uint32_t microseconds)
anfontanelli 11:04d8899b5d82 470 {
anfontanelli 11:04d8899b5d82 471 /* wait_ms implementation for RTOS spins until exact microseconds - we
anfontanelli 11:04d8899b5d82 472 * want to just sleep until next tick.
anfontanelli 11:04d8899b5d82 473 */
anfontanelli 11:04d8899b5d82 474 #if MBED_CONF_RTOS_PRESENT
anfontanelli 11:04d8899b5d82 475 rtos::ThisThread::sleep_for(microseconds/1000);
anfontanelli 11:04d8899b5d82 476 #else
anfontanelli 11:04d8899b5d82 477 ::wait_us(microseconds);
anfontanelli 11:04d8899b5d82 478 #endif
anfontanelli 11:04d8899b5d82 479 }
anfontanelli 11:04d8899b5d82 480 } //namespace mbed
anfontanelli 11:04d8899b5d82 481
anfontanelli 11:04d8899b5d82 482 #endif //(DEVICE_SERIAL && DEVICE_INTERRUPTIN)