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:
- 10:d5adca63e94a
- Parent:
- 8:3644d12758da
- Child:
- 11:bc067b42f8e0
--- a/rtos_serial.cpp Tue Oct 22 18:23:47 2013 +0000 +++ b/rtos_serial.cpp Wed Oct 23 21:06:59 2013 +0000 @@ -20,6 +20,14 @@ * SOFTWARE. */ +/* TODO: + * - assert rx overrun failure + * - fix rx overrun failure + * - size the tx thread stack + * - make an rx buffer thread + * - implement readable() + * - implement writeable() somehow + */ #include "rtos_serial.h" RTOS_Serial::RTOS_Serial(PinName tx, PinName rx, const char *name) @@ -31,8 +39,10 @@ #ifdef RTOS_SERIAL_TX_THREAD tx_emitter_threadp = new Thread(tx_emitter, (void *) this); #endif - rx_isr_pFP = attach(this, &RTOS_Serial::rx_isr, RxIrq); - tx_isr_pFP = attach(this, &RTOS_Serial::tx_isr, TxIrq); +// rx_isr_pFP = attach(this, &RTOS_Serial::rx_isr, RxIrq); +// tx_isr_pFP = attach(this, &RTOS_Serial::tx_isr, TxIrq); + attach(this, &RTOS_Serial::rx_isr, RxIrq); + attach(this, &RTOS_Serial::tx_isr, TxIrq); #ifdef RTOS_SERIAL_TX_THREAD tx_emitter_threadp->signal_set(0x01); // "prime the pump" of the tx-ready signals #else @@ -40,15 +50,28 @@ #endif } - +#if 0 RTOS_Serial::~RTOS_Serial() { - remove_handler(rx_isr_pFP, RxIrq); - remove_handler(tx_isr_pFP, TxIrq); + std::printf("[destroying RTOS_Serial 0x%x]", this); std::fflush(stdout); + bool b; + osDelay(200); //DEBUG +#if 0 + std::printf("[remove rx handler 0x%x", rx_isr_pFP); std::fflush(stdout); +// returns false as expected: b = remove_handler(NULL, RxIrq); + b = remove_handler(rx_isr_pFP, RxIrq); + std::printf("returned %d]", b); std::fflush(stdout); + std::printf("[remove tx handler 0x%x", tx_isr_pFP); std::fflush(stdout); + b = remove_handler(tx_isr_pFP, TxIrq); + std::printf("returned %d]", b); std::fflush(stdout); +#endif #ifdef RTOS_SERIAL_TX_THREAD tx_emitter_threadp->terminate(); + std::printf("[tx_emitter_thread 0x%x terminated]", tx_emitter_threadp); std::fflush(stdout); delete tx_emitter_threadp; + std::printf("[tx_emitter_threadp deleted]"); std::fflush(stdout); #endif } +#endif int RTOS_Serial::get_index() { return _serial.index; } @@ -93,7 +116,7 @@ } void RTOS_Serial::rx_isr(){ - rx_q.put((int *) _getc()); + rx_q.put((int *) _getc()); // FIXME: won't this wedge on overrun? } void RTOS_Serial::tx_isr(){ @@ -101,7 +124,7 @@ tx_emitter_threadp->signal_set(0x1); #else osEvent evt; - evt = tx_q.get(); + evt = tx_q.get(); // BUG: This will wait forever in ISR! if (evt.status == osEventMessage) { *ledp = 1; parent_putc(evt.value.v);