mbed library sources. Supersedes mbed-src.

Dependents:   Nucleo_Hello_Encoder BLE_iBeaconScan AM1805_DEMO DISCO-F429ZI_ExportTemplate1 ... more

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers SerialBase.cpp Source File

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