Marco Zecchini
/
Example_RTOS
Rtos API example
Embed:
(wiki syntax)
Show/hide line numbers
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_sleep.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 Sun Jul 17 2022 08:25:30 by 1.7.2