Buffered Serial Port Driver for RTOS tested with a K64F
Dependents: JRO_CR2 frdm_test JRO_DDSv2 JRO_DDSv2_rev2019
Fork of SerialDriver by
SerialDriver.cpp@4:3956012cd0c4, 2015-02-05 (annotated)
- Committer:
- miguelcordero191
- Date:
- Thu Feb 05 19:03:30 2015 +0000
- Revision:
- 4:3956012cd0c4
- Parent:
- 3:ea9719695b6a
- Child:
- 5:ee58295c58e1
putc was modified because it is not working with K64F. TxInterrupt does not work
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
BlazeX | 0:cd0d79be0c1a | 1 | #include "SerialDriver.h" |
BlazeX | 0:cd0d79be0c1a | 2 | |
BlazeX | 0:cd0d79be0c1a | 3 | SerialDriver::SerialDriver(PinName txPin, PinName rxPin, int txBufferLength_, int rxBufferLength_, unsigned char * txBuffer_, unsigned char * rxBuffer_) |
BlazeX | 0:cd0d79be0c1a | 4 | : SerialBase(txPin, rxPin), semTxBufferFull(0), semRxBufferEmpty(0) |
BlazeX | 0:cd0d79be0c1a | 5 | { |
BlazeX | 0:cd0d79be0c1a | 6 | // check buffer length |
BlazeX | 0:cd0d79be0c1a | 7 | txBufferLength= txBufferLength_; |
BlazeX | 0:cd0d79be0c1a | 8 | if(txBufferLength <= 1) |
BlazeX | 0:cd0d79be0c1a | 9 | error("TX buffer length must be > 1 !"); |
BlazeX | 0:cd0d79be0c1a | 10 | |
BlazeX | 0:cd0d79be0c1a | 11 | rxBufferLength= rxBufferLength_; |
BlazeX | 0:cd0d79be0c1a | 12 | if(rxBufferLength <= 1) |
BlazeX | 0:cd0d79be0c1a | 13 | error("RX buffer length must be > 1 !"); |
BlazeX | 0:cd0d79be0c1a | 14 | |
BlazeX | 0:cd0d79be0c1a | 15 | // take or allocate buffer |
BlazeX | 0:cd0d79be0c1a | 16 | txBuffer= txBuffer_; |
BlazeX | 0:cd0d79be0c1a | 17 | if(txBuffer == NULL) |
BlazeX | 0:cd0d79be0c1a | 18 | { |
BlazeX | 0:cd0d79be0c1a | 19 | txBuffer= new unsigned char[txBufferLength]; |
BlazeX | 0:cd0d79be0c1a | 20 | if(txBuffer == NULL) |
BlazeX | 0:cd0d79be0c1a | 21 | error("Cannot allocate TX buffer!"); |
BlazeX | 0:cd0d79be0c1a | 22 | } |
BlazeX | 0:cd0d79be0c1a | 23 | |
BlazeX | 0:cd0d79be0c1a | 24 | rxBuffer= rxBuffer_; |
BlazeX | 0:cd0d79be0c1a | 25 | if(rxBuffer == NULL) |
BlazeX | 0:cd0d79be0c1a | 26 | { |
BlazeX | 0:cd0d79be0c1a | 27 | rxBuffer= new unsigned char[rxBufferLength]; |
BlazeX | 0:cd0d79be0c1a | 28 | if(rxBuffer == NULL) |
BlazeX | 0:cd0d79be0c1a | 29 | error("Cannot allocate RX buffer!"); |
BlazeX | 0:cd0d79be0c1a | 30 | } |
BlazeX | 0:cd0d79be0c1a | 31 | |
BlazeX | 0:cd0d79be0c1a | 32 | |
BlazeX | 0:cd0d79be0c1a | 33 | // reset cursors |
BlazeX | 0:cd0d79be0c1a | 34 | txIn= txOut= 0; |
BlazeX | 0:cd0d79be0c1a | 35 | rxIn= rxOut= 0; |
BlazeX | 0:cd0d79be0c1a | 36 | txCount= rxCount= 0; |
BlazeX | 0:cd0d79be0c1a | 37 | |
BlazeX | 3:ea9719695b6a | 38 | // reset drop counters |
BlazeX | 3:ea9719695b6a | 39 | numTxDrops= 0; |
BlazeX | 3:ea9719695b6a | 40 | numRxDrops= 0; |
BlazeX | 3:ea9719695b6a | 41 | |
BlazeX | 0:cd0d79be0c1a | 42 | // attach interrupt routines |
BlazeX | 0:cd0d79be0c1a | 43 | attach(this, &SerialDriver::onRxIrq, RxIrq); |
miguelcordero191 | 4:3956012cd0c4 | 44 | //attach(this, &SerialDriver::onTxIrq, TxIrq); |
BlazeX | 0:cd0d79be0c1a | 45 | } |
BlazeX | 0:cd0d79be0c1a | 46 | |
BlazeX | 0:cd0d79be0c1a | 47 | int SerialDriver::putc(int c, unsigned int timeoutMs) |
BlazeX | 0:cd0d79be0c1a | 48 | { |
miguelcordero191 | 4:3956012cd0c4 | 49 | |
miguelcordero191 | 4:3956012cd0c4 | 50 | while(!SerialBase::writeable()) |
miguelcordero191 | 4:3956012cd0c4 | 51 | {//wait until character had been sent |
miguelcordero191 | 4:3956012cd0c4 | 52 | Thread::wait(1); |
miguelcordero191 | 4:3956012cd0c4 | 53 | } |
miguelcordero191 | 4:3956012cd0c4 | 54 | |
miguelcordero191 | 4:3956012cd0c4 | 55 | if(SerialBase::writeable()) |
miguelcordero191 | 4:3956012cd0c4 | 56 | { |
miguelcordero191 | 4:3956012cd0c4 | 57 | // take byte from tx buffer and put it out |
miguelcordero191 | 4:3956012cd0c4 | 58 | SerialBase::_base_putc(c); |
miguelcordero191 | 4:3956012cd0c4 | 59 | } |
miguelcordero191 | 4:3956012cd0c4 | 60 | |
miguelcordero191 | 4:3956012cd0c4 | 61 | return 1; |
miguelcordero191 | 4:3956012cd0c4 | 62 | } |
miguelcordero191 | 4:3956012cd0c4 | 63 | /* |
miguelcordero191 | 4:3956012cd0c4 | 64 | int SerialDriver::putc(int c, unsigned int timeoutMs) |
miguelcordero191 | 4:3956012cd0c4 | 65 | { |
BlazeX | 0:cd0d79be0c1a | 66 | // critical section, isr could modify cursors |
BlazeX | 0:cd0d79be0c1a | 67 | disableTxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 68 | |
BlazeX | 0:cd0d79be0c1a | 69 | if(isTxBufferFull()) |
BlazeX | 0:cd0d79be0c1a | 70 | { |
BlazeX | 0:cd0d79be0c1a | 71 | // wait for free space |
BlazeX | 0:cd0d79be0c1a | 72 | while(semTxBufferFull.wait(0) > 0); // clear semaphore |
BlazeX | 0:cd0d79be0c1a | 73 | enableTxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 74 | |
BlazeX | 0:cd0d79be0c1a | 75 | // let isr work |
BlazeX | 0:cd0d79be0c1a | 76 | semTxBufferFull.wait(timeoutMs); |
BlazeX | 0:cd0d79be0c1a | 77 | |
BlazeX | 0:cd0d79be0c1a | 78 | disableTxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 79 | if(isTxBufferFull()) // still full? drop byte! |
BlazeX | 0:cd0d79be0c1a | 80 | { |
BlazeX | 3:ea9719695b6a | 81 | numTxDrops++; |
BlazeX | 0:cd0d79be0c1a | 82 | enableTxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 83 | return 0; |
BlazeX | 0:cd0d79be0c1a | 84 | } |
BlazeX | 0:cd0d79be0c1a | 85 | } |
BlazeX | 0:cd0d79be0c1a | 86 | |
BlazeX | 0:cd0d79be0c1a | 87 | // write this byte to tx buffer |
BlazeX | 0:cd0d79be0c1a | 88 | txBuffer[txIn]= (unsigned char)c; |
BlazeX | 0:cd0d79be0c1a | 89 | txIn= (txIn+1) % txBufferLength; |
BlazeX | 0:cd0d79be0c1a | 90 | txCount++; |
BlazeX | 0:cd0d79be0c1a | 91 | |
BlazeX | 0:cd0d79be0c1a | 92 | // its over, isr can come |
BlazeX | 0:cd0d79be0c1a | 93 | enableTxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 94 | |
BlazeX | 0:cd0d79be0c1a | 95 | // Let's write (isr will check writeability itself) |
BlazeX | 0:cd0d79be0c1a | 96 | onTxIrq(); |
BlazeX | 0:cd0d79be0c1a | 97 | |
BlazeX | 0:cd0d79be0c1a | 98 | return 1; |
BlazeX | 0:cd0d79be0c1a | 99 | } |
miguelcordero191 | 4:3956012cd0c4 | 100 | */ |
BlazeX | 0:cd0d79be0c1a | 101 | void SerialDriver::onTxIrq() |
BlazeX | 0:cd0d79be0c1a | 102 | { |
BlazeX | 0:cd0d79be0c1a | 103 | // prevent fire another TxIrq now |
BlazeX | 0:cd0d79be0c1a | 104 | disableTxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 105 | |
BlazeX | 0:cd0d79be0c1a | 106 | // write as long as you can |
BlazeX | 0:cd0d79be0c1a | 107 | bool wasFull= isTxBufferFull(); |
BlazeX | 0:cd0d79be0c1a | 108 | while(SerialBase::writeable() && !isTxBufferEmtpy()) |
BlazeX | 0:cd0d79be0c1a | 109 | { |
BlazeX | 0:cd0d79be0c1a | 110 | // take byte from tx buffer and put it out |
BlazeX | 0:cd0d79be0c1a | 111 | SerialBase::_base_putc(txBuffer[txOut]); |
BlazeX | 0:cd0d79be0c1a | 112 | txOut= (txOut+1) % txBufferLength; |
BlazeX | 0:cd0d79be0c1a | 113 | txCount--; |
BlazeX | 0:cd0d79be0c1a | 114 | } |
BlazeX | 0:cd0d79be0c1a | 115 | |
BlazeX | 0:cd0d79be0c1a | 116 | if(wasFull && !isTxBufferFull()) // more bytes can come |
BlazeX | 0:cd0d79be0c1a | 117 | semTxBufferFull.release(); |
BlazeX | 0:cd0d79be0c1a | 118 | |
BlazeX | 0:cd0d79be0c1a | 119 | // ok, let's wait for next writability |
BlazeX | 0:cd0d79be0c1a | 120 | enableTxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 121 | } |
BlazeX | 0:cd0d79be0c1a | 122 | |
BlazeX | 0:cd0d79be0c1a | 123 | |
BlazeX | 0:cd0d79be0c1a | 124 | int SerialDriver::getc(unsigned int timeoutMs) |
BlazeX | 0:cd0d79be0c1a | 125 | { |
BlazeX | 0:cd0d79be0c1a | 126 | // Let's read (isr will check readability itself) |
BlazeX | 0:cd0d79be0c1a | 127 | onRxIrq(); |
BlazeX | 0:cd0d79be0c1a | 128 | |
BlazeX | 0:cd0d79be0c1a | 129 | // critical section, isr could modify cursors |
BlazeX | 0:cd0d79be0c1a | 130 | disableRxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 131 | |
BlazeX | 0:cd0d79be0c1a | 132 | if(isRxBufferEmpty()) |
BlazeX | 0:cd0d79be0c1a | 133 | { |
BlazeX | 0:cd0d79be0c1a | 134 | // wait for new byte |
BlazeX | 0:cd0d79be0c1a | 135 | while(semRxBufferEmpty.wait(0) > 0); // clear semaphore |
BlazeX | 0:cd0d79be0c1a | 136 | enableRxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 137 | |
BlazeX | 0:cd0d79be0c1a | 138 | // let isr work |
BlazeX | 0:cd0d79be0c1a | 139 | semRxBufferEmpty.wait(timeoutMs); |
BlazeX | 0:cd0d79be0c1a | 140 | |
BlazeX | 0:cd0d79be0c1a | 141 | disableRxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 142 | if(isRxBufferEmpty()) // still empty? nothing received! |
BlazeX | 0:cd0d79be0c1a | 143 | { |
BlazeX | 0:cd0d79be0c1a | 144 | enableRxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 145 | return -1; |
BlazeX | 0:cd0d79be0c1a | 146 | } |
BlazeX | 0:cd0d79be0c1a | 147 | } |
BlazeX | 0:cd0d79be0c1a | 148 | |
BlazeX | 0:cd0d79be0c1a | 149 | // get byte from rx buffer |
BlazeX | 0:cd0d79be0c1a | 150 | int c= (int)rxBuffer[rxOut]; |
BlazeX | 0:cd0d79be0c1a | 151 | rxOut= (rxOut+1) % rxBufferLength; |
BlazeX | 0:cd0d79be0c1a | 152 | rxCount--; |
BlazeX | 0:cd0d79be0c1a | 153 | |
BlazeX | 0:cd0d79be0c1a | 154 | // its over, isr can come |
BlazeX | 0:cd0d79be0c1a | 155 | enableRxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 156 | |
BlazeX | 0:cd0d79be0c1a | 157 | return c; |
BlazeX | 0:cd0d79be0c1a | 158 | } |
BlazeX | 0:cd0d79be0c1a | 159 | |
BlazeX | 0:cd0d79be0c1a | 160 | void SerialDriver::onRxIrq() |
BlazeX | 0:cd0d79be0c1a | 161 | { |
BlazeX | 0:cd0d79be0c1a | 162 | // prevent fire another RxIrq now |
BlazeX | 0:cd0d79be0c1a | 163 | disableRxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 164 | |
BlazeX | 0:cd0d79be0c1a | 165 | // read as long as you can |
BlazeX | 0:cd0d79be0c1a | 166 | bool wasEmpty= isRxBufferEmpty(); |
BlazeX | 0:cd0d79be0c1a | 167 | while(SerialBase::readable()) |
BlazeX | 0:cd0d79be0c1a | 168 | { |
BlazeX | 0:cd0d79be0c1a | 169 | // get byte and store it to the RX buffer |
BlazeX | 0:cd0d79be0c1a | 170 | int c= SerialBase::_base_getc(); |
BlazeX | 0:cd0d79be0c1a | 171 | if(!isRxBufferFull()) |
BlazeX | 0:cd0d79be0c1a | 172 | { |
BlazeX | 0:cd0d79be0c1a | 173 | rxBuffer[rxIn]= (unsigned char)c; |
BlazeX | 0:cd0d79be0c1a | 174 | rxIn= (rxIn+1) % rxBufferLength; |
BlazeX | 0:cd0d79be0c1a | 175 | rxCount++; |
BlazeX | 3:ea9719695b6a | 176 | } |
BlazeX | 3:ea9719695b6a | 177 | else // drop byte :( |
BlazeX | 3:ea9719695b6a | 178 | numRxDrops++; |
BlazeX | 0:cd0d79be0c1a | 179 | } |
BlazeX | 0:cd0d79be0c1a | 180 | |
BlazeX | 0:cd0d79be0c1a | 181 | if(wasEmpty && !isRxBufferEmpty()) // more bytes can go |
BlazeX | 0:cd0d79be0c1a | 182 | semRxBufferEmpty.release(); |
BlazeX | 0:cd0d79be0c1a | 183 | |
BlazeX | 0:cd0d79be0c1a | 184 | // ok, let's wait for next readability |
BlazeX | 0:cd0d79be0c1a | 185 | enableRxInterrupt(); |
BlazeX | 0:cd0d79be0c1a | 186 | } |
BlazeX | 0:cd0d79be0c1a | 187 | |
BlazeX | 0:cd0d79be0c1a | 188 | |
BlazeX | 0:cd0d79be0c1a | 189 | int SerialDriver::write(const unsigned char * buffer, const unsigned int length, bool block) |
BlazeX | 0:cd0d79be0c1a | 190 | { |
BlazeX | 0:cd0d79be0c1a | 191 | // try to put all bytes |
BlazeX | 0:cd0d79be0c1a | 192 | for(int i= 0; i < length; i++) |
BlazeX | 0:cd0d79be0c1a | 193 | if(!putc(buffer[i], block ? osWaitForever : 0)) |
BlazeX | 0:cd0d79be0c1a | 194 | return i; // putc failed, but already put i bytes |
BlazeX | 0:cd0d79be0c1a | 195 | |
BlazeX | 0:cd0d79be0c1a | 196 | return length; // put all bytes |
BlazeX | 0:cd0d79be0c1a | 197 | } |
BlazeX | 0:cd0d79be0c1a | 198 | |
miguelcordero191 | 4:3956012cd0c4 | 199 | int SerialDriver::read( char * buffer, const unsigned int length, bool block) |
BlazeX | 0:cd0d79be0c1a | 200 | { |
BlazeX | 0:cd0d79be0c1a | 201 | // try to get all bytes |
BlazeX | 0:cd0d79be0c1a | 202 | int c; |
BlazeX | 0:cd0d79be0c1a | 203 | for(int i= 0; i < length; i++) |
BlazeX | 0:cd0d79be0c1a | 204 | { |
BlazeX | 0:cd0d79be0c1a | 205 | c= getc(block ? osWaitForever : 0); |
BlazeX | 0:cd0d79be0c1a | 206 | if(c < 0) |
BlazeX | 0:cd0d79be0c1a | 207 | return i; // getc failed, but already got i bytes |
miguelcordero191 | 4:3956012cd0c4 | 208 | buffer[i]= ( char)c; |
BlazeX | 0:cd0d79be0c1a | 209 | } |
BlazeX | 0:cd0d79be0c1a | 210 | |
BlazeX | 0:cd0d79be0c1a | 211 | return length; // got all bytes |
BlazeX | 0:cd0d79be0c1a | 212 | } |
BlazeX | 0:cd0d79be0c1a | 213 | |
BlazeX | 0:cd0d79be0c1a | 214 | |
BlazeX | 0:cd0d79be0c1a | 215 | int SerialDriver::puts(const char * str, bool block) |
BlazeX | 0:cd0d79be0c1a | 216 | { |
BlazeX | 0:cd0d79be0c1a | 217 | // the same as write, but get length from strlen |
BlazeX | 0:cd0d79be0c1a | 218 | const int len= strlen(str); |
BlazeX | 0:cd0d79be0c1a | 219 | return write((const unsigned char *)str, len, block); |
BlazeX | 0:cd0d79be0c1a | 220 | } |
BlazeX | 0:cd0d79be0c1a | 221 | |
BlazeX | 0:cd0d79be0c1a | 222 | int SerialDriver::printf(const char * format, ...) |
BlazeX | 0:cd0d79be0c1a | 223 | { |
BlazeX | 0:cd0d79be0c1a | 224 | // Parts of this are copied from mbed RawSerial ;) |
BlazeX | 0:cd0d79be0c1a | 225 | std::va_list arg; |
BlazeX | 0:cd0d79be0c1a | 226 | va_start(arg, format); |
BlazeX | 0:cd0d79be0c1a | 227 | |
BlazeX | 0:cd0d79be0c1a | 228 | int length= vsnprintf(NULL, 0, format, arg); |
BlazeX | 0:cd0d79be0c1a | 229 | char *temp = new char[length + 1]; |
BlazeX | 0:cd0d79be0c1a | 230 | vsprintf(temp, format, arg); |
BlazeX | 0:cd0d79be0c1a | 231 | puts(temp, true); |
BlazeX | 0:cd0d79be0c1a | 232 | delete[] temp; |
BlazeX | 0:cd0d79be0c1a | 233 | |
BlazeX | 0:cd0d79be0c1a | 234 | va_end(arg); |
BlazeX | 0:cd0d79be0c1a | 235 | return length; |
BlazeX | 0:cd0d79be0c1a | 236 | } |
BlazeX | 0:cd0d79be0c1a | 237 | |
BlazeX | 3:ea9719695b6a | 238 | // still thinking of XTN |