ricreato il link mancante

Committer:
marcodesilva
Date:
Mon Jan 10 20:38:41 2022 +0000
Revision:
4:31695331ce17
compila al 10/01/2022, da testare sul tool

Who changed what in which revision?

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