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@17:93011ddbd0a2, 2013-10-30 (annotated)
- Committer:
- altasoul
- Date:
- Wed Oct 30 05:01:45 2013 +0000
- Revision:
- 17:93011ddbd0a2
- Parent:
- 16:2d3937773625
- Child:
- 18:8665cc17b30d
for publication
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 | 15:5f38a747ba08 | 87 | */ |
altasoul | 12:be7883573c91 | 88 | class RTOS_Serial : public RawSerial { |
altasoul | 0:0547c8bf304f | 89 | public: |
altasoul | 0:0547c8bf304f | 90 | |
altasoul | 17:93011ddbd0a2 | 91 | /** Create an RTOS_Serial connected to the specified UART pins. |
altasoul | 15:5f38a747ba08 | 92 | * |
altasoul | 15:5f38a747ba08 | 93 | * @param tx PinName of the UART output (transmission) pin |
altasoul | 15:5f38a747ba08 | 94 | * @param rx PinName of the UART input (reception) pin |
altasoul | 15:5f38a747ba08 | 95 | * @param name (optional) A string to identify the object |
altasoul | 15:5f38a747ba08 | 96 | */ |
altasoul | 0:0547c8bf304f | 97 | RTOS_Serial(PinName tx, PinName rx, const char *name=NULL); |
altasoul | 15:5f38a747ba08 | 98 | |
altasoul | 17:93011ddbd0a2 | 99 | /** Send a character. |
altasoul | 15:5f38a747ba08 | 100 | * If the output queue is full it yields until it can enqueue |
altasoul | 15:5f38a747ba08 | 101 | * |
altasoul | 15:5f38a747ba08 | 102 | * @param c character to queue for transmission |
altasoul | 15:5f38a747ba08 | 103 | * @returns c, or EOF on failure (which should never happen) |
altasoul | 15:5f38a747ba08 | 104 | */ |
altasoul | 15:5f38a747ba08 | 105 | int putc(int c); |
altasoul | 15:5f38a747ba08 | 106 | |
altasoul | 17:93011ddbd0a2 | 107 | /** Get a character. |
altasoul | 15:5f38a747ba08 | 108 | * Yields to other threads until a character is available |
altasoul | 15:5f38a747ba08 | 109 | * |
altasoul | 15:5f38a747ba08 | 110 | * @param timeout (optional) milliseconds to wait for a character (default forever) |
altasoul | 15:5f38a747ba08 | 111 | * @returns the next character, or EOF if none available within timeout |
altasoul | 15:5f38a747ba08 | 112 | */ |
altasoul | 14:33d60e4eb215 | 113 | int getc(int timeout = osWaitForever); |
altasoul | 15:5f38a747ba08 | 114 | |
altasoul | 17:93011ddbd0a2 | 115 | /** Put a null-terminated string of characters. |
altasoul | 15:5f38a747ba08 | 116 | * |
altasoul | 15:5f38a747ba08 | 117 | * @param s the string |
altasoul | 15:5f38a747ba08 | 118 | * @returns the number of characters enqueued for transmission, or EOF on error |
altasoul | 15:5f38a747ba08 | 119 | */ |
altasoul | 2:891773cc33fd | 120 | int puts(const char *s); |
altasoul | 14:33d60e4eb215 | 121 | // int readable(); |
altasoul | 14:33d60e4eb215 | 122 | // int writeable(); |
altasoul | 0:0547c8bf304f | 123 | int get_index(); |
altasoul | 17:93011ddbd0a2 | 124 | /** Obtain the baud rate of the UART. |
altasoul | 15:5f38a747ba08 | 125 | * |
altasoul | 15:5f38a747ba08 | 126 | * @returns the baud rate of the UART (tx and rx are the same) |
altasoul | 15:5f38a747ba08 | 127 | */ |
altasoul | 11:bc067b42f8e0 | 128 | int get_baud(); |
altasoul | 15:5f38a747ba08 | 129 | |
altasoul | 2:891773cc33fd | 130 | Queue<int, 16> rx_q; |
altasoul | 12:be7883573c91 | 131 | const char *name; |
altasoul | 12:be7883573c91 | 132 | |
altasoul | 0:0547c8bf304f | 133 | protected: |
altasoul | 0:0547c8bf304f | 134 | DigitalOut *ledp; |
altasoul | 5:5d388d1d7987 | 135 | int uart_number; |
altasoul | 0:0547c8bf304f | 136 | Queue<int, 16> tx_q; |
altasoul | 0:0547c8bf304f | 137 | int parent_putc(int); |
altasoul | 1:5a66fddad7c4 | 138 | |
altasoul | 12:be7883573c91 | 139 | static void threadStarter(void const *p); |
altasoul | 13:2fb32235253c | 140 | void tx_emitter(); |
altasoul | 12:be7883573c91 | 141 | |
altasoul | 12:be7883573c91 | 142 | Thread _tx_thread; |
altasoul | 8:3644d12758da | 143 | void rx_isr(); |
altasoul | 8:3644d12758da | 144 | void tx_isr(); |
altasoul | 0:0547c8bf304f | 145 | }; |
altasoul | 0:0547c8bf304f | 146 | |
altasoul | 0:0547c8bf304f | 147 | #endif |