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:
- 8:3644d12758da
- Parent:
- 7:dd892347b524
- Child:
- 10:d5adca63e94a
diff -r dd892347b524 -r 3644d12758da rtos_serial.cpp --- 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