mbed library sources. Supersedes mbed-src.
Dependents: Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more
SerialBase.cpp
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * SPDX-License-Identifier: Apache-2.0 00004 * 00005 * Licensed under the Apache License, Version 2.0 (the "License"); 00006 * you may not use this file except in compliance with the License. 00007 * You may obtain a copy of the License at 00008 * 00009 * http://www.apache.org/licenses/LICENSE-2.0 00010 * 00011 * Unless required by applicable law or agreed to in writing, software 00012 * distributed under the License is distributed on an "AS IS" BASIS, 00013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00014 * See the License for the specific language governing permissions and 00015 * limitations under the License. 00016 */ 00017 #include "drivers/SerialBase.h" 00018 #include "platform/mbed_wait_api.h" 00019 #include "platform/mbed_critical.h" 00020 #include "platform/mbed_power_mgmt.h" 00021 00022 #if DEVICE_SERIAL 00023 00024 namespace mbed { 00025 00026 SerialBase::SerialBase(PinName tx, PinName rx, int baud) : 00027 #if DEVICE_SERIAL_ASYNCH 00028 _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER), 00029 _rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL), 00030 _rx_callback(NULL), 00031 #endif 00032 _serial(), _baud(baud) 00033 { 00034 // No lock needed in the constructor 00035 00036 for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { 00037 _irq[i] = NULL; 00038 } 00039 00040 serial_init(&_serial, tx, rx); 00041 serial_baud(&_serial, _baud); 00042 serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); 00043 } 00044 00045 void SerialBase::baud(int baudrate) 00046 { 00047 lock(); 00048 serial_baud(&_serial, baudrate); 00049 _baud = baudrate; 00050 unlock(); 00051 } 00052 00053 void SerialBase::format(int bits, Parity parity, int stop_bits) 00054 { 00055 lock(); 00056 serial_format(&_serial, bits, (SerialParity)parity, stop_bits); 00057 unlock(); 00058 } 00059 00060 int SerialBase::readable() 00061 { 00062 lock(); 00063 int ret = serial_readable(&_serial); 00064 unlock(); 00065 return ret; 00066 } 00067 00068 00069 int SerialBase::writeable() 00070 { 00071 lock(); 00072 int ret = serial_writable(&_serial); 00073 unlock(); 00074 return ret; 00075 } 00076 00077 void SerialBase::attach(Callback<void()> func, IrqType type) 00078 { 00079 lock(); 00080 // Disable interrupts when attaching interrupt handler 00081 core_util_critical_section_enter(); 00082 if (func) { 00083 // lock deep sleep only the first time 00084 if (!_irq[type]) { 00085 sleep_manager_lock_deep_sleep(); 00086 } 00087 _irq[type] = func; 00088 serial_irq_set(&_serial, (SerialIrq)type, 1); 00089 } else { 00090 // unlock deep sleep only the first time 00091 if (_irq[type]) { 00092 sleep_manager_unlock_deep_sleep(); 00093 } 00094 _irq[type] = NULL; 00095 serial_irq_set(&_serial, (SerialIrq)type, 0); 00096 } 00097 core_util_critical_section_exit(); 00098 unlock(); 00099 } 00100 00101 void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) 00102 { 00103 SerialBase *handler = (SerialBase *)id; 00104 if (handler->_irq[irq_type]) { 00105 handler->_irq[irq_type](); 00106 } 00107 } 00108 00109 int SerialBase::_base_getc() 00110 { 00111 // Mutex is already held 00112 return serial_getc(&_serial); 00113 } 00114 00115 int SerialBase::_base_putc(int c) 00116 { 00117 // Mutex is already held 00118 serial_putc(&_serial, c); 00119 return c; 00120 } 00121 00122 void SerialBase::set_break() 00123 { 00124 lock(); 00125 serial_break_set(&_serial); 00126 unlock(); 00127 } 00128 00129 void SerialBase::clear_break() 00130 { 00131 lock(); 00132 serial_break_clear(&_serial); 00133 unlock(); 00134 } 00135 00136 void SerialBase::send_break() 00137 { 00138 lock(); 00139 // Wait for 1.5 frames before clearing the break condition 00140 // This will have different effects on our platforms, but should 00141 // ensure that we keep the break active for at least one frame. 00142 // We consider a full frame (1 start bit + 8 data bits bits + 00143 // 1 parity bit + 2 stop bits = 12 bits) for computation. 00144 // One bit time (in us) = 1000000/_baud 00145 // Twelve bits: 12000000/baud delay 00146 // 1.5 frames: 18000000/baud delay 00147 serial_break_set(&_serial); 00148 wait_us(18000000 / _baud); 00149 serial_break_clear(&_serial); 00150 unlock(); 00151 } 00152 00153 void SerialBase::lock() 00154 { 00155 // Stub 00156 } 00157 00158 void SerialBase:: unlock() 00159 { 00160 // Stub 00161 } 00162 00163 SerialBase::~SerialBase() 00164 { 00165 // No lock needed in destructor 00166 00167 // Detaching interrupts releases the sleep lock if it was locked 00168 for (int irq = 0; irq < IrqCnt; irq++) { 00169 attach(NULL, (IrqType)irq); 00170 } 00171 } 00172 00173 #if DEVICE_SERIAL_FC 00174 void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) 00175 { 00176 lock(); 00177 FlowControl flow_type = (FlowControl)type; 00178 switch (type) { 00179 case RTS: 00180 serial_set_flow_control(&_serial, flow_type, flow1, NC); 00181 break; 00182 00183 case CTS: 00184 serial_set_flow_control(&_serial, flow_type, NC, flow1); 00185 break; 00186 00187 case RTSCTS: 00188 case Disabled: 00189 serial_set_flow_control(&_serial, flow_type, flow1, flow2); 00190 break; 00191 00192 default: 00193 break; 00194 } 00195 unlock(); 00196 } 00197 #endif 00198 00199 #if DEVICE_SERIAL_ASYNCH 00200 00201 int SerialBase::write(const uint8_t *buffer, int length, const event_callback_t &callback, int event) 00202 { 00203 if (serial_tx_active(&_serial)) { 00204 return -1; // transaction ongoing 00205 } 00206 start_write((void *)buffer, length, 8, callback, event); 00207 return 0; 00208 } 00209 00210 int SerialBase::write(const uint16_t *buffer, int length, const event_callback_t &callback, int event) 00211 { 00212 if (serial_tx_active(&_serial)) { 00213 return -1; // transaction ongoing 00214 } 00215 start_write((void *)buffer, length, 16, callback, event); 00216 return 0; 00217 } 00218 00219 void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event) 00220 { 00221 _tx_callback = callback; 00222 00223 _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); 00224 sleep_manager_lock_deep_sleep(); 00225 serial_tx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, _tx_usage); 00226 } 00227 00228 void SerialBase::abort_write(void) 00229 { 00230 // rx might still be active 00231 if (_rx_callback) { 00232 sleep_manager_unlock_deep_sleep(); 00233 } 00234 _tx_callback = NULL; 00235 serial_tx_abort_asynch(&_serial); 00236 } 00237 00238 void SerialBase::abort_read(void) 00239 { 00240 // tx might still be active 00241 if (_tx_callback) { 00242 sleep_manager_unlock_deep_sleep(); 00243 } 00244 _rx_callback = NULL; 00245 serial_rx_abort_asynch(&_serial); 00246 } 00247 00248 int SerialBase::set_dma_usage_tx(DMAUsage usage) 00249 { 00250 if (serial_tx_active(&_serial)) { 00251 return -1; 00252 } 00253 _tx_usage = usage; 00254 return 0; 00255 } 00256 00257 int SerialBase::set_dma_usage_rx(DMAUsage usage) 00258 { 00259 if (serial_tx_active(&_serial)) { 00260 return -1; 00261 } 00262 _rx_usage = usage; 00263 return 0; 00264 } 00265 00266 int SerialBase::read(uint8_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match) 00267 { 00268 if (serial_rx_active(&_serial)) { 00269 return -1; // transaction ongoing 00270 } 00271 start_read((void *)buffer, length, 8, callback, event, char_match); 00272 return 0; 00273 } 00274 00275 00276 int SerialBase::read(uint16_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match) 00277 { 00278 if (serial_rx_active(&_serial)) { 00279 return -1; // transaction ongoing 00280 } 00281 start_read((void *)buffer, length, 16, callback, event, char_match); 00282 return 0; 00283 } 00284 00285 00286 void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match) 00287 { 00288 _rx_callback = callback; 00289 _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); 00290 sleep_manager_lock_deep_sleep(); 00291 serial_rx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, char_match, _rx_usage); 00292 } 00293 00294 void SerialBase::interrupt_handler_asynch(void) 00295 { 00296 int event = serial_irq_handler_asynch(&_serial); 00297 int rx_event = event & SERIAL_EVENT_RX_MASK; 00298 bool unlock_deepsleep = false; 00299 00300 if (_rx_callback && rx_event) { 00301 unlock_deepsleep = true; 00302 _rx_callback.call(rx_event); 00303 } 00304 00305 int tx_event = event & SERIAL_EVENT_TX_MASK; 00306 if (_tx_callback && tx_event) { 00307 unlock_deepsleep = true; 00308 _tx_callback.call(tx_event); 00309 } 00310 // unlock if tx or rx events are generated 00311 if (unlock_deepsleep) { 00312 sleep_manager_unlock_deep_sleep(); 00313 } 00314 } 00315 00316 #endif 00317 00318 } // namespace mbed 00319 00320 #endif
Generated on Tue Jul 12 2022 20:41:15 by 1.7.2