mbed-os5 only for TYBLE16
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
drivers/source/SerialBase.cpp@1:9db0e321a9f4, 2019-12-31 (annotated)
- Committer:
- kenjiArai
- Date:
- Tue Dec 31 06:02:27 2019 +0000
- Revision:
- 1:9db0e321a9f4
updated based on mbed-os5.15.0
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
kenjiArai | 1:9db0e321a9f4 | 1 | /* mbed Microcontroller Library |
kenjiArai | 1:9db0e321a9f4 | 2 | * Copyright (c) 2006-2013 ARM Limited |
kenjiArai | 1:9db0e321a9f4 | 3 | * SPDX-License-Identifier: Apache-2.0 |
kenjiArai | 1:9db0e321a9f4 | 4 | * |
kenjiArai | 1:9db0e321a9f4 | 5 | * Licensed under the Apache License, Version 2.0 (the "License"); |
kenjiArai | 1:9db0e321a9f4 | 6 | * you may not use this file except in compliance with the License. |
kenjiArai | 1:9db0e321a9f4 | 7 | * You may obtain a copy of the License at |
kenjiArai | 1:9db0e321a9f4 | 8 | * |
kenjiArai | 1:9db0e321a9f4 | 9 | * http://www.apache.org/licenses/LICENSE-2.0 |
kenjiArai | 1:9db0e321a9f4 | 10 | * |
kenjiArai | 1:9db0e321a9f4 | 11 | * Unless required by applicable law or agreed to in writing, software |
kenjiArai | 1:9db0e321a9f4 | 12 | * distributed under the License is distributed on an "AS IS" BASIS, |
kenjiArai | 1:9db0e321a9f4 | 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
kenjiArai | 1:9db0e321a9f4 | 14 | * See the License for the specific language governing permissions and |
kenjiArai | 1:9db0e321a9f4 | 15 | * limitations under the License. |
kenjiArai | 1:9db0e321a9f4 | 16 | */ |
kenjiArai | 1:9db0e321a9f4 | 17 | #include "drivers/SerialBase.h" |
kenjiArai | 1:9db0e321a9f4 | 18 | #include "platform/mbed_wait_api.h" |
kenjiArai | 1:9db0e321a9f4 | 19 | #include "platform/mbed_critical.h" |
kenjiArai | 1:9db0e321a9f4 | 20 | #include "platform/mbed_power_mgmt.h" |
kenjiArai | 1:9db0e321a9f4 | 21 | |
kenjiArai | 1:9db0e321a9f4 | 22 | #if DEVICE_SERIAL |
kenjiArai | 1:9db0e321a9f4 | 23 | |
kenjiArai | 1:9db0e321a9f4 | 24 | namespace mbed { |
kenjiArai | 1:9db0e321a9f4 | 25 | |
kenjiArai | 1:9db0e321a9f4 | 26 | SerialBase::SerialBase(PinName tx, PinName rx, int baud) : |
kenjiArai | 1:9db0e321a9f4 | 27 | #if DEVICE_SERIAL_ASYNCH |
kenjiArai | 1:9db0e321a9f4 | 28 | _thunk_irq(this), |
kenjiArai | 1:9db0e321a9f4 | 29 | #endif |
kenjiArai | 1:9db0e321a9f4 | 30 | _baud(baud), |
kenjiArai | 1:9db0e321a9f4 | 31 | _tx_pin(tx), |
kenjiArai | 1:9db0e321a9f4 | 32 | _rx_pin(rx), |
kenjiArai | 1:9db0e321a9f4 | 33 | _init_func(&SerialBase::_init) |
kenjiArai | 1:9db0e321a9f4 | 34 | { |
kenjiArai | 1:9db0e321a9f4 | 35 | // No lock needed in the constructor |
kenjiArai | 1:9db0e321a9f4 | 36 | |
kenjiArai | 1:9db0e321a9f4 | 37 | for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { |
kenjiArai | 1:9db0e321a9f4 | 38 | _irq[i] = NULL; |
kenjiArai | 1:9db0e321a9f4 | 39 | } |
kenjiArai | 1:9db0e321a9f4 | 40 | |
kenjiArai | 1:9db0e321a9f4 | 41 | (this->*_init_func)(); |
kenjiArai | 1:9db0e321a9f4 | 42 | } |
kenjiArai | 1:9db0e321a9f4 | 43 | |
kenjiArai | 1:9db0e321a9f4 | 44 | SerialBase::SerialBase(const serial_pinmap_t &static_pinmap, int baud) : |
kenjiArai | 1:9db0e321a9f4 | 45 | #if DEVICE_SERIAL_ASYNCH |
kenjiArai | 1:9db0e321a9f4 | 46 | _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER), |
kenjiArai | 1:9db0e321a9f4 | 47 | _rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL), |
kenjiArai | 1:9db0e321a9f4 | 48 | _rx_callback(NULL), _tx_asynch_set(false), |
kenjiArai | 1:9db0e321a9f4 | 49 | _rx_asynch_set(false), |
kenjiArai | 1:9db0e321a9f4 | 50 | #endif |
kenjiArai | 1:9db0e321a9f4 | 51 | _serial(), |
kenjiArai | 1:9db0e321a9f4 | 52 | _baud(baud), |
kenjiArai | 1:9db0e321a9f4 | 53 | _tx_pin(static_pinmap.tx_pin), |
kenjiArai | 1:9db0e321a9f4 | 54 | _rx_pin(static_pinmap.rx_pin), |
kenjiArai | 1:9db0e321a9f4 | 55 | _static_pinmap(&static_pinmap), |
kenjiArai | 1:9db0e321a9f4 | 56 | _init_func(&SerialBase::_init_direct) |
kenjiArai | 1:9db0e321a9f4 | 57 | { |
kenjiArai | 1:9db0e321a9f4 | 58 | // No lock needed in the constructor |
kenjiArai | 1:9db0e321a9f4 | 59 | |
kenjiArai | 1:9db0e321a9f4 | 60 | for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { |
kenjiArai | 1:9db0e321a9f4 | 61 | _irq[i] = NULL; |
kenjiArai | 1:9db0e321a9f4 | 62 | } |
kenjiArai | 1:9db0e321a9f4 | 63 | |
kenjiArai | 1:9db0e321a9f4 | 64 | (this->*_init_func)(); |
kenjiArai | 1:9db0e321a9f4 | 65 | } |
kenjiArai | 1:9db0e321a9f4 | 66 | |
kenjiArai | 1:9db0e321a9f4 | 67 | void SerialBase::baud(int baudrate) |
kenjiArai | 1:9db0e321a9f4 | 68 | { |
kenjiArai | 1:9db0e321a9f4 | 69 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 70 | serial_baud(&_serial, baudrate); |
kenjiArai | 1:9db0e321a9f4 | 71 | _baud = baudrate; |
kenjiArai | 1:9db0e321a9f4 | 72 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 73 | } |
kenjiArai | 1:9db0e321a9f4 | 74 | |
kenjiArai | 1:9db0e321a9f4 | 75 | void SerialBase::format(int bits, Parity parity, int stop_bits) |
kenjiArai | 1:9db0e321a9f4 | 76 | { |
kenjiArai | 1:9db0e321a9f4 | 77 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 78 | serial_format(&_serial, bits, (SerialParity)parity, stop_bits); |
kenjiArai | 1:9db0e321a9f4 | 79 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 80 | } |
kenjiArai | 1:9db0e321a9f4 | 81 | |
kenjiArai | 1:9db0e321a9f4 | 82 | int SerialBase::readable() |
kenjiArai | 1:9db0e321a9f4 | 83 | { |
kenjiArai | 1:9db0e321a9f4 | 84 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 85 | int ret = serial_readable(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 86 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 87 | return ret; |
kenjiArai | 1:9db0e321a9f4 | 88 | } |
kenjiArai | 1:9db0e321a9f4 | 89 | |
kenjiArai | 1:9db0e321a9f4 | 90 | |
kenjiArai | 1:9db0e321a9f4 | 91 | int SerialBase::writeable() |
kenjiArai | 1:9db0e321a9f4 | 92 | { |
kenjiArai | 1:9db0e321a9f4 | 93 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 94 | int ret = serial_writable(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 95 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 96 | return ret; |
kenjiArai | 1:9db0e321a9f4 | 97 | } |
kenjiArai | 1:9db0e321a9f4 | 98 | |
kenjiArai | 1:9db0e321a9f4 | 99 | void SerialBase::attach(Callback<void()> func, IrqType type) |
kenjiArai | 1:9db0e321a9f4 | 100 | { |
kenjiArai | 1:9db0e321a9f4 | 101 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 102 | const bool enabled { (_rx_enabled &&(type == RxIrq)) || (_tx_enabled &&(type == TxIrq)) }; |
kenjiArai | 1:9db0e321a9f4 | 103 | // If corresponding direction is not enabled only update the handler |
kenjiArai | 1:9db0e321a9f4 | 104 | if (!enabled) { |
kenjiArai | 1:9db0e321a9f4 | 105 | _irq[type] = func; |
kenjiArai | 1:9db0e321a9f4 | 106 | } else { |
kenjiArai | 1:9db0e321a9f4 | 107 | // Disable interrupts when attaching interrupt handler |
kenjiArai | 1:9db0e321a9f4 | 108 | core_util_critical_section_enter(); |
kenjiArai | 1:9db0e321a9f4 | 109 | if (func) { |
kenjiArai | 1:9db0e321a9f4 | 110 | // lock deep sleep only the first time |
kenjiArai | 1:9db0e321a9f4 | 111 | if (!_irq[type]) { |
kenjiArai | 1:9db0e321a9f4 | 112 | sleep_manager_lock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 113 | } |
kenjiArai | 1:9db0e321a9f4 | 114 | _irq[type] = func; |
kenjiArai | 1:9db0e321a9f4 | 115 | serial_irq_set(&_serial, (SerialIrq)type, 1); |
kenjiArai | 1:9db0e321a9f4 | 116 | } else { |
kenjiArai | 1:9db0e321a9f4 | 117 | // unlock deep sleep only the first time |
kenjiArai | 1:9db0e321a9f4 | 118 | if (_irq[type]) { |
kenjiArai | 1:9db0e321a9f4 | 119 | sleep_manager_unlock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 120 | } |
kenjiArai | 1:9db0e321a9f4 | 121 | _irq[type] = NULL; |
kenjiArai | 1:9db0e321a9f4 | 122 | serial_irq_set(&_serial, (SerialIrq)type, 0); |
kenjiArai | 1:9db0e321a9f4 | 123 | } |
kenjiArai | 1:9db0e321a9f4 | 124 | core_util_critical_section_exit(); |
kenjiArai | 1:9db0e321a9f4 | 125 | } |
kenjiArai | 1:9db0e321a9f4 | 126 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 127 | } |
kenjiArai | 1:9db0e321a9f4 | 128 | |
kenjiArai | 1:9db0e321a9f4 | 129 | void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) |
kenjiArai | 1:9db0e321a9f4 | 130 | { |
kenjiArai | 1:9db0e321a9f4 | 131 | SerialBase *handler = (SerialBase *)id; |
kenjiArai | 1:9db0e321a9f4 | 132 | if (handler->_irq[irq_type]) { |
kenjiArai | 1:9db0e321a9f4 | 133 | handler->_irq[irq_type](); |
kenjiArai | 1:9db0e321a9f4 | 134 | } |
kenjiArai | 1:9db0e321a9f4 | 135 | } |
kenjiArai | 1:9db0e321a9f4 | 136 | |
kenjiArai | 1:9db0e321a9f4 | 137 | int SerialBase::_base_getc() |
kenjiArai | 1:9db0e321a9f4 | 138 | { |
kenjiArai | 1:9db0e321a9f4 | 139 | // Mutex is already held |
kenjiArai | 1:9db0e321a9f4 | 140 | return serial_getc(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 141 | } |
kenjiArai | 1:9db0e321a9f4 | 142 | |
kenjiArai | 1:9db0e321a9f4 | 143 | int SerialBase::_base_putc(int c) |
kenjiArai | 1:9db0e321a9f4 | 144 | { |
kenjiArai | 1:9db0e321a9f4 | 145 | // Mutex is already held |
kenjiArai | 1:9db0e321a9f4 | 146 | serial_putc(&_serial, c); |
kenjiArai | 1:9db0e321a9f4 | 147 | return c; |
kenjiArai | 1:9db0e321a9f4 | 148 | } |
kenjiArai | 1:9db0e321a9f4 | 149 | |
kenjiArai | 1:9db0e321a9f4 | 150 | void SerialBase::_init() |
kenjiArai | 1:9db0e321a9f4 | 151 | { |
kenjiArai | 1:9db0e321a9f4 | 152 | serial_init(&_serial, _tx_pin, _rx_pin); |
kenjiArai | 1:9db0e321a9f4 | 153 | #if DEVICE_SERIAL_FC |
kenjiArai | 1:9db0e321a9f4 | 154 | if (_set_flow_control_dp_func) { |
kenjiArai | 1:9db0e321a9f4 | 155 | (this->*_set_flow_control_dp_func)(_flow_type, _flow1, _flow2); |
kenjiArai | 1:9db0e321a9f4 | 156 | } |
kenjiArai | 1:9db0e321a9f4 | 157 | #endif |
kenjiArai | 1:9db0e321a9f4 | 158 | serial_baud(&_serial, _baud); |
kenjiArai | 1:9db0e321a9f4 | 159 | serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); |
kenjiArai | 1:9db0e321a9f4 | 160 | } |
kenjiArai | 1:9db0e321a9f4 | 161 | |
kenjiArai | 1:9db0e321a9f4 | 162 | void SerialBase::_init_direct() |
kenjiArai | 1:9db0e321a9f4 | 163 | { |
kenjiArai | 1:9db0e321a9f4 | 164 | serial_init_direct(&_serial, _static_pinmap); |
kenjiArai | 1:9db0e321a9f4 | 165 | #if DEVICE_SERIAL_FC |
kenjiArai | 1:9db0e321a9f4 | 166 | if (_static_pinmap_fc && _set_flow_control_dp_func) { |
kenjiArai | 1:9db0e321a9f4 | 167 | (this->*_set_flow_control_sp_func)(_flow_type, *_static_pinmap_fc); |
kenjiArai | 1:9db0e321a9f4 | 168 | } |
kenjiArai | 1:9db0e321a9f4 | 169 | #endif |
kenjiArai | 1:9db0e321a9f4 | 170 | serial_baud(&_serial, _baud); |
kenjiArai | 1:9db0e321a9f4 | 171 | serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); |
kenjiArai | 1:9db0e321a9f4 | 172 | } |
kenjiArai | 1:9db0e321a9f4 | 173 | |
kenjiArai | 1:9db0e321a9f4 | 174 | void SerialBase::_deinit() |
kenjiArai | 1:9db0e321a9f4 | 175 | { |
kenjiArai | 1:9db0e321a9f4 | 176 | serial_free(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 177 | } |
kenjiArai | 1:9db0e321a9f4 | 178 | |
kenjiArai | 1:9db0e321a9f4 | 179 | void SerialBase::enable_input(bool enable) |
kenjiArai | 1:9db0e321a9f4 | 180 | { |
kenjiArai | 1:9db0e321a9f4 | 181 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 182 | if (_rx_enabled != enable) { |
kenjiArai | 1:9db0e321a9f4 | 183 | if (enable && !_tx_enabled) { |
kenjiArai | 1:9db0e321a9f4 | 184 | (this->*_init_func)(); |
kenjiArai | 1:9db0e321a9f4 | 185 | } |
kenjiArai | 1:9db0e321a9f4 | 186 | |
kenjiArai | 1:9db0e321a9f4 | 187 | core_util_critical_section_enter(); |
kenjiArai | 1:9db0e321a9f4 | 188 | if (enable) { |
kenjiArai | 1:9db0e321a9f4 | 189 | // Enable rx IRQ and lock deep sleep if a rx handler is attached |
kenjiArai | 1:9db0e321a9f4 | 190 | // (indicated by rx IRQ callback not NULL) |
kenjiArai | 1:9db0e321a9f4 | 191 | if (_irq[RxIrq]) { |
kenjiArai | 1:9db0e321a9f4 | 192 | _irq[RxIrq].call(); |
kenjiArai | 1:9db0e321a9f4 | 193 | sleep_manager_lock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 194 | serial_irq_set(&_serial, (SerialIrq)RxIrq, 1); |
kenjiArai | 1:9db0e321a9f4 | 195 | } |
kenjiArai | 1:9db0e321a9f4 | 196 | } else { |
kenjiArai | 1:9db0e321a9f4 | 197 | // Disable rx IRQ |
kenjiArai | 1:9db0e321a9f4 | 198 | serial_irq_set(&_serial, (SerialIrq)RxIrq, 0); |
kenjiArai | 1:9db0e321a9f4 | 199 | // Unlock deep sleep if a rx handler is attached |
kenjiArai | 1:9db0e321a9f4 | 200 | // (indicated by rx IRQ callback not NULL) |
kenjiArai | 1:9db0e321a9f4 | 201 | if (_irq[RxIrq]) { |
kenjiArai | 1:9db0e321a9f4 | 202 | sleep_manager_unlock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 203 | } |
kenjiArai | 1:9db0e321a9f4 | 204 | } |
kenjiArai | 1:9db0e321a9f4 | 205 | core_util_critical_section_exit(); |
kenjiArai | 1:9db0e321a9f4 | 206 | |
kenjiArai | 1:9db0e321a9f4 | 207 | _rx_enabled = enable; |
kenjiArai | 1:9db0e321a9f4 | 208 | |
kenjiArai | 1:9db0e321a9f4 | 209 | if (!enable && !_tx_enabled) { |
kenjiArai | 1:9db0e321a9f4 | 210 | _deinit(); |
kenjiArai | 1:9db0e321a9f4 | 211 | } |
kenjiArai | 1:9db0e321a9f4 | 212 | } |
kenjiArai | 1:9db0e321a9f4 | 213 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 214 | } |
kenjiArai | 1:9db0e321a9f4 | 215 | |
kenjiArai | 1:9db0e321a9f4 | 216 | void SerialBase::enable_output(bool enable) |
kenjiArai | 1:9db0e321a9f4 | 217 | { |
kenjiArai | 1:9db0e321a9f4 | 218 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 219 | if (_tx_enabled != enable) { |
kenjiArai | 1:9db0e321a9f4 | 220 | if (enable && !_rx_enabled) { |
kenjiArai | 1:9db0e321a9f4 | 221 | (this->*_init_func)(); |
kenjiArai | 1:9db0e321a9f4 | 222 | } |
kenjiArai | 1:9db0e321a9f4 | 223 | |
kenjiArai | 1:9db0e321a9f4 | 224 | core_util_critical_section_enter(); |
kenjiArai | 1:9db0e321a9f4 | 225 | if (enable) { |
kenjiArai | 1:9db0e321a9f4 | 226 | // Enable tx IRQ and lock deep sleep if a tx handler is attached |
kenjiArai | 1:9db0e321a9f4 | 227 | // (indicated by tx IRQ callback not NULL) |
kenjiArai | 1:9db0e321a9f4 | 228 | if (_irq[TxIrq]) { |
kenjiArai | 1:9db0e321a9f4 | 229 | _irq[TxIrq].call(); |
kenjiArai | 1:9db0e321a9f4 | 230 | sleep_manager_lock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 231 | serial_irq_set(&_serial, (SerialIrq)TxIrq, 1); |
kenjiArai | 1:9db0e321a9f4 | 232 | } |
kenjiArai | 1:9db0e321a9f4 | 233 | } else { |
kenjiArai | 1:9db0e321a9f4 | 234 | // Disable tx IRQ |
kenjiArai | 1:9db0e321a9f4 | 235 | serial_irq_set(&_serial, (SerialIrq)TxIrq, 0); |
kenjiArai | 1:9db0e321a9f4 | 236 | // Unlock deep sleep if a tx handler is attached |
kenjiArai | 1:9db0e321a9f4 | 237 | // (indicated by tx IRQ callback not NULL) |
kenjiArai | 1:9db0e321a9f4 | 238 | if (_irq[TxIrq]) { |
kenjiArai | 1:9db0e321a9f4 | 239 | sleep_manager_unlock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 240 | } |
kenjiArai | 1:9db0e321a9f4 | 241 | } |
kenjiArai | 1:9db0e321a9f4 | 242 | core_util_critical_section_exit(); |
kenjiArai | 1:9db0e321a9f4 | 243 | |
kenjiArai | 1:9db0e321a9f4 | 244 | _tx_enabled = enable; |
kenjiArai | 1:9db0e321a9f4 | 245 | |
kenjiArai | 1:9db0e321a9f4 | 246 | if (!enable && !_rx_enabled) { |
kenjiArai | 1:9db0e321a9f4 | 247 | _deinit(); |
kenjiArai | 1:9db0e321a9f4 | 248 | } |
kenjiArai | 1:9db0e321a9f4 | 249 | } |
kenjiArai | 1:9db0e321a9f4 | 250 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 251 | } |
kenjiArai | 1:9db0e321a9f4 | 252 | |
kenjiArai | 1:9db0e321a9f4 | 253 | void SerialBase::set_break() |
kenjiArai | 1:9db0e321a9f4 | 254 | { |
kenjiArai | 1:9db0e321a9f4 | 255 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 256 | serial_break_set(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 257 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 258 | } |
kenjiArai | 1:9db0e321a9f4 | 259 | |
kenjiArai | 1:9db0e321a9f4 | 260 | void SerialBase::clear_break() |
kenjiArai | 1:9db0e321a9f4 | 261 | { |
kenjiArai | 1:9db0e321a9f4 | 262 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 263 | serial_break_clear(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 264 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 265 | } |
kenjiArai | 1:9db0e321a9f4 | 266 | |
kenjiArai | 1:9db0e321a9f4 | 267 | void SerialBase::send_break() |
kenjiArai | 1:9db0e321a9f4 | 268 | { |
kenjiArai | 1:9db0e321a9f4 | 269 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 270 | // Wait for 1.5 frames before clearing the break condition |
kenjiArai | 1:9db0e321a9f4 | 271 | // This will have different effects on our platforms, but should |
kenjiArai | 1:9db0e321a9f4 | 272 | // ensure that we keep the break active for at least one frame. |
kenjiArai | 1:9db0e321a9f4 | 273 | // We consider a full frame (1 start bit + 8 data bits bits + |
kenjiArai | 1:9db0e321a9f4 | 274 | // 1 parity bit + 2 stop bits = 12 bits) for computation. |
kenjiArai | 1:9db0e321a9f4 | 275 | // One bit time (in us) = 1000000/_baud |
kenjiArai | 1:9db0e321a9f4 | 276 | // Twelve bits: 12000000/baud delay |
kenjiArai | 1:9db0e321a9f4 | 277 | // 1.5 frames: 18000000/baud delay |
kenjiArai | 1:9db0e321a9f4 | 278 | serial_break_set(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 279 | wait_us(18000000 / _baud); |
kenjiArai | 1:9db0e321a9f4 | 280 | serial_break_clear(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 281 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 282 | } |
kenjiArai | 1:9db0e321a9f4 | 283 | |
kenjiArai | 1:9db0e321a9f4 | 284 | void SerialBase::lock() |
kenjiArai | 1:9db0e321a9f4 | 285 | { |
kenjiArai | 1:9db0e321a9f4 | 286 | // Stub |
kenjiArai | 1:9db0e321a9f4 | 287 | } |
kenjiArai | 1:9db0e321a9f4 | 288 | |
kenjiArai | 1:9db0e321a9f4 | 289 | void SerialBase:: unlock() |
kenjiArai | 1:9db0e321a9f4 | 290 | { |
kenjiArai | 1:9db0e321a9f4 | 291 | // Stub |
kenjiArai | 1:9db0e321a9f4 | 292 | } |
kenjiArai | 1:9db0e321a9f4 | 293 | |
kenjiArai | 1:9db0e321a9f4 | 294 | SerialBase::~SerialBase() |
kenjiArai | 1:9db0e321a9f4 | 295 | { |
kenjiArai | 1:9db0e321a9f4 | 296 | // No lock needed in destructor |
kenjiArai | 1:9db0e321a9f4 | 297 | |
kenjiArai | 1:9db0e321a9f4 | 298 | // Detaching interrupts releases the sleep lock if it was locked |
kenjiArai | 1:9db0e321a9f4 | 299 | for (int irq = 0; irq < IrqCnt; irq++) { |
kenjiArai | 1:9db0e321a9f4 | 300 | attach(NULL, (IrqType)irq); |
kenjiArai | 1:9db0e321a9f4 | 301 | } |
kenjiArai | 1:9db0e321a9f4 | 302 | } |
kenjiArai | 1:9db0e321a9f4 | 303 | |
kenjiArai | 1:9db0e321a9f4 | 304 | #if DEVICE_SERIAL_FC |
kenjiArai | 1:9db0e321a9f4 | 305 | void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) |
kenjiArai | 1:9db0e321a9f4 | 306 | { |
kenjiArai | 1:9db0e321a9f4 | 307 | MBED_ASSERT(_static_pinmap == NULL); // this function must be used when serial object has been created using dynamic pin-map constructor |
kenjiArai | 1:9db0e321a9f4 | 308 | _set_flow_control_dp_func = &SerialBase::set_flow_control; |
kenjiArai | 1:9db0e321a9f4 | 309 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 310 | |
kenjiArai | 1:9db0e321a9f4 | 311 | _flow_type = type; |
kenjiArai | 1:9db0e321a9f4 | 312 | _flow1 = flow1; |
kenjiArai | 1:9db0e321a9f4 | 313 | _flow2 = flow2; |
kenjiArai | 1:9db0e321a9f4 | 314 | |
kenjiArai | 1:9db0e321a9f4 | 315 | FlowControl flow_type = (FlowControl)type; |
kenjiArai | 1:9db0e321a9f4 | 316 | switch (type) { |
kenjiArai | 1:9db0e321a9f4 | 317 | case RTS: |
kenjiArai | 1:9db0e321a9f4 | 318 | serial_set_flow_control(&_serial, flow_type, flow1, NC); |
kenjiArai | 1:9db0e321a9f4 | 319 | break; |
kenjiArai | 1:9db0e321a9f4 | 320 | |
kenjiArai | 1:9db0e321a9f4 | 321 | case CTS: |
kenjiArai | 1:9db0e321a9f4 | 322 | serial_set_flow_control(&_serial, flow_type, NC, flow1); |
kenjiArai | 1:9db0e321a9f4 | 323 | break; |
kenjiArai | 1:9db0e321a9f4 | 324 | |
kenjiArai | 1:9db0e321a9f4 | 325 | case RTSCTS: |
kenjiArai | 1:9db0e321a9f4 | 326 | case Disabled: |
kenjiArai | 1:9db0e321a9f4 | 327 | serial_set_flow_control(&_serial, flow_type, flow1, flow2); |
kenjiArai | 1:9db0e321a9f4 | 328 | break; |
kenjiArai | 1:9db0e321a9f4 | 329 | |
kenjiArai | 1:9db0e321a9f4 | 330 | default: |
kenjiArai | 1:9db0e321a9f4 | 331 | break; |
kenjiArai | 1:9db0e321a9f4 | 332 | } |
kenjiArai | 1:9db0e321a9f4 | 333 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 334 | } |
kenjiArai | 1:9db0e321a9f4 | 335 | |
kenjiArai | 1:9db0e321a9f4 | 336 | void SerialBase::set_flow_control(Flow type, const serial_fc_pinmap_t &static_pinmap) |
kenjiArai | 1:9db0e321a9f4 | 337 | { |
kenjiArai | 1:9db0e321a9f4 | 338 | MBED_ASSERT(_static_pinmap != NULL); // this function must be used when serial object has been created using static pin-map constructor |
kenjiArai | 1:9db0e321a9f4 | 339 | _set_flow_control_sp_func = &SerialBase::set_flow_control; |
kenjiArai | 1:9db0e321a9f4 | 340 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 341 | _static_pinmap_fc = &static_pinmap; |
kenjiArai | 1:9db0e321a9f4 | 342 | _flow_type = type; |
kenjiArai | 1:9db0e321a9f4 | 343 | FlowControl flow_type = (FlowControl)type; |
kenjiArai | 1:9db0e321a9f4 | 344 | serial_set_flow_control_direct(&_serial, flow_type, _static_pinmap_fc); |
kenjiArai | 1:9db0e321a9f4 | 345 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 346 | } |
kenjiArai | 1:9db0e321a9f4 | 347 | #endif |
kenjiArai | 1:9db0e321a9f4 | 348 | |
kenjiArai | 1:9db0e321a9f4 | 349 | #if DEVICE_SERIAL_ASYNCH |
kenjiArai | 1:9db0e321a9f4 | 350 | |
kenjiArai | 1:9db0e321a9f4 | 351 | int SerialBase::write(const uint8_t *buffer, int length, const event_callback_t &callback, int event) |
kenjiArai | 1:9db0e321a9f4 | 352 | { |
kenjiArai | 1:9db0e321a9f4 | 353 | int result = 0; |
kenjiArai | 1:9db0e321a9f4 | 354 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 355 | if (!serial_tx_active(&_serial) && !_tx_asynch_set) { |
kenjiArai | 1:9db0e321a9f4 | 356 | start_write((void *)buffer, length, 8, callback, event); |
kenjiArai | 1:9db0e321a9f4 | 357 | } else { |
kenjiArai | 1:9db0e321a9f4 | 358 | result = -1; // transaction ongoing |
kenjiArai | 1:9db0e321a9f4 | 359 | } |
kenjiArai | 1:9db0e321a9f4 | 360 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 361 | return result; |
kenjiArai | 1:9db0e321a9f4 | 362 | } |
kenjiArai | 1:9db0e321a9f4 | 363 | |
kenjiArai | 1:9db0e321a9f4 | 364 | int SerialBase::write(const uint16_t *buffer, int length, const event_callback_t &callback, int event) |
kenjiArai | 1:9db0e321a9f4 | 365 | { |
kenjiArai | 1:9db0e321a9f4 | 366 | int result = 0; |
kenjiArai | 1:9db0e321a9f4 | 367 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 368 | if (!serial_tx_active(&_serial) && !_tx_asynch_set) { |
kenjiArai | 1:9db0e321a9f4 | 369 | start_write((void *)buffer, length, 16, callback, event); |
kenjiArai | 1:9db0e321a9f4 | 370 | } else { |
kenjiArai | 1:9db0e321a9f4 | 371 | result = -1; // transaction ongoing |
kenjiArai | 1:9db0e321a9f4 | 372 | } |
kenjiArai | 1:9db0e321a9f4 | 373 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 374 | return result; |
kenjiArai | 1:9db0e321a9f4 | 375 | } |
kenjiArai | 1:9db0e321a9f4 | 376 | |
kenjiArai | 1:9db0e321a9f4 | 377 | void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event) |
kenjiArai | 1:9db0e321a9f4 | 378 | { |
kenjiArai | 1:9db0e321a9f4 | 379 | _tx_asynch_set = true; |
kenjiArai | 1:9db0e321a9f4 | 380 | _tx_callback = callback; |
kenjiArai | 1:9db0e321a9f4 | 381 | |
kenjiArai | 1:9db0e321a9f4 | 382 | _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); |
kenjiArai | 1:9db0e321a9f4 | 383 | sleep_manager_lock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 384 | serial_tx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, _tx_usage); |
kenjiArai | 1:9db0e321a9f4 | 385 | } |
kenjiArai | 1:9db0e321a9f4 | 386 | |
kenjiArai | 1:9db0e321a9f4 | 387 | void SerialBase::abort_write(void) |
kenjiArai | 1:9db0e321a9f4 | 388 | { |
kenjiArai | 1:9db0e321a9f4 | 389 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 390 | core_util_critical_section_enter(); |
kenjiArai | 1:9db0e321a9f4 | 391 | if (_tx_asynch_set) { |
kenjiArai | 1:9db0e321a9f4 | 392 | _tx_callback = NULL; |
kenjiArai | 1:9db0e321a9f4 | 393 | _tx_asynch_set = false; |
kenjiArai | 1:9db0e321a9f4 | 394 | serial_tx_abort_asynch(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 395 | sleep_manager_unlock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 396 | } |
kenjiArai | 1:9db0e321a9f4 | 397 | core_util_critical_section_exit(); |
kenjiArai | 1:9db0e321a9f4 | 398 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 399 | } |
kenjiArai | 1:9db0e321a9f4 | 400 | |
kenjiArai | 1:9db0e321a9f4 | 401 | void SerialBase::abort_read(void) |
kenjiArai | 1:9db0e321a9f4 | 402 | { |
kenjiArai | 1:9db0e321a9f4 | 403 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 404 | core_util_critical_section_enter(); |
kenjiArai | 1:9db0e321a9f4 | 405 | if (_rx_asynch_set) { |
kenjiArai | 1:9db0e321a9f4 | 406 | _rx_callback = NULL; |
kenjiArai | 1:9db0e321a9f4 | 407 | _rx_asynch_set = false; |
kenjiArai | 1:9db0e321a9f4 | 408 | serial_rx_abort_asynch(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 409 | sleep_manager_unlock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 410 | } |
kenjiArai | 1:9db0e321a9f4 | 411 | core_util_critical_section_exit(); |
kenjiArai | 1:9db0e321a9f4 | 412 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 413 | } |
kenjiArai | 1:9db0e321a9f4 | 414 | |
kenjiArai | 1:9db0e321a9f4 | 415 | int SerialBase::set_dma_usage_tx(DMAUsage usage) |
kenjiArai | 1:9db0e321a9f4 | 416 | { |
kenjiArai | 1:9db0e321a9f4 | 417 | if (serial_tx_active(&_serial)) { |
kenjiArai | 1:9db0e321a9f4 | 418 | return -1; |
kenjiArai | 1:9db0e321a9f4 | 419 | } |
kenjiArai | 1:9db0e321a9f4 | 420 | _tx_usage = usage; |
kenjiArai | 1:9db0e321a9f4 | 421 | return 0; |
kenjiArai | 1:9db0e321a9f4 | 422 | } |
kenjiArai | 1:9db0e321a9f4 | 423 | |
kenjiArai | 1:9db0e321a9f4 | 424 | int SerialBase::set_dma_usage_rx(DMAUsage usage) |
kenjiArai | 1:9db0e321a9f4 | 425 | { |
kenjiArai | 1:9db0e321a9f4 | 426 | if (serial_tx_active(&_serial)) { |
kenjiArai | 1:9db0e321a9f4 | 427 | return -1; |
kenjiArai | 1:9db0e321a9f4 | 428 | } |
kenjiArai | 1:9db0e321a9f4 | 429 | _rx_usage = usage; |
kenjiArai | 1:9db0e321a9f4 | 430 | return 0; |
kenjiArai | 1:9db0e321a9f4 | 431 | } |
kenjiArai | 1:9db0e321a9f4 | 432 | |
kenjiArai | 1:9db0e321a9f4 | 433 | int SerialBase::read(uint8_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match) |
kenjiArai | 1:9db0e321a9f4 | 434 | { |
kenjiArai | 1:9db0e321a9f4 | 435 | int result = 0; |
kenjiArai | 1:9db0e321a9f4 | 436 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 437 | if (!serial_rx_active(&_serial) && !_rx_asynch_set) { |
kenjiArai | 1:9db0e321a9f4 | 438 | start_read((void *)buffer, length, 8, callback, event, char_match); |
kenjiArai | 1:9db0e321a9f4 | 439 | } else { |
kenjiArai | 1:9db0e321a9f4 | 440 | result = -1; // transaction ongoing |
kenjiArai | 1:9db0e321a9f4 | 441 | } |
kenjiArai | 1:9db0e321a9f4 | 442 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 443 | return result; |
kenjiArai | 1:9db0e321a9f4 | 444 | } |
kenjiArai | 1:9db0e321a9f4 | 445 | |
kenjiArai | 1:9db0e321a9f4 | 446 | |
kenjiArai | 1:9db0e321a9f4 | 447 | int SerialBase::read(uint16_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match) |
kenjiArai | 1:9db0e321a9f4 | 448 | { |
kenjiArai | 1:9db0e321a9f4 | 449 | int result = 0; |
kenjiArai | 1:9db0e321a9f4 | 450 | lock(); |
kenjiArai | 1:9db0e321a9f4 | 451 | if (!serial_rx_active(&_serial) && !_rx_asynch_set) { |
kenjiArai | 1:9db0e321a9f4 | 452 | start_read((void *)buffer, length, 16, callback, event, char_match); |
kenjiArai | 1:9db0e321a9f4 | 453 | } else { |
kenjiArai | 1:9db0e321a9f4 | 454 | result = -1; // transaction ongoing |
kenjiArai | 1:9db0e321a9f4 | 455 | } |
kenjiArai | 1:9db0e321a9f4 | 456 | unlock(); |
kenjiArai | 1:9db0e321a9f4 | 457 | return result; |
kenjiArai | 1:9db0e321a9f4 | 458 | } |
kenjiArai | 1:9db0e321a9f4 | 459 | |
kenjiArai | 1:9db0e321a9f4 | 460 | |
kenjiArai | 1:9db0e321a9f4 | 461 | void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match) |
kenjiArai | 1:9db0e321a9f4 | 462 | { |
kenjiArai | 1:9db0e321a9f4 | 463 | _rx_asynch_set = true; |
kenjiArai | 1:9db0e321a9f4 | 464 | _rx_callback = callback; |
kenjiArai | 1:9db0e321a9f4 | 465 | _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); |
kenjiArai | 1:9db0e321a9f4 | 466 | sleep_manager_lock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 467 | serial_rx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, char_match, _rx_usage); |
kenjiArai | 1:9db0e321a9f4 | 468 | } |
kenjiArai | 1:9db0e321a9f4 | 469 | |
kenjiArai | 1:9db0e321a9f4 | 470 | void SerialBase::interrupt_handler_asynch(void) |
kenjiArai | 1:9db0e321a9f4 | 471 | { |
kenjiArai | 1:9db0e321a9f4 | 472 | int event = serial_irq_handler_asynch(&_serial); |
kenjiArai | 1:9db0e321a9f4 | 473 | int rx_event = event & SERIAL_EVENT_RX_MASK; |
kenjiArai | 1:9db0e321a9f4 | 474 | |
kenjiArai | 1:9db0e321a9f4 | 475 | if (_rx_asynch_set && rx_event) { |
kenjiArai | 1:9db0e321a9f4 | 476 | event_callback_t cb = _rx_callback; |
kenjiArai | 1:9db0e321a9f4 | 477 | _rx_asynch_set = false; |
kenjiArai | 1:9db0e321a9f4 | 478 | _rx_callback = NULL; |
kenjiArai | 1:9db0e321a9f4 | 479 | if (cb) { |
kenjiArai | 1:9db0e321a9f4 | 480 | cb.call(rx_event); |
kenjiArai | 1:9db0e321a9f4 | 481 | } |
kenjiArai | 1:9db0e321a9f4 | 482 | sleep_manager_unlock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 483 | } |
kenjiArai | 1:9db0e321a9f4 | 484 | |
kenjiArai | 1:9db0e321a9f4 | 485 | int tx_event = event & SERIAL_EVENT_TX_MASK; |
kenjiArai | 1:9db0e321a9f4 | 486 | if (_tx_asynch_set && tx_event) { |
kenjiArai | 1:9db0e321a9f4 | 487 | event_callback_t cb = _tx_callback; |
kenjiArai | 1:9db0e321a9f4 | 488 | _tx_asynch_set = false; |
kenjiArai | 1:9db0e321a9f4 | 489 | _tx_callback = NULL; |
kenjiArai | 1:9db0e321a9f4 | 490 | if (cb) { |
kenjiArai | 1:9db0e321a9f4 | 491 | cb.call(tx_event); |
kenjiArai | 1:9db0e321a9f4 | 492 | } |
kenjiArai | 1:9db0e321a9f4 | 493 | sleep_manager_unlock_deep_sleep(); |
kenjiArai | 1:9db0e321a9f4 | 494 | } |
kenjiArai | 1:9db0e321a9f4 | 495 | } |
kenjiArai | 1:9db0e321a9f4 | 496 | |
kenjiArai | 1:9db0e321a9f4 | 497 | #endif |
kenjiArai | 1:9db0e321a9f4 | 498 | |
kenjiArai | 1:9db0e321a9f4 | 499 | } // namespace mbed |
kenjiArai | 1:9db0e321a9f4 | 500 | |
kenjiArai | 1:9db0e321a9f4 | 501 | #endif |