UART1 buffered serial driver, requires RTOS
Dependents: Serial_interrupts_buffered HARP2 HARP3
buffered_serial.cpp
00001 /* 00002 * @file buffered_serial.cpp 00003 * @author Tyler Weaver 00004 * 00005 * @section LICENSE 00006 * 00007 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software 00008 * and associated documentation files (the "Software"), to deal in the Software without restriction, 00009 * including without limitation the rights to use, copy, modify, merge, publish, distribute, 00010 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is 00011 * furnished to do so, subject to the following conditions: 00012 * 00013 * The above copyright notice and this permission notice shall be included in all copies or 00014 * substantial portions of the Software. 00015 * 00016 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING 00017 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 00018 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 00019 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00020 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 00021 * 00022 * @section DESCRIPTION 00023 * 00024 * Buffered serial UART1 - Setup to work with UART1 (p13,p14) 00025 * 00026 * Uses RTOS to block current thread. 00027 */ 00028 #include "buffered_serial.h" 00029 00030 BufferedSerial::BufferedSerial() : Serial(p13,p14), /*led1(LED1), led2(LED2),*/ rx_sem_(0), tx_sem_(0) 00031 { 00032 tx_in_=0; 00033 tx_out_=0; 00034 rx_in_=0; 00035 rx_out_=0; 00036 00037 device_irqn = UART1_IRQn; 00038 00039 // attach the interrupts 00040 Serial::attach(this, &BufferedSerial::Rx_interrupt, Serial::RxIrq); 00041 Serial::attach(this, &BufferedSerial::Tx_interrupt, Serial::TxIrq); 00042 } 00043 00044 // Copy tx line buffer to large tx buffer for tx interrupt routine 00045 void BufferedSerial::put_line(char *c) 00046 { 00047 int i; 00048 char temp_char; 00049 bool empty; 00050 i = 0; 00051 strncpy(tx_line_,c,LINE_SIZE); 00052 // Start Critical Section - don't interrupt while changing global buffer variables 00053 NVIC_DisableIRQ(device_irqn); 00054 empty = (tx_in_ == tx_out_); 00055 while ((i==0) || (tx_line_[i-1] != '\n')) { 00056 // Wait if buffer full 00057 if (IS_TX_FULL) { 00058 // End Critical Section - need to let interrupt routine empty buffer by sending 00059 NVIC_EnableIRQ(device_irqn); 00060 //while (IS_TX_FULL) ; // buffer is full 00061 tx_sem_.wait(); 00062 // Start Critical Section - don't interrupt while changing global buffer variables 00063 NVIC_DisableIRQ(device_irqn); 00064 } 00065 tx_buffer_[tx_in_] = tx_line_[i]; 00066 i++; 00067 tx_in_ = NEXT(tx_in_); 00068 } 00069 if (Serial::writeable() && (empty)) { 00070 temp_char = tx_buffer_[tx_out_]; 00071 tx_out_ = NEXT(tx_out_); 00072 // Send first character to start tx interrupts, if stopped 00073 LPC_UART1->THR = temp_char; 00074 } 00075 // End Critical Section 00076 NVIC_EnableIRQ(device_irqn); 00077 } 00078 00079 // Read a line from the large rx buffer from rx interrupt routine 00080 void BufferedSerial::get_line(char *c) 00081 { 00082 int i; 00083 i = 0; 00084 // Start Critical Section - don't interrupt while changing global buffer variables 00085 NVIC_DisableIRQ(device_irqn); 00086 // Loop reading rx buffer characters until end of line character 00087 while ((i==0) || (rx_line_[i-1] != '\n')) { 00088 // Wait if buffer empty 00089 if (IS_RX_EMPTY) { // buffer empty 00090 // End Critical Section - need to allow rx interrupt to get new characters for buffer 00091 NVIC_EnableIRQ(device_irqn); 00092 00093 rx_sem_.wait(); 00094 // Start Critical Section - don't interrupt while changing global buffer variables 00095 NVIC_DisableIRQ(device_irqn); 00096 } else { 00097 rx_sem_.wait(); 00098 } 00099 rx_line_[i] = rx_buffer_[rx_out_]; 00100 i++; 00101 rx_out_ = NEXT(rx_out_); 00102 00103 // prevent overflow on rx_line 00104 if(i == LINE_SIZE) { 00105 i--; 00106 break; 00107 } 00108 } 00109 rx_line_[i++] = 0; 00110 // End Critical Section 00111 NVIC_EnableIRQ(device_irqn); 00112 strncpy(c,rx_line_,i); 00113 } 00114 00115 // Interupt Routine to read in data from serial port 00116 void BufferedSerial::Rx_interrupt() 00117 { 00118 uint32_t IRR1 = LPC_UART1->IIR; 00119 // led1=1; 00120 while (readable() && !(IS_RX_FULL)) { 00121 rx_buffer_[rx_in_] = LPC_UART1->RBR; 00122 rx_in_ = NEXT(rx_in_); 00123 rx_sem_.release(); 00124 } 00125 // led1=0; 00126 } 00127 00128 // Interupt Routine to write out data to serial port 00129 void BufferedSerial::Tx_interrupt() 00130 { 00131 uint32_t IRR = LPC_UART1->IIR; 00132 // led2=1; 00133 while ((writeable()) && (tx_in_ != tx_out_)) { // while serial is writeable and there are still characters in the buffer 00134 LPC_UART1->THR = tx_buffer_[tx_out_]; // send the character 00135 tx_out_ = NEXT(tx_out_); 00136 } 00137 if(!IS_TX_FULL) // if not full 00138 tx_sem_.release(); 00139 // led2=0; 00140 }
Generated on Sat Jul 16 2022 17:21:01 by 1.7.2