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@19:d974f46f6882, 2013-10-30 (annotated)
- 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?
User | Revision | Line number | New 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 |