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