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

Dependencies:   Buffer

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);
     }
 }
Committer:
sam_grove
Date:
Fri May 24 22:00:26 2013 +0000
Revision:
2:7e8a450a9101
Parent:
1:57a11fb5d529
Child:
3:6b76fcf27545
Override virtual member write. Better management of prime to avoid contentious writes under heavy traffic. updated puts to add \n per stdlib puts definition

Who changed what in which revision?

UserRevisionLine numberNew contents of line
sam_grove 0:a977d0a3d81e 1 /**
sam_grove 0:a977d0a3d81e 2 * @file BufferedSerial.cpp
sam_grove 0:a977d0a3d81e 3 * @brief Software Buffer - Extends mbed Serial functionallity adding irq driven TX and RX
sam_grove 0:a977d0a3d81e 4 * @author sam grove
sam_grove 0:a977d0a3d81e 5 * @version 1.0
sam_grove 0:a977d0a3d81e 6 * @see
sam_grove 0:a977d0a3d81e 7 *
sam_grove 0:a977d0a3d81e 8 * Copyright (c) 2013
sam_grove 0:a977d0a3d81e 9 *
sam_grove 0:a977d0a3d81e 10 * Licensed under the Apache License, Version 2.0 (the "License");
sam_grove 0:a977d0a3d81e 11 * you may not use this file except in compliance with the License.
sam_grove 0:a977d0a3d81e 12 * You may obtain a copy of the License at
sam_grove 0:a977d0a3d81e 13 *
sam_grove 0:a977d0a3d81e 14 * http://www.apache.org/licenses/LICENSE-2.0
sam_grove 0:a977d0a3d81e 15 *
sam_grove 0:a977d0a3d81e 16 * Unless required by applicable law or agreed to in writing, software
sam_grove 0:a977d0a3d81e 17 * distributed under the License is distributed on an "AS IS" BASIS,
sam_grove 0:a977d0a3d81e 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
sam_grove 0:a977d0a3d81e 19 * See the License for the specific language governing permissions and
sam_grove 0:a977d0a3d81e 20 * limitations under the License.
sam_grove 0:a977d0a3d81e 21 */
sam_grove 0:a977d0a3d81e 22
sam_grove 0:a977d0a3d81e 23 #include "BufferedSerial.h"
sam_grove 0:a977d0a3d81e 24 #include "LogUtil.h"
sam_grove 0:a977d0a3d81e 25 #include <stdarg.h>
sam_grove 0:a977d0a3d81e 26
sam_grove 0:a977d0a3d81e 27 BufferedSerial::BufferedSerial(PinName tx, PinName rx, const char* name)
sam_grove 0:a977d0a3d81e 28 : Serial(tx, rx, name)
sam_grove 0:a977d0a3d81e 29 {
sam_grove 0:a977d0a3d81e 30 Serial::attach(this, &BufferedSerial::rxIrq, Serial::RxIrq);
sam_grove 0:a977d0a3d81e 31 Serial::attach(this, &BufferedSerial::txIrq, Serial::TxIrq);
sam_grove 0:a977d0a3d81e 32
sam_grove 0:a977d0a3d81e 33 return;
sam_grove 0:a977d0a3d81e 34 }
sam_grove 0:a977d0a3d81e 35
sam_grove 0:a977d0a3d81e 36 BufferedSerial::~BufferedSerial(void)
sam_grove 0:a977d0a3d81e 37 {
sam_grove 0:a977d0a3d81e 38 Serial::attach(NULL, Serial::RxIrq);
sam_grove 0:a977d0a3d81e 39 Serial::attach(NULL, Serial::TxIrq);
sam_grove 0:a977d0a3d81e 40
sam_grove 0:a977d0a3d81e 41 return;
sam_grove 0:a977d0a3d81e 42 }
sam_grove 0:a977d0a3d81e 43
sam_grove 0:a977d0a3d81e 44 int BufferedSerial::readable(void)
sam_grove 0:a977d0a3d81e 45 {
sam_grove 0:a977d0a3d81e 46 return _rxbuf.available(); // note: look if things are in the buffer
sam_grove 0:a977d0a3d81e 47 }
sam_grove 0:a977d0a3d81e 48
sam_grove 0:a977d0a3d81e 49 int BufferedSerial::writeable(void)
sam_grove 0:a977d0a3d81e 50 {
sam_grove 0:a977d0a3d81e 51 return 1; // buffer allows overwriting by design, always true
sam_grove 0:a977d0a3d81e 52 }
sam_grove 0:a977d0a3d81e 53
sam_grove 0:a977d0a3d81e 54 int BufferedSerial::getc(void)
sam_grove 0:a977d0a3d81e 55 {
sam_grove 0:a977d0a3d81e 56 return _rxbuf; // note: pulling from the buffer
sam_grove 0:a977d0a3d81e 57 }
sam_grove 0:a977d0a3d81e 58
sam_grove 0:a977d0a3d81e 59 int BufferedSerial::putc(int c)
sam_grove 0:a977d0a3d81e 60 {
sam_grove 0:a977d0a3d81e 61 _txbuf = (char)c;
sam_grove 1:57a11fb5d529 62 BufferedSerial::prime();
sam_grove 0:a977d0a3d81e 63
sam_grove 0:a977d0a3d81e 64 return c;
sam_grove 0:a977d0a3d81e 65 }
sam_grove 0:a977d0a3d81e 66
sam_grove 0:a977d0a3d81e 67 int BufferedSerial::puts(const char *s)
sam_grove 0:a977d0a3d81e 68 {
sam_grove 2:7e8a450a9101 69 const char* ptr = s;
sam_grove 0:a977d0a3d81e 70
sam_grove 2:7e8a450a9101 71 while(*(ptr) != 0)
sam_grove 0:a977d0a3d81e 72 {
sam_grove 2:7e8a450a9101 73 _txbuf = *(ptr++);
sam_grove 0:a977d0a3d81e 74 }
sam_grove 2:7e8a450a9101 75 _txbuf = '\n'; // done per puts definition
sam_grove 1:57a11fb5d529 76 BufferedSerial::prime();
sam_grove 0:a977d0a3d81e 77
sam_grove 2:7e8a450a9101 78 return (ptr - s) + 1;
sam_grove 0:a977d0a3d81e 79 }
sam_grove 0:a977d0a3d81e 80
sam_grove 0:a977d0a3d81e 81 int BufferedSerial::printf(const char* format, ...)
sam_grove 0:a977d0a3d81e 82 {
sam_grove 0:a977d0a3d81e 83 char buf[256] = {0};
sam_grove 0:a977d0a3d81e 84 int r = 0;
sam_grove 0:a977d0a3d81e 85
sam_grove 0:a977d0a3d81e 86 va_list arg;
sam_grove 0:a977d0a3d81e 87 va_start(arg, format);
sam_grove 0:a977d0a3d81e 88 r = vsprintf(buf, format, arg);
sam_grove 0:a977d0a3d81e 89 // this may not hit the heap but should alert the user anyways
sam_grove 0:a977d0a3d81e 90 if(r > sizeof(buf))
sam_grove 0:a977d0a3d81e 91 {
sam_grove 2:7e8a450a9101 92 ERROR("Buffer Overflow on the Stack Occured!\n");
sam_grove 0:a977d0a3d81e 93 }
sam_grove 2:7e8a450a9101 94 r = BufferedSerial::write(buf, r);
sam_grove 0:a977d0a3d81e 95 va_end(arg);
sam_grove 0:a977d0a3d81e 96
sam_grove 0:a977d0a3d81e 97 return r;
sam_grove 0:a977d0a3d81e 98 }
sam_grove 0:a977d0a3d81e 99
sam_grove 2:7e8a450a9101 100 ssize_t BufferedSerial::write(const void *s, size_t length)
sam_grove 2:7e8a450a9101 101 {
sam_grove 2:7e8a450a9101 102 const char* ptr = (const char*)s;
sam_grove 2:7e8a450a9101 103 const char* end = ptr + length;
sam_grove 2:7e8a450a9101 104
sam_grove 2:7e8a450a9101 105 while (ptr != end)
sam_grove 2:7e8a450a9101 106 {
sam_grove 2:7e8a450a9101 107 _txbuf = *(ptr++);
sam_grove 2:7e8a450a9101 108 }
sam_grove 2:7e8a450a9101 109 BufferedSerial::prime();
sam_grove 2:7e8a450a9101 110
sam_grove 2:7e8a450a9101 111 return ptr - (const char*)s;
sam_grove 2:7e8a450a9101 112 }
sam_grove 2:7e8a450a9101 113
sam_grove 2:7e8a450a9101 114
sam_grove 0:a977d0a3d81e 115 void BufferedSerial::rxIrq(void)
sam_grove 0:a977d0a3d81e 116 {
sam_grove 0:a977d0a3d81e 117 // read from the peripheral and see if things are available
sam_grove 2:7e8a450a9101 118 if(serial_readable(&_serial))
sam_grove 0:a977d0a3d81e 119 {
sam_grove 0:a977d0a3d81e 120 _rxbuf = serial_getc(&_serial); // if so load them into a buffer
sam_grove 0:a977d0a3d81e 121 }
sam_grove 0:a977d0a3d81e 122
sam_grove 0:a977d0a3d81e 123 return;
sam_grove 0:a977d0a3d81e 124 }
sam_grove 0:a977d0a3d81e 125
sam_grove 0:a977d0a3d81e 126 void BufferedSerial::txIrq(void)
sam_grove 0:a977d0a3d81e 127 {
sam_grove 0:a977d0a3d81e 128 // see if there is room in the hardware buffer and something is in the software buffer
sam_grove 2:7e8a450a9101 129 if(serial_writable(&_serial) && _txbuf.available())
sam_grove 0:a977d0a3d81e 130 {
sam_grove 0:a977d0a3d81e 131 serial_putc(&_serial, (int)_txbuf.get());
sam_grove 0:a977d0a3d81e 132 }
sam_grove 0:a977d0a3d81e 133
sam_grove 0:a977d0a3d81e 134 return;
sam_grove 0:a977d0a3d81e 135 }
sam_grove 0:a977d0a3d81e 136
sam_grove 1:57a11fb5d529 137 void BufferedSerial::prime(void)
sam_grove 1:57a11fb5d529 138 {
sam_grove 2:7e8a450a9101 139 // if already busy then the irq will pick this up
sam_grove 2:7e8a450a9101 140 if(serial_writable(&_serial))
sam_grove 2:7e8a450a9101 141 {
sam_grove 2:7e8a450a9101 142 __disable_irq(); // make sure not to cause contention in the irq
sam_grove 2:7e8a450a9101 143 BufferedSerial::txIrq(); // prime the txirq - only write to hardware in one place
sam_grove 2:7e8a450a9101 144 __enable_irq();
sam_grove 2:7e8a450a9101 145 }
sam_grove 1:57a11fb5d529 146
sam_grove 1:57a11fb5d529 147 return;
sam_grove 1:57a11fb5d529 148 }
sam_grove 0:a977d0a3d81e 149
sam_grove 0:a977d0a3d81e 150