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

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);