An RTOS-friendly Serial interface Its primary benefit is that it never hogs the CPU. An amusing alternative to the traditional ring-bufferd interrupt-serviced systems, it uses short mbed-rtos queues to buffer characters to and from the UART, and a thread to service the transmitter. Short interrupt service routines enqueue received characters and signal the transmit thread when the transmitter is available. WARNING: Do not create RTOS-Serial objects before the RTOS is running! Put them inside your main() block or another function, not in the global initialization.
Dependents: Test_RDM880_rfid_reader
Diff: rtos_serial.cpp
- Revision:
- 0:0547c8bf304f
- Child:
- 1:5a66fddad7c4
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/rtos_serial.cpp Fri Oct 18 02:55:07 2013 +0000 @@ -0,0 +1,86 @@ +/* + * Copyright (c) 2013 Tom Soulanille + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + */ + +#include "rtos_serial.h" + +//RTOS_Serial::tx_mail_t blah; + +RTOS_Serial::RTOS_Serial(PinName tx, PinName rx, const char *name) + : Serial(tx, rx, name) +{ + const PinName leds[] = {LED1,LED2,LED3,LED4}; + ledp = new DigitalOut(leds[get_index()]); + tx_emitter_threadp = new Thread(tx_emitter, (void *) this); +}; + +Thread* RTOS_Serial::tx_tp[4] = { NULL, NULL, NULL, NULL }; + +serial_t RTOS_Serial::get_serial() { return _serial; }; + +int RTOS_Serial::get_index() { return _serial.index; } + +int RTOS_Serial::putc(int c) { + //return Serial::putc(c); + //if (tx_q.put((int *)c, osWaitForever) == osOK) return c; else return EOF; + int status; + if ( (status = tx_q.put((int *)c, osWaitForever)) == osOK) return c; else { + std::printf("tx_q.put() returned %d\r\n", status); + return EOF; + } +} + +int RTOS_Serial::parent_putc(int c) { + return Serial::putc(c); +} + +// class method +void RTOS_Serial::UART0_TX_ISR(){ + uint32_t IRR = LPC_UART0->IIR; + //tx_emitter_threadp->signal_set(0x1); + tx_tp[0]->signal_set(0x01); +} + +// tx_emitter is a class method +void RTOS_Serial::tx_emitter(void const *argument){ + RTOS_Serial *sp = (RTOS_Serial *) argument; + osEvent evt; + while(true){ +#if 0 + *(sp->ledp) = 0; + osDelay(200); + *(sp->ledp) = 1; + osDelay(200); +#endif +#if 1 + evt = sp->tx_q.get(); + if (evt.status == osEventMessage) { + //Thread::signal_wait(0x1); + *(sp->ledp) = 1; + sp->parent_putc(evt.value.v); + *(sp->ledp) = 0; + } else { + std::printf("tx_emitter() evt.status %d\n", evt.status); + } +#endif + *(sp->ledp) = 0; + } +} \ No newline at end of file