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

rtos_serial.h

Committer:
altasoul
Date:
2013-10-30
Revision:
15:5f38a747ba08
Parent:
14:33d60e4eb215
Child:
16:2d3937773625

File content as of revision 15:5f38a747ba08:

/*
 * 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.
 */

#ifndef RTOS_SERIAL_H
#define RTOS_SERIAL_H

#include "mbed.h"
#include "rtos.h"

#define MBED_RTOS_SERIAL_VERSION_MAJOR    0
#define MBED_RTOS_SERIAL_VERSION_MINOR    1
#define MBED_RTOS_SERIAL_VERSION_EDIT     6

#define RTOS_SERIAL_TX_THREAD 1
#define RTOS_SERIAL_TX_THREAD_STACK_SIZE 1024    /* FIXME: figure out good value */

/*
from Serial.h:
class Serial : public Stream {

public:
    Serial(PinName tx, PinName rx, const char *name=NULL);
    ...
protected:
    ...
    serial_t        _serial;

from serial_api.h:
typedef struct serial_s serial_t;

from objects.h:
struct serial_s {
    LPC_UART_TypeDef *uart;
    int index;
};

from LPC17xx.h:
typedef struct
{
  union {
  __I  uint8_t  RBR;
  __O  uint8_t  THR;
  __IO uint8_t  DLL;
       uint32_t RESERVED0;
  };
  union {
  __IO uint8_t  DLM;
  __IO uint32_t IER;
  };
  union {
  __I  uint32_t IIR;
  __O  uint8_t  FCR;
  };
  __IO uint8_t  LCR;
       uint8_t  RESERVED1[7];
  __I  uint8_t  LSR;
       uint8_t  RESERVED2[7];
  __IO uint8_t  SCR;
       uint8_t  RESERVED3[3];
  __IO uint32_t ACR;
  __IO uint8_t  ICR;
       uint8_t  RESERVED4[3];
  __IO uint8_t  FDR;
       uint8_t  RESERVED5[7];
  __IO uint8_t  TER;
       uint8_t  RESERVED6[39];
  __IO uint32_t FIFOLVL;
} LPC_UART_TypeDef;

*/

/** An RTOS-friendly serial port
 */
class RTOS_Serial : public RawSerial {
  public:

    /** Create an RTOS_Serial connected to the specified UART pins
     *
     * @param tx PinName of the UART output (transmission) pin
     * @param rx PinName of the UART input (reception) pin
     * @param name (optional) A string to identify the object
     */
    RTOS_Serial(PinName tx, PinName rx, const char *name=NULL);
    
    /** Send a character
     * If the output queue is full it yields until it can enqueue
     *
     * @param c character to queue for transmission
     * @returns c, or EOF on failure (which should never happen)
     */
    int putc(int c);
    
    /** Get a character
     * Yields to other threads until a character is available
     *
     * @param timeout (optional) milliseconds to wait for a character (default forever)
     * @returns the next character, or EOF if none available within timeout
     */
    int getc(int timeout = osWaitForever);
    
    /** Put a null-terminated string of characters
     *
     * @param s the string
     * @returns the number of characters enqueued for transmission, or EOF on error
     */
    int puts(const char *s);
//    int readable();
//    int writeable();
    int get_index();
    /** Obtain the baud rate of the UART
     *
     * @returns the baud rate of the UART (tx and rx are the same)
     */
    int get_baud();
    
    Queue<int, 16> rx_q;
    const char *name;
 
  protected:
    DigitalOut *ledp;
    int uart_number;
    Queue<int, 16> tx_q;
    int parent_putc(int);
    
    static void threadStarter(void const *p);
    void tx_emitter();
    
    Thread _tx_thread;
    void rx_isr();
    void tx_isr();
};

#endif