Entrega 3er corte - sistemas embebidos

Committer:
Bethory
Date:
Wed May 30 04:46:28 2018 +0000
Revision:
1:fcdb45ee95b9
Parent:
0:6ad07c9019fd
Entrega Final

Who changed what in which revision?

UserRevisionLine numberNew contents of line
Bethory 0:6ad07c9019fd 1 /* mbed Microcontroller Library
Bethory 0:6ad07c9019fd 2 * Copyright (c) 2006-2017 ARM Limited
Bethory 0:6ad07c9019fd 3 *
Bethory 0:6ad07c9019fd 4 * Licensed under the Apache License, Version 2.0 (the "License");
Bethory 0:6ad07c9019fd 5 * you may not use this file except in compliance with the License.
Bethory 0:6ad07c9019fd 6 * You may obtain a copy of the License at
Bethory 0:6ad07c9019fd 7 *
Bethory 0:6ad07c9019fd 8 * http://www.apache.org/licenses/LICENSE-2.0
Bethory 0:6ad07c9019fd 9 *
Bethory 0:6ad07c9019fd 10 * Unless required by applicable law or agreed to in writing, software
Bethory 0:6ad07c9019fd 11 * distributed under the License is distributed on an "AS IS" BASIS,
Bethory 0:6ad07c9019fd 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
Bethory 0:6ad07c9019fd 13 * See the License for the specific language governing permissions and
Bethory 0:6ad07c9019fd 14 * limitations under the License.
Bethory 0:6ad07c9019fd 15 */
Bethory 0:6ad07c9019fd 16
Bethory 0:6ad07c9019fd 17 #if (DEVICE_SERIAL && DEVICE_INTERRUPTIN)
Bethory 0:6ad07c9019fd 18
Bethory 0:6ad07c9019fd 19 #include <errno.h>
Bethory 0:6ad07c9019fd 20 #include "UARTSerial.h"
Bethory 0:6ad07c9019fd 21 #include "platform/mbed_poll.h"
Bethory 0:6ad07c9019fd 22
Bethory 0:6ad07c9019fd 23 #if MBED_CONF_RTOS_PRESENT
Bethory 0:6ad07c9019fd 24 #include "rtos/Thread.h"
Bethory 0:6ad07c9019fd 25 #else
Bethory 0:6ad07c9019fd 26 #include "platform/mbed_wait_api.h"
Bethory 0:6ad07c9019fd 27 #endif
Bethory 0:6ad07c9019fd 28
Bethory 0:6ad07c9019fd 29 namespace mbed {
Bethory 0:6ad07c9019fd 30
Bethory 0:6ad07c9019fd 31 UARTSerial::UARTSerial(PinName tx, PinName rx, int baud) :
Bethory 0:6ad07c9019fd 32 SerialBase(tx, rx, baud),
Bethory 0:6ad07c9019fd 33 _blocking(true),
Bethory 0:6ad07c9019fd 34 _tx_irq_enabled(false),
Bethory 0:6ad07c9019fd 35 _rx_irq_enabled(true),
Bethory 0:6ad07c9019fd 36 _dcd_irq(NULL)
Bethory 0:6ad07c9019fd 37 {
Bethory 0:6ad07c9019fd 38 /* Attatch IRQ routines to the serial device. */
Bethory 0:6ad07c9019fd 39 SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
Bethory 0:6ad07c9019fd 40 }
Bethory 0:6ad07c9019fd 41
Bethory 0:6ad07c9019fd 42 UARTSerial::~UARTSerial()
Bethory 0:6ad07c9019fd 43 {
Bethory 0:6ad07c9019fd 44 delete _dcd_irq;
Bethory 0:6ad07c9019fd 45 }
Bethory 0:6ad07c9019fd 46
Bethory 0:6ad07c9019fd 47 void UARTSerial::dcd_irq()
Bethory 0:6ad07c9019fd 48 {
Bethory 0:6ad07c9019fd 49 wake();
Bethory 0:6ad07c9019fd 50 }
Bethory 0:6ad07c9019fd 51
Bethory 0:6ad07c9019fd 52 void UARTSerial::set_baud(int baud)
Bethory 0:6ad07c9019fd 53 {
Bethory 0:6ad07c9019fd 54 SerialBase::baud(baud);
Bethory 0:6ad07c9019fd 55 }
Bethory 0:6ad07c9019fd 56
Bethory 0:6ad07c9019fd 57 void UARTSerial::set_data_carrier_detect(PinName dcd_pin, bool active_high)
Bethory 0:6ad07c9019fd 58 {
Bethory 0:6ad07c9019fd 59 delete _dcd_irq;
Bethory 0:6ad07c9019fd 60 _dcd_irq = NULL;
Bethory 0:6ad07c9019fd 61
Bethory 0:6ad07c9019fd 62 if (dcd_pin != NC) {
Bethory 0:6ad07c9019fd 63 _dcd_irq = new InterruptIn(dcd_pin);
Bethory 0:6ad07c9019fd 64 if (active_high) {
Bethory 0:6ad07c9019fd 65 _dcd_irq->fall(callback(this, &UARTSerial::dcd_irq));
Bethory 0:6ad07c9019fd 66 } else {
Bethory 0:6ad07c9019fd 67 _dcd_irq->rise(callback(this, &UARTSerial::dcd_irq));
Bethory 0:6ad07c9019fd 68 }
Bethory 0:6ad07c9019fd 69 }
Bethory 0:6ad07c9019fd 70 }
Bethory 0:6ad07c9019fd 71
Bethory 0:6ad07c9019fd 72 void UARTSerial::set_format(int bits, Parity parity, int stop_bits)
Bethory 0:6ad07c9019fd 73 {
Bethory 0:6ad07c9019fd 74 api_lock();
Bethory 0:6ad07c9019fd 75 SerialBase::format(bits, parity, stop_bits);
Bethory 0:6ad07c9019fd 76 api_unlock();
Bethory 0:6ad07c9019fd 77 }
Bethory 0:6ad07c9019fd 78
Bethory 0:6ad07c9019fd 79 #if DEVICE_SERIAL_FC
Bethory 0:6ad07c9019fd 80 void UARTSerial::set_flow_control(Flow type, PinName flow1, PinName flow2)
Bethory 0:6ad07c9019fd 81 {
Bethory 0:6ad07c9019fd 82 api_lock();
Bethory 0:6ad07c9019fd 83 SerialBase::set_flow_control(type, flow1, flow2);
Bethory 0:6ad07c9019fd 84 api_unlock();
Bethory 0:6ad07c9019fd 85 }
Bethory 0:6ad07c9019fd 86 #endif
Bethory 0:6ad07c9019fd 87
Bethory 0:6ad07c9019fd 88 int UARTSerial::close()
Bethory 0:6ad07c9019fd 89 {
Bethory 0:6ad07c9019fd 90 /* Does not let us pass a file descriptor. So how to close ?
Bethory 0:6ad07c9019fd 91 * Also, does it make sense to close a device type file descriptor*/
Bethory 0:6ad07c9019fd 92 return 0;
Bethory 0:6ad07c9019fd 93 }
Bethory 0:6ad07c9019fd 94
Bethory 0:6ad07c9019fd 95 int UARTSerial::isatty()
Bethory 0:6ad07c9019fd 96 {
Bethory 0:6ad07c9019fd 97 return 1;
Bethory 0:6ad07c9019fd 98
Bethory 0:6ad07c9019fd 99 }
Bethory 0:6ad07c9019fd 100
Bethory 0:6ad07c9019fd 101 off_t UARTSerial::seek(off_t offset, int whence)
Bethory 0:6ad07c9019fd 102 {
Bethory 0:6ad07c9019fd 103 /*XXX lseek can be done theoratically, but is it sane to mark positions on a dynamically growing/shrinking
Bethory 0:6ad07c9019fd 104 * buffer system (from an interrupt context) */
Bethory 0:6ad07c9019fd 105 return -ESPIPE;
Bethory 0:6ad07c9019fd 106 }
Bethory 0:6ad07c9019fd 107
Bethory 0:6ad07c9019fd 108 int UARTSerial::sync()
Bethory 0:6ad07c9019fd 109 {
Bethory 0:6ad07c9019fd 110 api_lock();
Bethory 0:6ad07c9019fd 111
Bethory 0:6ad07c9019fd 112 while (!_txbuf.empty()) {
Bethory 0:6ad07c9019fd 113 api_unlock();
Bethory 0:6ad07c9019fd 114 // Doing better than wait would require TxIRQ to also do wake() when becoming empty. Worth it?
Bethory 0:6ad07c9019fd 115 wait_ms(1);
Bethory 0:6ad07c9019fd 116 api_lock();
Bethory 0:6ad07c9019fd 117 }
Bethory 0:6ad07c9019fd 118
Bethory 0:6ad07c9019fd 119 api_unlock();
Bethory 0:6ad07c9019fd 120
Bethory 0:6ad07c9019fd 121 return 0;
Bethory 0:6ad07c9019fd 122 }
Bethory 0:6ad07c9019fd 123
Bethory 0:6ad07c9019fd 124 void UARTSerial::sigio(Callback<void()> func) {
Bethory 0:6ad07c9019fd 125 core_util_critical_section_enter();
Bethory 0:6ad07c9019fd 126 _sigio_cb = func;
Bethory 0:6ad07c9019fd 127 if (_sigio_cb) {
Bethory 0:6ad07c9019fd 128 short current_events = poll(0x7FFF);
Bethory 0:6ad07c9019fd 129 if (current_events) {
Bethory 0:6ad07c9019fd 130 _sigio_cb();
Bethory 0:6ad07c9019fd 131 }
Bethory 0:6ad07c9019fd 132 }
Bethory 0:6ad07c9019fd 133 core_util_critical_section_exit();
Bethory 0:6ad07c9019fd 134 }
Bethory 0:6ad07c9019fd 135
Bethory 0:6ad07c9019fd 136 ssize_t UARTSerial::write(const void* buffer, size_t length)
Bethory 0:6ad07c9019fd 137 {
Bethory 0:6ad07c9019fd 138 size_t data_written = 0;
Bethory 0:6ad07c9019fd 139 const char *buf_ptr = static_cast<const char *>(buffer);
Bethory 0:6ad07c9019fd 140
Bethory 0:6ad07c9019fd 141 if (length == 0) {
Bethory 0:6ad07c9019fd 142 return 0;
Bethory 0:6ad07c9019fd 143 }
Bethory 0:6ad07c9019fd 144
Bethory 0:6ad07c9019fd 145 api_lock();
Bethory 0:6ad07c9019fd 146
Bethory 0:6ad07c9019fd 147 // Unlike read, we should write the whole thing if blocking. POSIX only
Bethory 0:6ad07c9019fd 148 // allows partial as a side-effect of signal handling; it normally tries to
Bethory 0:6ad07c9019fd 149 // write everything if blocking. Without signals we can always write all.
Bethory 0:6ad07c9019fd 150 while (data_written < length) {
Bethory 0:6ad07c9019fd 151
Bethory 0:6ad07c9019fd 152 if (_txbuf.full()) {
Bethory 0:6ad07c9019fd 153 if (!_blocking) {
Bethory 0:6ad07c9019fd 154 break;
Bethory 0:6ad07c9019fd 155 }
Bethory 0:6ad07c9019fd 156 do {
Bethory 0:6ad07c9019fd 157 api_unlock();
Bethory 0:6ad07c9019fd 158 wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
Bethory 0:6ad07c9019fd 159 api_lock();
Bethory 0:6ad07c9019fd 160 } while (_txbuf.full());
Bethory 0:6ad07c9019fd 161 }
Bethory 0:6ad07c9019fd 162
Bethory 0:6ad07c9019fd 163 while (data_written < length && !_txbuf.full()) {
Bethory 0:6ad07c9019fd 164 _txbuf.push(*buf_ptr++);
Bethory 0:6ad07c9019fd 165 data_written++;
Bethory 0:6ad07c9019fd 166 }
Bethory 0:6ad07c9019fd 167
Bethory 0:6ad07c9019fd 168 core_util_critical_section_enter();
Bethory 0:6ad07c9019fd 169 if (!_tx_irq_enabled) {
Bethory 0:6ad07c9019fd 170 UARTSerial::tx_irq(); // only write to hardware in one place
Bethory 0:6ad07c9019fd 171 if (!_txbuf.empty()) {
Bethory 0:6ad07c9019fd 172 SerialBase::attach(callback(this, &UARTSerial::tx_irq), TxIrq);
Bethory 0:6ad07c9019fd 173 _tx_irq_enabled = true;
Bethory 0:6ad07c9019fd 174 }
Bethory 0:6ad07c9019fd 175 }
Bethory 0:6ad07c9019fd 176 core_util_critical_section_exit();
Bethory 0:6ad07c9019fd 177 }
Bethory 0:6ad07c9019fd 178
Bethory 0:6ad07c9019fd 179 api_unlock();
Bethory 0:6ad07c9019fd 180
Bethory 0:6ad07c9019fd 181 return data_written != 0 ? (ssize_t) data_written : (ssize_t) -EAGAIN;
Bethory 0:6ad07c9019fd 182 }
Bethory 0:6ad07c9019fd 183
Bethory 0:6ad07c9019fd 184 ssize_t UARTSerial::read(void* buffer, size_t length)
Bethory 0:6ad07c9019fd 185 {
Bethory 0:6ad07c9019fd 186 size_t data_read = 0;
Bethory 0:6ad07c9019fd 187
Bethory 0:6ad07c9019fd 188 char *ptr = static_cast<char *>(buffer);
Bethory 0:6ad07c9019fd 189
Bethory 0:6ad07c9019fd 190 if (length == 0) {
Bethory 0:6ad07c9019fd 191 return 0;
Bethory 0:6ad07c9019fd 192 }
Bethory 0:6ad07c9019fd 193
Bethory 0:6ad07c9019fd 194 api_lock();
Bethory 0:6ad07c9019fd 195
Bethory 0:6ad07c9019fd 196 while (_rxbuf.empty()) {
Bethory 0:6ad07c9019fd 197 if (!_blocking) {
Bethory 0:6ad07c9019fd 198 api_unlock();
Bethory 0:6ad07c9019fd 199 return -EAGAIN;
Bethory 0:6ad07c9019fd 200 }
Bethory 0:6ad07c9019fd 201 api_unlock();
Bethory 0:6ad07c9019fd 202 wait_ms(1); // XXX todo - proper wait, WFE for non-rtos ?
Bethory 0:6ad07c9019fd 203 api_lock();
Bethory 0:6ad07c9019fd 204 }
Bethory 0:6ad07c9019fd 205
Bethory 0:6ad07c9019fd 206 while (data_read < length && !_rxbuf.empty()) {
Bethory 0:6ad07c9019fd 207 _rxbuf.pop(*ptr++);
Bethory 0:6ad07c9019fd 208 data_read++;
Bethory 0:6ad07c9019fd 209 }
Bethory 0:6ad07c9019fd 210
Bethory 0:6ad07c9019fd 211 core_util_critical_section_enter();
Bethory 0:6ad07c9019fd 212 if (!_rx_irq_enabled) {
Bethory 0:6ad07c9019fd 213 UARTSerial::rx_irq(); // only read from hardware in one place
Bethory 0:6ad07c9019fd 214 if (!_rxbuf.full()) {
Bethory 0:6ad07c9019fd 215 SerialBase::attach(callback(this, &UARTSerial::rx_irq), RxIrq);
Bethory 0:6ad07c9019fd 216 _rx_irq_enabled = true;
Bethory 0:6ad07c9019fd 217 }
Bethory 0:6ad07c9019fd 218 }
Bethory 0:6ad07c9019fd 219 core_util_critical_section_exit();
Bethory 0:6ad07c9019fd 220
Bethory 0:6ad07c9019fd 221 api_unlock();
Bethory 0:6ad07c9019fd 222
Bethory 0:6ad07c9019fd 223 return data_read;
Bethory 0:6ad07c9019fd 224 }
Bethory 0:6ad07c9019fd 225
Bethory 0:6ad07c9019fd 226 bool UARTSerial::hup() const
Bethory 0:6ad07c9019fd 227 {
Bethory 0:6ad07c9019fd 228 return _dcd_irq && _dcd_irq->read() != 0;
Bethory 0:6ad07c9019fd 229 }
Bethory 0:6ad07c9019fd 230
Bethory 0:6ad07c9019fd 231 void UARTSerial::wake()
Bethory 0:6ad07c9019fd 232 {
Bethory 0:6ad07c9019fd 233 if (_sigio_cb) {
Bethory 0:6ad07c9019fd 234 _sigio_cb();
Bethory 0:6ad07c9019fd 235 }
Bethory 0:6ad07c9019fd 236 }
Bethory 0:6ad07c9019fd 237
Bethory 0:6ad07c9019fd 238 short UARTSerial::poll(short events) const {
Bethory 0:6ad07c9019fd 239
Bethory 0:6ad07c9019fd 240 short revents = 0;
Bethory 0:6ad07c9019fd 241 /* Check the Circular Buffer if space available for writing out */
Bethory 0:6ad07c9019fd 242
Bethory 0:6ad07c9019fd 243
Bethory 0:6ad07c9019fd 244 if (!_rxbuf.empty()) {
Bethory 0:6ad07c9019fd 245 revents |= POLLIN;
Bethory 0:6ad07c9019fd 246 }
Bethory 0:6ad07c9019fd 247
Bethory 0:6ad07c9019fd 248 /* POLLHUP and POLLOUT are mutually exclusive */
Bethory 0:6ad07c9019fd 249 if (hup()) {
Bethory 0:6ad07c9019fd 250 revents |= POLLHUP;
Bethory 0:6ad07c9019fd 251 } else if (!_txbuf.full()) {
Bethory 0:6ad07c9019fd 252 revents |= POLLOUT;
Bethory 0:6ad07c9019fd 253 }
Bethory 0:6ad07c9019fd 254
Bethory 0:6ad07c9019fd 255 /*TODO Handle other event types */
Bethory 0:6ad07c9019fd 256
Bethory 0:6ad07c9019fd 257 return revents;
Bethory 0:6ad07c9019fd 258 }
Bethory 0:6ad07c9019fd 259
Bethory 0:6ad07c9019fd 260 void UARTSerial::lock()
Bethory 0:6ad07c9019fd 261 {
Bethory 0:6ad07c9019fd 262 // This is the override for SerialBase.
Bethory 0:6ad07c9019fd 263 // No lock required as we only use SerialBase from interrupt or from
Bethory 0:6ad07c9019fd 264 // inside our own critical section.
Bethory 0:6ad07c9019fd 265 }
Bethory 0:6ad07c9019fd 266
Bethory 0:6ad07c9019fd 267 void UARTSerial::unlock()
Bethory 0:6ad07c9019fd 268 {
Bethory 0:6ad07c9019fd 269 // This is the override for SerialBase.
Bethory 0:6ad07c9019fd 270 }
Bethory 0:6ad07c9019fd 271
Bethory 0:6ad07c9019fd 272 void UARTSerial::api_lock(void)
Bethory 0:6ad07c9019fd 273 {
Bethory 0:6ad07c9019fd 274 _mutex.lock();
Bethory 0:6ad07c9019fd 275 }
Bethory 0:6ad07c9019fd 276
Bethory 0:6ad07c9019fd 277 void UARTSerial::api_unlock(void)
Bethory 0:6ad07c9019fd 278 {
Bethory 0:6ad07c9019fd 279 _mutex.unlock();
Bethory 0:6ad07c9019fd 280 }
Bethory 0:6ad07c9019fd 281
Bethory 0:6ad07c9019fd 282 void UARTSerial::rx_irq(void)
Bethory 0:6ad07c9019fd 283 {
Bethory 0:6ad07c9019fd 284 bool was_empty = _rxbuf.empty();
Bethory 0:6ad07c9019fd 285
Bethory 0:6ad07c9019fd 286 /* Fill in the receive buffer if the peripheral is readable
Bethory 0:6ad07c9019fd 287 * and receive buffer is not full. */
Bethory 0:6ad07c9019fd 288 while (!_rxbuf.full() && SerialBase::readable()) {
Bethory 0:6ad07c9019fd 289 char data = SerialBase::_base_getc();
Bethory 0:6ad07c9019fd 290 _rxbuf.push(data);
Bethory 0:6ad07c9019fd 291 }
Bethory 0:6ad07c9019fd 292
Bethory 0:6ad07c9019fd 293 if (_rx_irq_enabled && _rxbuf.full()) {
Bethory 0:6ad07c9019fd 294 SerialBase::attach(NULL, RxIrq);
Bethory 0:6ad07c9019fd 295 _rx_irq_enabled = false;
Bethory 0:6ad07c9019fd 296 }
Bethory 0:6ad07c9019fd 297
Bethory 0:6ad07c9019fd 298 /* Report the File handler that data is ready to be read from the buffer. */
Bethory 0:6ad07c9019fd 299 if (was_empty && !_rxbuf.empty()) {
Bethory 0:6ad07c9019fd 300 wake();
Bethory 0:6ad07c9019fd 301 }
Bethory 0:6ad07c9019fd 302 }
Bethory 0:6ad07c9019fd 303
Bethory 0:6ad07c9019fd 304 // Also called from write to start transfer
Bethory 0:6ad07c9019fd 305 void UARTSerial::tx_irq(void)
Bethory 0:6ad07c9019fd 306 {
Bethory 0:6ad07c9019fd 307 bool was_full = _txbuf.full();
Bethory 0:6ad07c9019fd 308 char data;
Bethory 0:6ad07c9019fd 309
Bethory 0:6ad07c9019fd 310 /* Write to the peripheral if there is something to write
Bethory 0:6ad07c9019fd 311 * and if the peripheral is available to write. */
Bethory 0:6ad07c9019fd 312 while (SerialBase::writeable() && _txbuf.pop(data)) {
Bethory 0:6ad07c9019fd 313 SerialBase::_base_putc(data);
Bethory 0:6ad07c9019fd 314 }
Bethory 0:6ad07c9019fd 315
Bethory 0:6ad07c9019fd 316 if (_tx_irq_enabled && _txbuf.empty()) {
Bethory 0:6ad07c9019fd 317 SerialBase::attach(NULL, TxIrq);
Bethory 0:6ad07c9019fd 318 _tx_irq_enabled = false;
Bethory 0:6ad07c9019fd 319 }
Bethory 0:6ad07c9019fd 320
Bethory 0:6ad07c9019fd 321 /* Report the File handler that data can be written to peripheral. */
Bethory 0:6ad07c9019fd 322 if (was_full && !_txbuf.full() && !hup()) {
Bethory 0:6ad07c9019fd 323 wake();
Bethory 0:6ad07c9019fd 324 }
Bethory 0:6ad07c9019fd 325 }
Bethory 0:6ad07c9019fd 326
Bethory 0:6ad07c9019fd 327 void UARTSerial::wait_ms(uint32_t millisec)
Bethory 0:6ad07c9019fd 328 {
Bethory 0:6ad07c9019fd 329 /* wait_ms implementation for RTOS spins until exact microseconds - we
Bethory 0:6ad07c9019fd 330 * want to just sleep until next tick.
Bethory 0:6ad07c9019fd 331 */
Bethory 0:6ad07c9019fd 332 #if MBED_CONF_RTOS_PRESENT
Bethory 0:6ad07c9019fd 333 rtos::Thread::wait(millisec);
Bethory 0:6ad07c9019fd 334 #else
Bethory 0:6ad07c9019fd 335 ::wait_ms(millisec);
Bethory 0:6ad07c9019fd 336 #endif
Bethory 0:6ad07c9019fd 337 }
Bethory 0:6ad07c9019fd 338 } //namespace mbed
Bethory 0:6ad07c9019fd 339
Bethory 0:6ad07c9019fd 340 #endif //(DEVICE_SERIAL && DEVICE_INTERRUPTIN)