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
Diff: main.cpp
- Revision:
- 2:94d791a36afe
- Parent:
- 1:ae55f51ee284
- Child:
- 3:4ed0d32d3b38
diff -r ae55f51ee284 -r 94d791a36afe main.cpp --- a/main.cpp Fri Sep 27 05:33:28 2013 +0000 +++ b/main.cpp Fri Aug 01 21:54:31 2014 +0000 @@ -2,13 +2,37 @@ #include "mbed_rpc.h" Serial pc(USBTX, USBRX); +void Tx_interrupt(); +void Rx_interrupt(); +void send_line(); +void read_line(); + + +// Circular buffers for serial TX and RX data - used by interrupt routines +const int buffer_size = 255; +// might need to increase buffer size for high baud rates +char tx_buffer[buffer_size]; +char rx_buffer[buffer_size]; +// Circular buffer pointers +// volatile makes read-modify-write atomic +volatile int tx_in=0; +volatile int tx_out=0; +volatile int rx_in=0; +volatile int rx_out=0; +// Line buffers for sprintf and sscanf +char tx_line[80]; +char rx_line[80]; + + int main() { + char buf[256], outbuf[256]; - + pc.baud(115200); + // setup the classes that can be created dynamically -// RPC::add_rpc_class<RpcAnalogIn>(); -// RPC::add_rpc_class<RpcAnalogOut>(); + // RPC::add_rpc_class<RpcAnalogIn>(); + // RPC::add_rpc_class<RpcAnalogOut>(); RPC::add_rpc_class<RpcDigitalIn>(); RPC::add_rpc_class<RpcDigitalOut>(); RPC::add_rpc_class<RpcDigitalInOut>(); @@ -18,9 +42,125 @@ RPC::add_rpc_class<RpcSerial>(); // receive commands, and send back the responses + pc.printf(" ************** Serial RPC example starting ************************* \r\n"); + // Setup a serial interrupt function to receive data + pc.attach(&Rx_interrupt, Serial::RxIrq); + // Setup a serial interrupt function to transmit data + //pc.attach(&Tx_interrupt, Serial::TxIrq); + + while(1) { - pc.gets(buf, 256); + // Read a line from the large rx buffer from rx interrupt routine + read_line(); + + //pc.gets(buf, 4); + //pc.printf("#> '%s'\r\n", buf); + + /************************************ + This is an example of the RPC command required to create an LED object and turn it on: + /DigitalOut/new LED1 myled + /myled/write 1 + ************************************* + */ + + RPC::call(buf, outbuf); + RPC::call(rx_line, outbuf); + pc.printf("%s\r\n", outbuf); } } + + + +// Copy tx line buffer to large tx buffer for tx interrupt routine +void send_line() { + int i; + char temp_char; + bool empty; + i = 0; +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + empty = (tx_in == tx_out); + while ((i==0) || (tx_line[i-1] != '\n')) { +// Wait if buffer full + if (((tx_in + 1) % buffer_size) == tx_out) { +// End Critical Section - need to let interrupt routine empty buffer by sending + NVIC_EnableIRQ(UART1_IRQn); + while (((tx_in + 1) % buffer_size) == tx_out) { + } +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + } + tx_buffer[tx_in] = tx_line[i]; + i++; + tx_in = (tx_in + 1) % buffer_size; + } + if (pc.writeable() && (empty)) { + temp_char = tx_buffer[tx_out]; + tx_out = (tx_out + 1) % buffer_size; +// Send first character to start tx interrupts, if stopped + pc.putc(temp_char); + } +// End Critical Section + NVIC_EnableIRQ(UART1_IRQn); + return; +} + + +// Read a line from the large rx buffer from rx interrupt routine +void read_line() { + int i; + i = 0; +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); +// Loop reading rx buffer characters until end of line character + while ((i==0) || (rx_line[i-1] != '\r')) { +// Wait if buffer empty + if (rx_in == rx_out) { +// End Critical Section - need to allow rx interrupt to get new characters for buffer + NVIC_EnableIRQ(UART1_IRQn); + while (rx_in == rx_out) { + } +// Start Critical Section - don't interrupt while changing global buffer variables + NVIC_DisableIRQ(UART1_IRQn); + } + rx_line[i] = rx_buffer[rx_out]; + i++; + rx_out = (rx_out + 1) % buffer_size; + } +// End Critical Section + NVIC_EnableIRQ(UART1_IRQn); + rx_line[i-1] = 0; + return; +} + + +// Interupt Routine to read in data from serial port +void Rx_interrupt() { +// led1=1; +// Loop just in case more than one character is in UART's receive FIFO buffer +// Stop if buffer full + while ((pc.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) { + rx_buffer[rx_in] = pc.getc(); +// Uncomment to Echo to USB serial to watch data flow + pc.putc(rx_buffer[rx_in]); + rx_in = (rx_in + 1) % buffer_size; + } +// led1=0; + return; +} + + +// Interupt Routine to write out data to serial port +void Tx_interrupt() { +// led2=1; +// Loop to fill more than one character in UART's transmit FIFO buffer +// Stop if buffer empty + while ((pc.writeable()) && (tx_in != tx_out)) { + pc.putc(tx_buffer[tx_out]); + tx_out = (tx_out + 1) % buffer_size; + } +// led2=0; + return; +}