RPC over Serial with read line interrupt tested on LPC1768 and mac minicom terminal. Baudrate 115200
Dependencies: mbed-rpc-stmfork mbed-src
Fork of rpc_over_serial by
main.cpp
00001 #include "mbed.h" 00002 #include "mbed_rpc.h" 00003 #include "stmbed.h" 00004 00005 //Serial pc(USBTX, USBRX); 00006 //Serial pc(p29, p30); // stm32f103b 00007 Serial pc(SERIAL_TX, SERIAL_RX); // stm32f103b PA_2 PA_3 00008 DigitalOut ld1(PA_5); 00009 DigitalOut myled(LED1); 00010 00011 void Tx_interrupt(); 00012 void Rx_interrupt(); 00013 void send_line(); 00014 void read_line(); 00015 00016 00017 // Circular buffers for serial TX and RX data - used by interrupt routines 00018 const int buffer_size = 255; 00019 // might need to increase buffer size for high baud rates 00020 char tx_buffer[buffer_size]; 00021 char rx_buffer[buffer_size]; 00022 // Circular buffer pointers 00023 // volatile makes read-modify-write atomic 00024 volatile int tx_in=0; 00025 volatile int tx_out=0; 00026 volatile int rx_in=0; 00027 volatile int rx_out=0; 00028 // Line buffers for sprintf and sscanf 00029 char tx_line[80]; 00030 char rx_line[80]; 00031 00032 00033 void blink(){ 00034 myled = 1; // LED is ON 00035 wait(0.5); // 200 ms 00036 myled = 0; // LED is OFF 00037 wait(1.0); // 1 sec 00038 } 00039 00040 int main() { 00041 ld1=0; 00042 blink(); 00043 blink(); 00044 blink(); 00045 00046 char buf[256], outbuf[256]; 00047 //pc.baud(115200); 00048 pc.baud(9600); // nucleo F103RB 00049 00050 // receive commands, and send back the responses 00051 pc.printf(" ************** Serial RPC example starting ************************* \r\n"); 00052 00053 // setup the classes that can be created dynamically 00054 // RPC::add_rpc_class<RpcAnalogIn>(); 00055 // RPC::add_rpc_class<RpcAnalogOut>(); 00056 RPC::add_rpc_class<RpcDigitalIn>(); 00057 RPC::add_rpc_class<RpcDigitalOut>(); 00058 RPC::add_rpc_class<RpcDigitalInOut>(); 00059 RPC::add_rpc_class<RpcPwmOut>(); 00060 RPC::add_rpc_class<RpcTimer>(); 00061 RPC::add_rpc_class<RpcSPI>(); 00062 RPC::add_rpc_class<RpcSerial>(); 00063 // receive commands, and send back the responses 00064 pc.printf(" ************** 1 \r\n"); 00065 00066 // Setup a serial interrupt function to receive data 00067 pc.attach(&Rx_interrupt, Serial::RxIrq); 00068 // Setup a serial interrupt function to transmit data 00069 //pc.attach(&Tx_interrupt, Serial::TxIrq); 00070 pc.printf(" ************** 2 \r\n"); 00071 00072 while(1) { 00073 // Read a line from the large rx buffer from rx interrupt routine 00074 read_line(); 00075 00076 //pc.gets(buf, 4); 00077 //pc.printf("#> '%s'\r\n", buf); 00078 00079 /************************************ 00080 This is an example of the RPC command required to create an LED object and turn it on: 00081 /DigitalOut/new LED1 myled 00082 /myled/write 1 00083 ************************************* 00084 */ 00085 00086 00087 RPC::call(buf, outbuf); 00088 RPC::call(rx_line, outbuf); 00089 00090 pc.printf("%s\r\n", outbuf); 00091 } 00092 } 00093 00094 00095 00096 // Copy tx line buffer to large tx buffer for tx interrupt routine 00097 void send_line() { 00098 int i; 00099 char temp_char; 00100 bool empty; 00101 i = 0; 00102 // Start Critical Section - don't interrupt while changing global buffer variables 00103 NVIC_DisableIRQ(USART2_IRQn); 00104 empty = (tx_in == tx_out); 00105 while ((i==0) || (tx_line[i-1] != '\n')) { 00106 // Wait if buffer full 00107 if (((tx_in + 1) % buffer_size) == tx_out) { 00108 // End Critical Section - need to let interrupt routine empty buffer by sending 00109 NVIC_EnableIRQ(USART2_IRQn); 00110 while (((tx_in + 1) % buffer_size) == tx_out) { 00111 } 00112 // Start Critical Section - don't interrupt while changing global buffer variables 00113 NVIC_DisableIRQ(USART2_IRQn); 00114 } 00115 tx_buffer[tx_in] = tx_line[i]; 00116 i++; 00117 tx_in = (tx_in + 1) % buffer_size; 00118 } 00119 if (pc.writeable() && (empty)) { 00120 temp_char = tx_buffer[tx_out]; 00121 tx_out = (tx_out + 1) % buffer_size; 00122 // Send first character to start tx interrupts, if stopped 00123 pc.putc(temp_char); 00124 } 00125 // End Critical Section 00126 NVIC_EnableIRQ(USART2_IRQn); 00127 return; 00128 } 00129 00130 00131 // Read a line from the large rx buffer from rx interrupt routine 00132 void read_line() { 00133 int i; 00134 i = 0; 00135 // Start Critical Section - don't interrupt while changing global buffer variables 00136 NVIC_DisableIRQ(USART2_IRQn); // stm32: USART2_IRQn lpc nxp: UART1_IRQn 00137 // Loop reading rx buffer characters until end of line character 00138 while ((i==0) || (rx_line[i-1] != '\r')) { 00139 // Wait if buffer empty 00140 if (rx_in == rx_out) { 00141 // End Critical Section - need to allow rx interrupt to get new characters for buffer 00142 NVIC_EnableIRQ(USART2_IRQn); 00143 while (rx_in == rx_out) { 00144 } 00145 // Start Critical Section - don't interrupt while changing global buffer variables 00146 NVIC_DisableIRQ(USART2_IRQn); 00147 } 00148 rx_line[i] = rx_buffer[rx_out]; 00149 i++; 00150 rx_out = (rx_out + 1) % buffer_size; 00151 } 00152 // End Critical Section 00153 NVIC_EnableIRQ(USART2_IRQn); 00154 rx_line[i-1] = 0; 00155 return; 00156 } 00157 00158 00159 // Interupt Routine to read in data from serial port 00160 void Rx_interrupt() { 00161 // led1=1; 00162 // Loop just in case more than one character is in UART's receive FIFO buffer 00163 // Stop if buffer full 00164 while ((pc.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) { 00165 rx_buffer[rx_in] = pc.getc(); 00166 // Uncomment to Echo to USB serial to watch data flow 00167 pc.putc(rx_buffer[rx_in]); 00168 rx_in = (rx_in + 1) % buffer_size; 00169 } 00170 // led1=0; 00171 return; 00172 } 00173 00174 00175 // Interupt Routine to write out data to serial port 00176 void Tx_interrupt() { 00177 // led2=1; 00178 // Loop to fill more than one character in UART's transmit FIFO buffer 00179 // Stop if buffer empty 00180 while ((pc.writeable()) && (tx_in != tx_out)) { 00181 pc.putc(tx_buffer[tx_out]); 00182 tx_out = (tx_out + 1) % buffer_size; 00183 } 00184 // led2=0; 00185 return; 00186 }
Generated on Thu Jul 14 2022 01:22:05 by 1.7.2