t

Fork of mbed-dev by mbed official

Committer:
AnnaBridge
Date:
Wed Oct 25 14:53:38 2017 +0100
Revision:
177:447f873cad2f
Parent:
171:19eb464bc2be
This updates the lib to the mbed lib v 154

Who changed what in which revision?

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