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