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/

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?

UserRevisionLine numberNew 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 }