Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: TYBLE16_simple_data_logger TYBLE16_MP3_Air
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), 00029 #endif 00030 _baud(baud), 00031 _tx_pin(tx), 00032 _rx_pin(rx), 00033 _init_func(&SerialBase::_init) 00034 { 00035 // No lock needed in the constructor 00036 00037 for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { 00038 _irq[i] = NULL; 00039 } 00040 00041 (this->*_init_func)(); 00042 } 00043 00044 SerialBase::SerialBase(const serial_pinmap_t &static_pinmap, int baud) : 00045 #if DEVICE_SERIAL_ASYNCH 00046 _thunk_irq(this), _tx_usage(DMA_USAGE_NEVER), 00047 _rx_usage(DMA_USAGE_NEVER), _tx_callback(NULL), 00048 _rx_callback(NULL), _tx_asynch_set(false), 00049 _rx_asynch_set(false), 00050 #endif 00051 _serial(), 00052 _baud(baud), 00053 _tx_pin(static_pinmap.tx_pin), 00054 _rx_pin(static_pinmap.rx_pin), 00055 _static_pinmap(&static_pinmap), 00056 _init_func(&SerialBase::_init_direct) 00057 { 00058 // No lock needed in the constructor 00059 00060 for (size_t i = 0; i < sizeof _irq / sizeof _irq[0]; i++) { 00061 _irq[i] = NULL; 00062 } 00063 00064 (this->*_init_func)(); 00065 } 00066 00067 void SerialBase::baud(int baudrate) 00068 { 00069 lock(); 00070 serial_baud(&_serial, baudrate); 00071 _baud = baudrate; 00072 unlock(); 00073 } 00074 00075 void SerialBase::format(int bits, Parity parity, int stop_bits) 00076 { 00077 lock(); 00078 serial_format(&_serial, bits, (SerialParity)parity, stop_bits); 00079 unlock(); 00080 } 00081 00082 int SerialBase::readable() 00083 { 00084 lock(); 00085 int ret = serial_readable(&_serial); 00086 unlock(); 00087 return ret; 00088 } 00089 00090 00091 int SerialBase::writeable() 00092 { 00093 lock(); 00094 int ret = serial_writable(&_serial); 00095 unlock(); 00096 return ret; 00097 } 00098 00099 void SerialBase::attach(Callback<void()> func, IrqType type) 00100 { 00101 lock(); 00102 const bool enabled { (_rx_enabled &&(type == RxIrq)) || (_tx_enabled &&(type == TxIrq)) }; 00103 // If corresponding direction is not enabled only update the handler 00104 if (!enabled) { 00105 _irq[type] = func; 00106 } else { 00107 // Disable interrupts when attaching interrupt handler 00108 core_util_critical_section_enter(); 00109 if (func) { 00110 // lock deep sleep only the first time 00111 if (!_irq[type]) { 00112 sleep_manager_lock_deep_sleep(); 00113 } 00114 _irq[type] = func; 00115 serial_irq_set(&_serial, (SerialIrq)type, 1); 00116 } else { 00117 // unlock deep sleep only the first time 00118 if (_irq[type]) { 00119 sleep_manager_unlock_deep_sleep(); 00120 } 00121 _irq[type] = NULL; 00122 serial_irq_set(&_serial, (SerialIrq)type, 0); 00123 } 00124 core_util_critical_section_exit(); 00125 } 00126 unlock(); 00127 } 00128 00129 void SerialBase::_irq_handler(uint32_t id, SerialIrq irq_type) 00130 { 00131 SerialBase *handler = (SerialBase *)id; 00132 if (handler->_irq[irq_type]) { 00133 handler->_irq[irq_type](); 00134 } 00135 } 00136 00137 int SerialBase::_base_getc() 00138 { 00139 // Mutex is already held 00140 return serial_getc(&_serial); 00141 } 00142 00143 int SerialBase::_base_putc(int c) 00144 { 00145 // Mutex is already held 00146 serial_putc(&_serial, c); 00147 return c; 00148 } 00149 00150 void SerialBase::_init() 00151 { 00152 serial_init(&_serial, _tx_pin, _rx_pin); 00153 #if DEVICE_SERIAL_FC 00154 if (_set_flow_control_dp_func) { 00155 (this->*_set_flow_control_dp_func)(_flow_type, _flow1, _flow2); 00156 } 00157 #endif 00158 serial_baud(&_serial, _baud); 00159 serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); 00160 } 00161 00162 void SerialBase::_init_direct() 00163 { 00164 serial_init_direct(&_serial, _static_pinmap); 00165 #if DEVICE_SERIAL_FC 00166 if (_static_pinmap_fc && _set_flow_control_dp_func) { 00167 (this->*_set_flow_control_sp_func)(_flow_type, *_static_pinmap_fc); 00168 } 00169 #endif 00170 serial_baud(&_serial, _baud); 00171 serial_irq_handler(&_serial, SerialBase::_irq_handler, (uint32_t)this); 00172 } 00173 00174 void SerialBase::_deinit() 00175 { 00176 serial_free(&_serial); 00177 } 00178 00179 void SerialBase::enable_input(bool enable) 00180 { 00181 lock(); 00182 if (_rx_enabled != enable) { 00183 if (enable && !_tx_enabled) { 00184 (this->*_init_func)(); 00185 } 00186 00187 core_util_critical_section_enter(); 00188 if (enable) { 00189 // Enable rx IRQ and lock deep sleep if a rx handler is attached 00190 // (indicated by rx IRQ callback not NULL) 00191 if (_irq[RxIrq]) { 00192 _irq[RxIrq].call(); 00193 sleep_manager_lock_deep_sleep(); 00194 serial_irq_set(&_serial, (SerialIrq)RxIrq, 1); 00195 } 00196 } else { 00197 // Disable rx IRQ 00198 serial_irq_set(&_serial, (SerialIrq)RxIrq, 0); 00199 // Unlock deep sleep if a rx handler is attached 00200 // (indicated by rx IRQ callback not NULL) 00201 if (_irq[RxIrq]) { 00202 sleep_manager_unlock_deep_sleep(); 00203 } 00204 } 00205 core_util_critical_section_exit(); 00206 00207 _rx_enabled = enable; 00208 00209 if (!enable && !_tx_enabled) { 00210 _deinit(); 00211 } 00212 } 00213 unlock(); 00214 } 00215 00216 void SerialBase::enable_output(bool enable) 00217 { 00218 lock(); 00219 if (_tx_enabled != enable) { 00220 if (enable && !_rx_enabled) { 00221 (this->*_init_func)(); 00222 } 00223 00224 core_util_critical_section_enter(); 00225 if (enable) { 00226 // Enable tx IRQ and lock deep sleep if a tx handler is attached 00227 // (indicated by tx IRQ callback not NULL) 00228 if (_irq[TxIrq]) { 00229 _irq[TxIrq].call(); 00230 sleep_manager_lock_deep_sleep(); 00231 serial_irq_set(&_serial, (SerialIrq)TxIrq, 1); 00232 } 00233 } else { 00234 // Disable tx IRQ 00235 serial_irq_set(&_serial, (SerialIrq)TxIrq, 0); 00236 // Unlock deep sleep if a tx handler is attached 00237 // (indicated by tx IRQ callback not NULL) 00238 if (_irq[TxIrq]) { 00239 sleep_manager_unlock_deep_sleep(); 00240 } 00241 } 00242 core_util_critical_section_exit(); 00243 00244 _tx_enabled = enable; 00245 00246 if (!enable && !_rx_enabled) { 00247 _deinit(); 00248 } 00249 } 00250 unlock(); 00251 } 00252 00253 void SerialBase::set_break() 00254 { 00255 lock(); 00256 serial_break_set(&_serial); 00257 unlock(); 00258 } 00259 00260 void SerialBase::clear_break() 00261 { 00262 lock(); 00263 serial_break_clear(&_serial); 00264 unlock(); 00265 } 00266 00267 void SerialBase::send_break() 00268 { 00269 lock(); 00270 // Wait for 1.5 frames before clearing the break condition 00271 // This will have different effects on our platforms, but should 00272 // ensure that we keep the break active for at least one frame. 00273 // We consider a full frame (1 start bit + 8 data bits bits + 00274 // 1 parity bit + 2 stop bits = 12 bits) for computation. 00275 // One bit time (in us) = 1000000/_baud 00276 // Twelve bits: 12000000/baud delay 00277 // 1.5 frames: 18000000/baud delay 00278 serial_break_set(&_serial); 00279 wait_us(18000000 / _baud); 00280 serial_break_clear(&_serial); 00281 unlock(); 00282 } 00283 00284 void SerialBase::lock() 00285 { 00286 // Stub 00287 } 00288 00289 void SerialBase:: unlock() 00290 { 00291 // Stub 00292 } 00293 00294 SerialBase::~SerialBase() 00295 { 00296 // No lock needed in destructor 00297 00298 // Detaching interrupts releases the sleep lock if it was locked 00299 for (int irq = 0; irq < IrqCnt; irq++) { 00300 attach(NULL, (IrqType)irq); 00301 } 00302 } 00303 00304 #if DEVICE_SERIAL_FC 00305 void SerialBase::set_flow_control(Flow type, PinName flow1, PinName flow2) 00306 { 00307 MBED_ASSERT(_static_pinmap == NULL); // this function must be used when serial object has been created using dynamic pin-map constructor 00308 _set_flow_control_dp_func = &SerialBase::set_flow_control; 00309 lock(); 00310 00311 _flow_type = type; 00312 _flow1 = flow1; 00313 _flow2 = flow2; 00314 00315 FlowControl flow_type = (FlowControl)type; 00316 switch (type) { 00317 case RTS: 00318 serial_set_flow_control(&_serial, flow_type, flow1, NC); 00319 break; 00320 00321 case CTS: 00322 serial_set_flow_control(&_serial, flow_type, NC, flow1); 00323 break; 00324 00325 case RTSCTS: 00326 case Disabled: 00327 serial_set_flow_control(&_serial, flow_type, flow1, flow2); 00328 break; 00329 00330 default: 00331 break; 00332 } 00333 unlock(); 00334 } 00335 00336 void SerialBase::set_flow_control(Flow type, const serial_fc_pinmap_t &static_pinmap) 00337 { 00338 MBED_ASSERT(_static_pinmap != NULL); // this function must be used when serial object has been created using static pin-map constructor 00339 _set_flow_control_sp_func = &SerialBase::set_flow_control; 00340 lock(); 00341 _static_pinmap_fc = &static_pinmap; 00342 _flow_type = type; 00343 FlowControl flow_type = (FlowControl)type; 00344 serial_set_flow_control_direct(&_serial, flow_type, _static_pinmap_fc); 00345 unlock(); 00346 } 00347 #endif 00348 00349 #if DEVICE_SERIAL_ASYNCH 00350 00351 int SerialBase::write(const uint8_t *buffer, int length, const event_callback_t &callback, int event) 00352 { 00353 int result = 0; 00354 lock(); 00355 if (!serial_tx_active(&_serial) && !_tx_asynch_set) { 00356 start_write((void *)buffer, length, 8, callback, event); 00357 } else { 00358 result = -1; // transaction ongoing 00359 } 00360 unlock(); 00361 return result; 00362 } 00363 00364 int SerialBase::write(const uint16_t *buffer, int length, const event_callback_t &callback, int event) 00365 { 00366 int result = 0; 00367 lock(); 00368 if (!serial_tx_active(&_serial) && !_tx_asynch_set) { 00369 start_write((void *)buffer, length, 16, callback, event); 00370 } else { 00371 result = -1; // transaction ongoing 00372 } 00373 unlock(); 00374 return result; 00375 } 00376 00377 void SerialBase::start_write(const void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event) 00378 { 00379 _tx_asynch_set = true; 00380 _tx_callback = callback; 00381 00382 _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); 00383 sleep_manager_lock_deep_sleep(); 00384 serial_tx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, _tx_usage); 00385 } 00386 00387 void SerialBase::abort_write(void) 00388 { 00389 lock(); 00390 core_util_critical_section_enter(); 00391 if (_tx_asynch_set) { 00392 _tx_callback = NULL; 00393 _tx_asynch_set = false; 00394 serial_tx_abort_asynch(&_serial); 00395 sleep_manager_unlock_deep_sleep(); 00396 } 00397 core_util_critical_section_exit(); 00398 unlock(); 00399 } 00400 00401 void SerialBase::abort_read(void) 00402 { 00403 lock(); 00404 core_util_critical_section_enter(); 00405 if (_rx_asynch_set) { 00406 _rx_callback = NULL; 00407 _rx_asynch_set = false; 00408 serial_rx_abort_asynch(&_serial); 00409 sleep_manager_unlock_deep_sleep(); 00410 } 00411 core_util_critical_section_exit(); 00412 unlock(); 00413 } 00414 00415 int SerialBase::set_dma_usage_tx(DMAUsage usage) 00416 { 00417 if (serial_tx_active(&_serial)) { 00418 return -1; 00419 } 00420 _tx_usage = usage; 00421 return 0; 00422 } 00423 00424 int SerialBase::set_dma_usage_rx(DMAUsage usage) 00425 { 00426 if (serial_tx_active(&_serial)) { 00427 return -1; 00428 } 00429 _rx_usage = usage; 00430 return 0; 00431 } 00432 00433 int SerialBase::read(uint8_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match) 00434 { 00435 int result = 0; 00436 lock(); 00437 if (!serial_rx_active(&_serial) && !_rx_asynch_set) { 00438 start_read((void *)buffer, length, 8, callback, event, char_match); 00439 } else { 00440 result = -1; // transaction ongoing 00441 } 00442 unlock(); 00443 return result; 00444 } 00445 00446 00447 int SerialBase::read(uint16_t *buffer, int length, const event_callback_t &callback, int event, unsigned char char_match) 00448 { 00449 int result = 0; 00450 lock(); 00451 if (!serial_rx_active(&_serial) && !_rx_asynch_set) { 00452 start_read((void *)buffer, length, 16, callback, event, char_match); 00453 } else { 00454 result = -1; // transaction ongoing 00455 } 00456 unlock(); 00457 return result; 00458 } 00459 00460 00461 void SerialBase::start_read(void *buffer, int buffer_size, char buffer_width, const event_callback_t &callback, int event, unsigned char char_match) 00462 { 00463 _rx_asynch_set = true; 00464 _rx_callback = callback; 00465 _thunk_irq.callback(&SerialBase::interrupt_handler_asynch); 00466 sleep_manager_lock_deep_sleep(); 00467 serial_rx_asynch(&_serial, buffer, buffer_size, buffer_width, _thunk_irq.entry(), event, char_match, _rx_usage); 00468 } 00469 00470 void SerialBase::interrupt_handler_asynch(void) 00471 { 00472 int event = serial_irq_handler_asynch(&_serial); 00473 int rx_event = event & SERIAL_EVENT_RX_MASK; 00474 00475 if (_rx_asynch_set && rx_event) { 00476 event_callback_t cb = _rx_callback; 00477 _rx_asynch_set = false; 00478 _rx_callback = NULL; 00479 if (cb) { 00480 cb.call(rx_event); 00481 } 00482 sleep_manager_unlock_deep_sleep(); 00483 } 00484 00485 int tx_event = event & SERIAL_EVENT_TX_MASK; 00486 if (_tx_asynch_set && tx_event) { 00487 event_callback_t cb = _tx_callback; 00488 _tx_asynch_set = false; 00489 _tx_callback = NULL; 00490 if (cb) { 00491 cb.call(tx_event); 00492 } 00493 sleep_manager_unlock_deep_sleep(); 00494 } 00495 } 00496 00497 #endif 00498 00499 } // namespace mbed 00500 00501 #endif
Generated on Tue Jul 12 2022 13:54:49 by
1.7.2