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:
8:3644d12758da
Parent:
7:dd892347b524
Child:
10:d5adca63e94a
--- a/rtos_serial.cpp	Mon Oct 21 22:58:04 2013 +0000
+++ b/rtos_serial.cpp	Tue Oct 22 17:38:50 2013 +0000
@@ -28,35 +28,31 @@
     uart_number = get_index();
     const PinName leds[] = {LED1,LED2,LED3,LED4};
     ledp = new DigitalOut(leds[uart_number]);
-    rtos_serial_pointers_by_index[uart_number] = this;
+#ifdef RTOS_SERIAL_TX_THREAD
     tx_emitter_threadp = new Thread(tx_emitter, (void *) this);
-    tx_tp[uart_number] = tx_emitter_threadp;
-    rx_isr_pFP = attach(rx_isr[uart_number], RxIrq);
-    tx_isr_pFP = attach(tx_isr[uart_number], TxIrq);
+#endif
+    rx_isr_pFP = attach(this, &RTOS_Serial::rx_isr, RxIrq);
+    tx_isr_pFP = 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
+    Serial::_putc('*'); //DEBUG
+#endif
 }
 
 
 RTOS_Serial::~RTOS_Serial() {
     remove_handler(rx_isr_pFP, RxIrq);
     remove_handler(tx_isr_pFP, TxIrq);
+#ifdef RTOS_SERIAL_TX_THREAD
     tx_emitter_threadp->terminate();
-    tx_tp[uart_number] = NULL;
     delete tx_emitter_threadp;
-    rtos_serial_pointers_by_index[uart_number] = NULL;
+#endif
 }
 
-RTOS_Serial* RTOS_Serial::rtos_serial_pointers_by_index[4] = { NULL, NULL, NULL, NULL };
-
-serial_t RTOS_Serial::get_serial() { return _serial; }
-
 int  RTOS_Serial::get_index() { return _serial.index; }
 
-#ifdef RTOS_Serial_underscore_putc
-int RTOS_Serial::_putc(int c) {
-#else
 int RTOS_Serial::putc(int c) {
-#endif
     //return Serial::putc(c); //DEBUG
     //if (tx_q.put((int *)c, osWaitForever) == osOK) return c; else return EOF;
     int status;
@@ -80,18 +76,10 @@
 }
 
 int RTOS_Serial::parent_putc(int c) {
-#ifdef RTOS_Serial_underscore_putc
     return Serial::_putc(c);
-#else
-    return Serial::putc(c);
-#endif
 }
 
-#ifdef RTOS_Serial_underscore_getc
-int RTOS_Serial::_getc() {
-#else
 int RTOS_Serial::getc() {
-#endif
     int rv;
     //return Serial::getc();  //FIXME: stand-in, which fails if we use our RX ISR
     osEvent evt = rx_q.get();
@@ -104,67 +92,27 @@
     return rv;
 }
 
-
-// ISR's for transmitter interrupts
-// 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);
-}
-// class method
-void RTOS_Serial::UART1_TX_ISR(){
-    //uint32_t IRR = LPC_UART1->IIR;
-    //tx_emitter_threadp->signal_set(0x1);
-    tx_tp[1]->signal_set(0x01);
-}
-// class method
-void RTOS_Serial::UART2_TX_ISR(){
-    //uint32_t IRR = LPC_UART2->IIR;
-    //tx_emitter_threadp->signal_set(0x1);
-    tx_tp[2]->signal_set(0x01);
-}
-// class method
-void RTOS_Serial::UART3_TX_ISR(){
-    //uint32_t IRR = LPC_UART3->IIR;  //DEBUG: maybe this?
-    //tx_emitter_threadp->signal_set(0x1);
-    tx_tp[3]->signal_set(0x01);
+void RTOS_Serial::rx_isr(){
+    rx_q.put((int *) _getc());
 }
 
-func RTOS_Serial::tx_isr[4] = {
-    &RTOS_Serial::UART0_TX_ISR, 
-    &RTOS_Serial::UART1_TX_ISR, 
-    &RTOS_Serial::UART2_TX_ISR, 
-    &RTOS_Serial::UART3_TX_ISR, 
-};
-
-/// ISR's for receiver interrupts
-// class method
-void RTOS_Serial::UART0_RX_ISR(){
-    RTOS_Serial::rtos_serial_pointers_by_index[0]->rx_q.put((int *)LPC_UART0->RBR);
-}
-// class method
-void RTOS_Serial::UART1_RX_ISR(){
-    RTOS_Serial::rtos_serial_pointers_by_index[1]->rx_q.put((int *)LPC_UART1->RBR);
-}
-// class method
-void RTOS_Serial::UART2_RX_ISR(){
-    RTOS_Serial::rtos_serial_pointers_by_index[2]->rx_q.put((int *)LPC_UART2->RBR);
-}
-// class method
-void RTOS_Serial::UART3_RX_ISR(){
-    RTOS_Serial::rtos_serial_pointers_by_index[3]->rx_q.put((int *)LPC_UART3->RBR);
+void RTOS_Serial::tx_isr(){
+#ifdef RTOS_SERIAL_TX_THREAD
+    tx_emitter_threadp->signal_set(0x1);
+#else
+    osEvent evt;
+    evt = tx_q.get();
+    if (evt.status == osEventMessage) {
+        *ledp = 1;
+        parent_putc(evt.value.v);
+        *ledp = 0;
+    } /*else {
+        std::printf("\r\nRTOS_Serial::tx_emitter() evt.status %d\n", evt.status);
+    }*/
+#endif
 }
 
-func RTOS_Serial::rx_isr[4] = {
-    &RTOS_Serial::UART0_RX_ISR, 
-    &RTOS_Serial::UART1_RX_ISR, 
-    &RTOS_Serial::UART2_RX_ISR, 
-    &RTOS_Serial::UART3_RX_ISR, 
-};
-
-Thread* RTOS_Serial::tx_tp[4] = { NULL, NULL, NULL, NULL };
-
+#ifdef RTOS_SERIAL_TX_THREAD
 // tx_emitter is a class method
 void RTOS_Serial::tx_emitter(void const *argument){
     RTOS_Serial *sp = (RTOS_Serial *) argument;
@@ -191,3 +139,4 @@
         *(sp->ledp) = 0;
     }
 }
+#endif