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

Committer:
altasoul
Date:
Wed Oct 30 05:56:17 2013 +0000
Revision:
19:d974f46f6882
Parent:
18:8665cc17b30d
example needed @endcode

Who changed what in which revision?

UserRevisionLine numberNew contents of line
altasoul 0:0547c8bf304f 1 /*
altasoul 0:0547c8bf304f 2 * Copyright (c) 2013 Tom Soulanille
altasoul 0:0547c8bf304f 3 *
altasoul 16:2d3937773625 4 *
altasoul 16:2d3937773625 5 * Licensed under the Apache License, Version 2.0 (the "License");
altasoul 16:2d3937773625 6 * you may not use this file except in compliance with the License.
altasoul 16:2d3937773625 7 * You may obtain a copy of the License at
altasoul 0:0547c8bf304f 8 *
altasoul 16:2d3937773625 9 * http://www.apache.org/licenses/LICENSE-2.0
altasoul 0:0547c8bf304f 10 *
altasoul 16:2d3937773625 11 * Unless required by applicable law or agreed to in writing, software
altasoul 16:2d3937773625 12 * distributed under the License is distributed on an "AS IS" BASIS,
altasoul 16:2d3937773625 13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
altasoul 16:2d3937773625 14 * See the License for the specific language governing permissions and
altasoul 16:2d3937773625 15 * limitations under the License.
altasoul 0:0547c8bf304f 16 */
altasoul 0:0547c8bf304f 17
altasoul 0:0547c8bf304f 18 #ifndef RTOS_SERIAL_H
altasoul 0:0547c8bf304f 19 #define RTOS_SERIAL_H
altasoul 0:0547c8bf304f 20
altasoul 0:0547c8bf304f 21 #include "mbed.h"
altasoul 0:0547c8bf304f 22 #include "rtos.h"
altasoul 0:0547c8bf304f 23
altasoul 0:0547c8bf304f 24 #define MBED_RTOS_SERIAL_VERSION_MAJOR 0
altasoul 8:3644d12758da 25 #define MBED_RTOS_SERIAL_VERSION_MINOR 1
altasoul 11:bc067b42f8e0 26 #define MBED_RTOS_SERIAL_VERSION_EDIT 6
altasoul 0:0547c8bf304f 27
altasoul 9:b664b4f9f93d 28 #define RTOS_SERIAL_TX_THREAD 1
altasoul 12:be7883573c91 29 #define RTOS_SERIAL_TX_THREAD_STACK_SIZE 1024 /* FIXME: figure out good value */
altasoul 0:0547c8bf304f 30
altasoul 0:0547c8bf304f 31 /*
altasoul 0:0547c8bf304f 32 from Serial.h:
altasoul 0:0547c8bf304f 33 class Serial : public Stream {
altasoul 0:0547c8bf304f 34
altasoul 0:0547c8bf304f 35 public:
altasoul 0:0547c8bf304f 36 Serial(PinName tx, PinName rx, const char *name=NULL);
altasoul 0:0547c8bf304f 37 ...
altasoul 0:0547c8bf304f 38 protected:
altasoul 0:0547c8bf304f 39 ...
altasoul 0:0547c8bf304f 40 serial_t _serial;
altasoul 0:0547c8bf304f 41
altasoul 0:0547c8bf304f 42 from serial_api.h:
altasoul 0:0547c8bf304f 43 typedef struct serial_s serial_t;
altasoul 0:0547c8bf304f 44
altasoul 0:0547c8bf304f 45 from objects.h:
altasoul 0:0547c8bf304f 46 struct serial_s {
altasoul 0:0547c8bf304f 47 LPC_UART_TypeDef *uart;
altasoul 0:0547c8bf304f 48 int index;
altasoul 0:0547c8bf304f 49 };
altasoul 0:0547c8bf304f 50
altasoul 0:0547c8bf304f 51 from LPC17xx.h:
altasoul 0:0547c8bf304f 52 typedef struct
altasoul 0:0547c8bf304f 53 {
altasoul 0:0547c8bf304f 54 union {
altasoul 0:0547c8bf304f 55 __I uint8_t RBR;
altasoul 0:0547c8bf304f 56 __O uint8_t THR;
altasoul 0:0547c8bf304f 57 __IO uint8_t DLL;
altasoul 0:0547c8bf304f 58 uint32_t RESERVED0;
altasoul 0:0547c8bf304f 59 };
altasoul 0:0547c8bf304f 60 union {
altasoul 0:0547c8bf304f 61 __IO uint8_t DLM;
altasoul 0:0547c8bf304f 62 __IO uint32_t IER;
altasoul 0:0547c8bf304f 63 };
altasoul 0:0547c8bf304f 64 union {
altasoul 0:0547c8bf304f 65 __I uint32_t IIR;
altasoul 0:0547c8bf304f 66 __O uint8_t FCR;
altasoul 0:0547c8bf304f 67 };
altasoul 0:0547c8bf304f 68 __IO uint8_t LCR;
altasoul 0:0547c8bf304f 69 uint8_t RESERVED1[7];
altasoul 0:0547c8bf304f 70 __I uint8_t LSR;
altasoul 0:0547c8bf304f 71 uint8_t RESERVED2[7];
altasoul 0:0547c8bf304f 72 __IO uint8_t SCR;
altasoul 0:0547c8bf304f 73 uint8_t RESERVED3[3];
altasoul 0:0547c8bf304f 74 __IO uint32_t ACR;
altasoul 0:0547c8bf304f 75 __IO uint8_t ICR;
altasoul 0:0547c8bf304f 76 uint8_t RESERVED4[3];
altasoul 0:0547c8bf304f 77 __IO uint8_t FDR;
altasoul 0:0547c8bf304f 78 uint8_t RESERVED5[7];
altasoul 0:0547c8bf304f 79 __IO uint8_t TER;
altasoul 0:0547c8bf304f 80 uint8_t RESERVED6[39];
altasoul 0:0547c8bf304f 81 __IO uint32_t FIFOLVL;
altasoul 0:0547c8bf304f 82 } LPC_UART_TypeDef;
altasoul 0:0547c8bf304f 83
altasoul 0:0547c8bf304f 84 */
altasoul 0:0547c8bf304f 85
altasoul 15:5f38a747ba08 86 /** An RTOS-friendly serial port
altasoul 18:8665cc17b30d 87 *
altasoul 18:8665cc17b30d 88 * Example:
altasoul 18:8665cc17b30d 89 * @code
altasoul 18:8665cc17b30d 90 * // Bridge the USB serial interface to a uart
altasoul 18:8665cc17b30d 91 * #include "mbed.h"
altasoul 18:8665cc17b30d 92 * #include "rtos.h"
altasoul 18:8665cc17b30d 93 * #include "rtos_serial.h"
altasoul 18:8665cc17b30d 94 *
altasoul 18:8665cc17b30d 95 * DigitalOut myled(LED1);
altasoul 18:8665cc17b30d 96 *
altasoul 18:8665cc17b30d 97 * void p_to_p(const void* arg) {
altasoul 18:8665cc17b30d 98 * RTOS_Serial** ports = (RTOS_Serial**) arg;
altasoul 18:8665cc17b30d 99 * while (true) ports[1]->putc(ports[0]->getc());
altasoul 18:8665cc17b30d 100 * }
altasoul 18:8665cc17b30d 101 *
altasoul 18:8665cc17b30d 102 * int main() {
altasoul 18:8665cc17b30d 103 * RTOS_Serial host(USBTX, USBRX);
altasoul 18:8665cc17b30d 104 * RTOS_Serial uart(p13, p14);
altasoul 18:8665cc17b30d 105 * RTOS_Serial *host_uart_ports[] = {&host, &uart};
altasoul 18:8665cc17b30d 106 * Thread host_to_port_thread(p_to_p, (void*) host_uart_ports);
altasoul 18:8665cc17b30d 107 * RTOS_Serial *uart_host_ports[] = {&uart, &host};
altasoul 18:8665cc17b30d 108 * Thread port_to_host_thread(p_to_p, (void*) uart_host_ports);
altasoul 18:8665cc17b30d 109 *
altasoul 18:8665cc17b30d 110 * while (true) {
altasoul 18:8665cc17b30d 111 * myled = !myled;
altasoul 18:8665cc17b30d 112 * Thread::wait(400);
altasoul 18:8665cc17b30d 113 * }
altasoul 18:8665cc17b30d 114 * }
altasoul 19:d974f46f6882 115 * @endcode
altasoul 15:5f38a747ba08 116 */
altasoul 12:be7883573c91 117 class RTOS_Serial : public RawSerial {
altasoul 0:0547c8bf304f 118 public:
altasoul 0:0547c8bf304f 119
altasoul 17:93011ddbd0a2 120 /** Create an RTOS_Serial connected to the specified UART pins.
altasoul 15:5f38a747ba08 121 *
altasoul 15:5f38a747ba08 122 * @param tx PinName of the UART output (transmission) pin
altasoul 15:5f38a747ba08 123 * @param rx PinName of the UART input (reception) pin
altasoul 15:5f38a747ba08 124 * @param name (optional) A string to identify the object
altasoul 15:5f38a747ba08 125 */
altasoul 0:0547c8bf304f 126 RTOS_Serial(PinName tx, PinName rx, const char *name=NULL);
altasoul 15:5f38a747ba08 127
altasoul 17:93011ddbd0a2 128 /** Send a character.
altasoul 15:5f38a747ba08 129 * If the output queue is full it yields until it can enqueue
altasoul 15:5f38a747ba08 130 *
altasoul 15:5f38a747ba08 131 * @param c character to queue for transmission
altasoul 15:5f38a747ba08 132 * @returns c, or EOF on failure (which should never happen)
altasoul 15:5f38a747ba08 133 */
altasoul 15:5f38a747ba08 134 int putc(int c);
altasoul 15:5f38a747ba08 135
altasoul 17:93011ddbd0a2 136 /** Get a character.
altasoul 15:5f38a747ba08 137 * Yields to other threads until a character is available
altasoul 15:5f38a747ba08 138 *
altasoul 15:5f38a747ba08 139 * @param timeout (optional) milliseconds to wait for a character (default forever)
altasoul 15:5f38a747ba08 140 * @returns the next character, or EOF if none available within timeout
altasoul 15:5f38a747ba08 141 */
altasoul 14:33d60e4eb215 142 int getc(int timeout = osWaitForever);
altasoul 15:5f38a747ba08 143
altasoul 17:93011ddbd0a2 144 /** Put a null-terminated string of characters.
altasoul 15:5f38a747ba08 145 *
altasoul 15:5f38a747ba08 146 * @param s the string
altasoul 15:5f38a747ba08 147 * @returns the number of characters enqueued for transmission, or EOF on error
altasoul 15:5f38a747ba08 148 */
altasoul 2:891773cc33fd 149 int puts(const char *s);
altasoul 14:33d60e4eb215 150 // int readable();
altasoul 14:33d60e4eb215 151 // int writeable();
altasoul 0:0547c8bf304f 152 int get_index();
altasoul 17:93011ddbd0a2 153 /** Obtain the baud rate of the UART.
altasoul 15:5f38a747ba08 154 *
altasoul 15:5f38a747ba08 155 * @returns the baud rate of the UART (tx and rx are the same)
altasoul 15:5f38a747ba08 156 */
altasoul 11:bc067b42f8e0 157 int get_baud();
altasoul 15:5f38a747ba08 158
altasoul 2:891773cc33fd 159 Queue<int, 16> rx_q;
altasoul 12:be7883573c91 160 const char *name;
altasoul 12:be7883573c91 161
altasoul 0:0547c8bf304f 162 protected:
altasoul 0:0547c8bf304f 163 DigitalOut *ledp;
altasoul 5:5d388d1d7987 164 int uart_number;
altasoul 0:0547c8bf304f 165 Queue<int, 16> tx_q;
altasoul 0:0547c8bf304f 166 int parent_putc(int);
altasoul 1:5a66fddad7c4 167
altasoul 12:be7883573c91 168 static void threadStarter(void const *p);
altasoul 13:2fb32235253c 169 void tx_emitter();
altasoul 12:be7883573c91 170
altasoul 12:be7883573c91 171 Thread _tx_thread;
altasoul 8:3644d12758da 172 void rx_isr();
altasoul 8:3644d12758da 173 void tx_isr();
altasoul 0:0547c8bf304f 174 };
altasoul 0:0547c8bf304f 175
altasoul 0:0547c8bf304f 176 #endif