mbed library sources

Fork of mbed-src by mbed official

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