a

Committer:
marcodesilva
Date:
Tue Sep 28 10:42:56 2021 +0000
Revision:
0:6b67f1bb9c76
d

Who changed what in which revision?

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