Inherit from Serial and use software buffers for TX and RX. This allows the UART peripherals to operate in a IRQ driven mode. Overrides most (but not all) stdio functions as Serial did
Dependents: buffered_serial_test BLE_Police_HRM evena_BLE_Police_HRM df-2014-workshop-rfid-case-generator-k64f ... more
Example
#include "mbed.h" #include "BufferedSerial.h" BufferedSerial pc(USBTX, USBRX); int main() { pc.baud(115200); while(1) { Timer s; s.start(); pc.printf("Hello World - buff\n"); int buffered_time = s.read_us(); wait(0.1f); // give time for the buffer to empty s.reset(); printf("Hello World - poll\n"); int polled_time = s.read_us(); s.stop(); wait(0.1f); // give time for the buffer to empty pc.printf("printf buffered took %d us\n", buffered_time); pc.printf("printf polled took %d us\n", polled_time); wait(0.5f); } }
Diff: BufferedSerial.cpp
- Revision:
- 4:2ba4d2e1f05d
- Parent:
- 3:6b76fcf27545
- Child:
- 6:8287e83943f0
--- a/BufferedSerial.cpp Wed Jun 12 20:40:15 2013 +0000 +++ b/BufferedSerial.cpp Mon Dec 30 18:16:39 2013 +0000 @@ -3,7 +3,7 @@ * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX * @author sam grove * @version 1.0 - * @see + * @see * * Copyright (c) 2013 * @@ -21,15 +21,13 @@ */ #include "BufferedSerial.h" -#include "LogUtil.h" #include <stdarg.h> BufferedSerial::BufferedSerial(PinName tx, PinName rx, const char* name) : Serial(tx, rx, name) { Serial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq); - Serial::attach(this, &BufferedSerial::txIrq, Serial::TxIrq); - + return; } @@ -37,7 +35,7 @@ { Serial::attach(NULL, Serial::RxIrq); Serial::attach(NULL, Serial::TxIrq); - + return; } @@ -60,21 +58,20 @@ { _txbuf = (char)c; BufferedSerial::prime(); - + return c; } int BufferedSerial::puts(const char *s) { const char* ptr = s; - - while(*(ptr) != 0) - { + + while(*(ptr) != 0) { _txbuf = *(ptr++); } _txbuf = '\n'; // done per puts definition BufferedSerial::prime(); - + return (ptr - s) + 1; } @@ -82,18 +79,17 @@ { char buf[256] = {0}; int r = 0; - + va_list arg; va_start(arg, format); r = vsprintf(buf, format, arg); // this may not hit the heap but should alert the user anyways - if(r > sizeof(buf)) - { - ERROR("Buffer Overflow on the Stack Occured!\n"); + if(r > sizeof(buf)) { + error("%s %d buffer overwrite!\n", __FILE__, __LINE__); } + va_end(arg); r = BufferedSerial::write(buf, r); - va_end(arg); - + return r; } @@ -101,49 +97,51 @@ { const char* ptr = (const char*)s; const char* end = ptr + length; - - while (ptr != end) - { + + while (ptr != end) { _txbuf = *(ptr++); } BufferedSerial::prime(); - - return ptr - (const char*)s; + + return ptr - (const char*)s; } void BufferedSerial::rxIrq(void) { // read from the peripheral and make sure something is available - if(serial_readable(&_serial)) - { + if(serial_readable(&_serial)) { _rxbuf = serial_getc(&_serial); // if so load them into a buffer } - + return; } void BufferedSerial::txIrq(void) { // see if there is room in the hardware fifo and if something is in the software fifo - while(serial_writable(&_serial) && _txbuf.available()) - { - serial_putc(&_serial, (int)_txbuf.get()); + while(serial_writable(&_serial)) { + if(_txbuf.available()) { + serial_putc(&_serial, (int)_txbuf.get()); + } else { + // disable the TX interrupt when there is nothing left to send + Serial::attach(NULL, Serial::TxIrq); + break; + } } - + return; } void BufferedSerial::prime(void) { // if already busy then the irq will pick this up - if(serial_writable(&_serial)) - { - Serial::attach(NULL, Serial::TxIrq); // make sure not to cause contention in the irq + if(serial_writable(&_serial)) { + Serial::attach(NULL, Serial::TxIrq); // make sure not to cause contention in the irq BufferedSerial::txIrq(); // only write to hardware in one place Serial::attach(this, &BufferedSerial::txIrq, Serial::TxIrq); } - + return; }