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