UART1 buffered serial driver, requires RTOS
Dependents: Serial_interrupts_buffered HARP2 HARP3
Buffered serial UART1 - Setup to work with UART1 (p13,p14)
Uses RTOS to block current thread.
Reference: http://mbed.org/users/tylerjw/notebook/buffered-serial-with-rtos/
buffered_serial.cpp@4:d3122119f92b, 2012-12-17 (annotated)
- Committer:
- tylerjw
- Date:
- Mon Dec 17 22:35:51 2012 +0000
- Revision:
- 4:d3122119f92b
- Parent:
- 3:a4a21e18acd1
naming conventions and documentation
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
tylerjw | 4:d3122119f92b | 1 | /* |
tylerjw | 4:d3122119f92b | 2 | * @file buffered_serial.cpp |
tylerjw | 4:d3122119f92b | 3 | * @author Tyler Weaver |
tylerjw | 4:d3122119f92b | 4 | * |
tylerjw | 4:d3122119f92b | 5 | * @section LICENSE |
tylerjw | 4:d3122119f92b | 6 | * |
tylerjw | 4:d3122119f92b | 7 | * Permission is hereby granted, free of charge, to any person obtaining a copy of this software |
tylerjw | 4:d3122119f92b | 8 | * and associated documentation files (the "Software"), to deal in the Software without restriction, |
tylerjw | 4:d3122119f92b | 9 | * including without limitation the rights to use, copy, modify, merge, publish, distribute, |
tylerjw | 4:d3122119f92b | 10 | * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is |
tylerjw | 4:d3122119f92b | 11 | * furnished to do so, subject to the following conditions: |
tylerjw | 4:d3122119f92b | 12 | * |
tylerjw | 4:d3122119f92b | 13 | * The above copyright notice and this permission notice shall be included in all copies or |
tylerjw | 4:d3122119f92b | 14 | * substantial portions of the Software. |
tylerjw | 4:d3122119f92b | 15 | * |
tylerjw | 4:d3122119f92b | 16 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING |
tylerjw | 4:d3122119f92b | 17 | * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND |
tylerjw | 4:d3122119f92b | 18 | * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, |
tylerjw | 4:d3122119f92b | 19 | * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, |
tylerjw | 4:d3122119f92b | 20 | * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. |
tylerjw | 4:d3122119f92b | 21 | * |
tylerjw | 4:d3122119f92b | 22 | * @section DESCRIPTION |
tylerjw | 4:d3122119f92b | 23 | * |
tylerjw | 4:d3122119f92b | 24 | * Buffered serial UART1 - Setup to work with UART1 (p13,p14) |
tylerjw | 4:d3122119f92b | 25 | * |
tylerjw | 4:d3122119f92b | 26 | * Uses RTOS to block current thread. |
tylerjw | 4:d3122119f92b | 27 | */ |
tylerjw | 0:707b9f3904dd | 28 | #include "buffered_serial.h" |
tylerjw | 0:707b9f3904dd | 29 | |
tylerjw | 4:d3122119f92b | 30 | BufferedSerial::BufferedSerial() : Serial(p13,p14), /*led1(LED1), led2(LED2),*/ rx_sem_(0), tx_sem_(0) |
tylerjw | 0:707b9f3904dd | 31 | { |
tylerjw | 4:d3122119f92b | 32 | tx_in_=0; |
tylerjw | 4:d3122119f92b | 33 | tx_out_=0; |
tylerjw | 4:d3122119f92b | 34 | rx_in_=0; |
tylerjw | 4:d3122119f92b | 35 | rx_out_=0; |
tylerjw | 0:707b9f3904dd | 36 | |
tylerjw | 0:707b9f3904dd | 37 | device_irqn = UART1_IRQn; |
tylerjw | 0:707b9f3904dd | 38 | |
tylerjw | 0:707b9f3904dd | 39 | // attach the interrupts |
tylerjw | 0:707b9f3904dd | 40 | Serial::attach(this, &BufferedSerial::Rx_interrupt, Serial::RxIrq); |
tylerjw | 0:707b9f3904dd | 41 | Serial::attach(this, &BufferedSerial::Tx_interrupt, Serial::TxIrq); |
tylerjw | 0:707b9f3904dd | 42 | } |
tylerjw | 0:707b9f3904dd | 43 | |
tylerjw | 0:707b9f3904dd | 44 | // Copy tx line buffer to large tx buffer for tx interrupt routine |
tylerjw | 4:d3122119f92b | 45 | void BufferedSerial::put_line(char *c) |
tylerjw | 0:707b9f3904dd | 46 | { |
tylerjw | 0:707b9f3904dd | 47 | int i; |
tylerjw | 0:707b9f3904dd | 48 | char temp_char; |
tylerjw | 0:707b9f3904dd | 49 | bool empty; |
tylerjw | 0:707b9f3904dd | 50 | i = 0; |
tylerjw | 4:d3122119f92b | 51 | strncpy(tx_line_,c,LINE_SIZE); |
tylerjw | 0:707b9f3904dd | 52 | // Start Critical Section - don't interrupt while changing global buffer variables |
tylerjw | 0:707b9f3904dd | 53 | NVIC_DisableIRQ(device_irqn); |
tylerjw | 4:d3122119f92b | 54 | empty = (tx_in_ == tx_out_); |
tylerjw | 4:d3122119f92b | 55 | while ((i==0) || (tx_line_[i-1] != '\n')) { |
tylerjw | 0:707b9f3904dd | 56 | // Wait if buffer full |
tylerjw | 0:707b9f3904dd | 57 | if (IS_TX_FULL) { |
tylerjw | 0:707b9f3904dd | 58 | // End Critical Section - need to let interrupt routine empty buffer by sending |
tylerjw | 0:707b9f3904dd | 59 | NVIC_EnableIRQ(device_irqn); |
tylerjw | 0:707b9f3904dd | 60 | //while (IS_TX_FULL) ; // buffer is full |
tylerjw | 4:d3122119f92b | 61 | tx_sem_.wait(); |
tylerjw | 0:707b9f3904dd | 62 | // Start Critical Section - don't interrupt while changing global buffer variables |
tylerjw | 0:707b9f3904dd | 63 | NVIC_DisableIRQ(device_irqn); |
tylerjw | 0:707b9f3904dd | 64 | } |
tylerjw | 4:d3122119f92b | 65 | tx_buffer_[tx_in_] = tx_line_[i]; |
tylerjw | 0:707b9f3904dd | 66 | i++; |
tylerjw | 4:d3122119f92b | 67 | tx_in_ = NEXT(tx_in_); |
tylerjw | 0:707b9f3904dd | 68 | } |
tylerjw | 0:707b9f3904dd | 69 | if (Serial::writeable() && (empty)) { |
tylerjw | 4:d3122119f92b | 70 | temp_char = tx_buffer_[tx_out_]; |
tylerjw | 4:d3122119f92b | 71 | tx_out_ = NEXT(tx_out_); |
tylerjw | 0:707b9f3904dd | 72 | // Send first character to start tx interrupts, if stopped |
tylerjw | 0:707b9f3904dd | 73 | LPC_UART1->THR = temp_char; |
tylerjw | 0:707b9f3904dd | 74 | } |
tylerjw | 0:707b9f3904dd | 75 | // End Critical Section |
tylerjw | 0:707b9f3904dd | 76 | NVIC_EnableIRQ(device_irqn); |
tylerjw | 0:707b9f3904dd | 77 | } |
tylerjw | 0:707b9f3904dd | 78 | |
tylerjw | 0:707b9f3904dd | 79 | // Read a line from the large rx buffer from rx interrupt routine |
tylerjw | 4:d3122119f92b | 80 | void BufferedSerial::get_line(char *c) |
tylerjw | 0:707b9f3904dd | 81 | { |
tylerjw | 0:707b9f3904dd | 82 | int i; |
tylerjw | 0:707b9f3904dd | 83 | i = 0; |
tylerjw | 0:707b9f3904dd | 84 | // Start Critical Section - don't interrupt while changing global buffer variables |
tylerjw | 0:707b9f3904dd | 85 | NVIC_DisableIRQ(device_irqn); |
tylerjw | 0:707b9f3904dd | 86 | // Loop reading rx buffer characters until end of line character |
tylerjw | 4:d3122119f92b | 87 | while ((i==0) || (rx_line_[i-1] != '\n')) { |
tylerjw | 0:707b9f3904dd | 88 | // Wait if buffer empty |
tylerjw | 0:707b9f3904dd | 89 | if (IS_RX_EMPTY) { // buffer empty |
tylerjw | 0:707b9f3904dd | 90 | // End Critical Section - need to allow rx interrupt to get new characters for buffer |
tylerjw | 0:707b9f3904dd | 91 | NVIC_EnableIRQ(device_irqn); |
tylerjw | 4:d3122119f92b | 92 | |
tylerjw | 4:d3122119f92b | 93 | rx_sem_.wait(); |
tylerjw | 0:707b9f3904dd | 94 | // Start Critical Section - don't interrupt while changing global buffer variables |
tylerjw | 0:707b9f3904dd | 95 | NVIC_DisableIRQ(device_irqn); |
tylerjw | 0:707b9f3904dd | 96 | } else { |
tylerjw | 4:d3122119f92b | 97 | rx_sem_.wait(); |
tylerjw | 0:707b9f3904dd | 98 | } |
tylerjw | 4:d3122119f92b | 99 | rx_line_[i] = rx_buffer_[rx_out_]; |
tylerjw | 0:707b9f3904dd | 100 | i++; |
tylerjw | 4:d3122119f92b | 101 | rx_out_ = NEXT(rx_out_); |
tylerjw | 4:d3122119f92b | 102 | |
tylerjw | 1:eabb26ce183b | 103 | // prevent overflow on rx_line |
tylerjw | 4:d3122119f92b | 104 | if(i == LINE_SIZE) { |
tylerjw | 1:eabb26ce183b | 105 | i--; |
tylerjw | 1:eabb26ce183b | 106 | break; |
tylerjw | 2:8ccf9bb8dc65 | 107 | } |
tylerjw | 0:707b9f3904dd | 108 | } |
tylerjw | 4:d3122119f92b | 109 | rx_line_[i++] = 0; |
tylerjw | 0:707b9f3904dd | 110 | // End Critical Section |
tylerjw | 0:707b9f3904dd | 111 | NVIC_EnableIRQ(device_irqn); |
tylerjw | 4:d3122119f92b | 112 | strncpy(c,rx_line_,i); |
tylerjw | 0:707b9f3904dd | 113 | } |
tylerjw | 0:707b9f3904dd | 114 | |
tylerjw | 0:707b9f3904dd | 115 | // Interupt Routine to read in data from serial port |
tylerjw | 0:707b9f3904dd | 116 | void BufferedSerial::Rx_interrupt() |
tylerjw | 0:707b9f3904dd | 117 | { |
tylerjw | 0:707b9f3904dd | 118 | uint32_t IRR1 = LPC_UART1->IIR; |
tylerjw | 3:a4a21e18acd1 | 119 | // led1=1; |
tylerjw | 0:707b9f3904dd | 120 | while (readable() && !(IS_RX_FULL)) { |
tylerjw | 4:d3122119f92b | 121 | rx_buffer_[rx_in_] = LPC_UART1->RBR; |
tylerjw | 4:d3122119f92b | 122 | rx_in_ = NEXT(rx_in_); |
tylerjw | 4:d3122119f92b | 123 | rx_sem_.release(); |
tylerjw | 0:707b9f3904dd | 124 | } |
tylerjw | 3:a4a21e18acd1 | 125 | // led1=0; |
tylerjw | 0:707b9f3904dd | 126 | } |
tylerjw | 0:707b9f3904dd | 127 | |
tylerjw | 0:707b9f3904dd | 128 | // Interupt Routine to write out data to serial port |
tylerjw | 0:707b9f3904dd | 129 | void BufferedSerial::Tx_interrupt() |
tylerjw | 0:707b9f3904dd | 130 | { |
tylerjw | 0:707b9f3904dd | 131 | uint32_t IRR = LPC_UART1->IIR; |
tylerjw | 3:a4a21e18acd1 | 132 | // led2=1; |
tylerjw | 4:d3122119f92b | 133 | while ((writeable()) && (tx_in_ != tx_out_)) { // while serial is writeable and there are still characters in the buffer |
tylerjw | 4:d3122119f92b | 134 | LPC_UART1->THR = tx_buffer_[tx_out_]; // send the character |
tylerjw | 4:d3122119f92b | 135 | tx_out_ = NEXT(tx_out_); |
tylerjw | 0:707b9f3904dd | 136 | } |
tylerjw | 0:707b9f3904dd | 137 | if(!IS_TX_FULL) // if not full |
tylerjw | 4:d3122119f92b | 138 | tx_sem_.release(); |
tylerjw | 3:a4a21e18acd1 | 139 | // led2=0; |
tylerjw | 0:707b9f3904dd | 140 | } |