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@2:94d791a36afe, 2014-08-01 (annotated)
- Committer:
- mosi
- Date:
- Fri Aug 01 21:54:31 2014 +0000
- Revision:
- 2:94d791a36afe
- Parent:
- 1:ae55f51ee284
- Child:
- 3:4ed0d32d3b38
Implemented serial read interrupt from another example, echoing of serial read and couple of comments;
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
okini3939 | 0:7e0e5391432a | 1 | #include "mbed.h" |
okini3939 | 0:7e0e5391432a | 2 | #include "mbed_rpc.h" |
okini3939 | 0:7e0e5391432a | 3 | |
okini3939 | 0:7e0e5391432a | 4 | Serial pc(USBTX, USBRX); |
mosi | 2:94d791a36afe | 5 | void Tx_interrupt(); |
mosi | 2:94d791a36afe | 6 | void Rx_interrupt(); |
mosi | 2:94d791a36afe | 7 | void send_line(); |
mosi | 2:94d791a36afe | 8 | void read_line(); |
mosi | 2:94d791a36afe | 9 | |
mosi | 2:94d791a36afe | 10 | |
mosi | 2:94d791a36afe | 11 | // Circular buffers for serial TX and RX data - used by interrupt routines |
mosi | 2:94d791a36afe | 12 | const int buffer_size = 255; |
mosi | 2:94d791a36afe | 13 | // might need to increase buffer size for high baud rates |
mosi | 2:94d791a36afe | 14 | char tx_buffer[buffer_size]; |
mosi | 2:94d791a36afe | 15 | char rx_buffer[buffer_size]; |
mosi | 2:94d791a36afe | 16 | // Circular buffer pointers |
mosi | 2:94d791a36afe | 17 | // volatile makes read-modify-write atomic |
mosi | 2:94d791a36afe | 18 | volatile int tx_in=0; |
mosi | 2:94d791a36afe | 19 | volatile int tx_out=0; |
mosi | 2:94d791a36afe | 20 | volatile int rx_in=0; |
mosi | 2:94d791a36afe | 21 | volatile int rx_out=0; |
mosi | 2:94d791a36afe | 22 | // Line buffers for sprintf and sscanf |
mosi | 2:94d791a36afe | 23 | char tx_line[80]; |
mosi | 2:94d791a36afe | 24 | char rx_line[80]; |
mosi | 2:94d791a36afe | 25 | |
mosi | 2:94d791a36afe | 26 | |
okini3939 | 0:7e0e5391432a | 27 | |
okini3939 | 0:7e0e5391432a | 28 | int main() { |
mosi | 2:94d791a36afe | 29 | |
okini3939 | 0:7e0e5391432a | 30 | char buf[256], outbuf[256]; |
mosi | 2:94d791a36afe | 31 | pc.baud(115200); |
mosi | 2:94d791a36afe | 32 | |
okini3939 | 0:7e0e5391432a | 33 | // setup the classes that can be created dynamically |
mosi | 2:94d791a36afe | 34 | // RPC::add_rpc_class<RpcAnalogIn>(); |
mosi | 2:94d791a36afe | 35 | // RPC::add_rpc_class<RpcAnalogOut>(); |
okini3939 | 0:7e0e5391432a | 36 | RPC::add_rpc_class<RpcDigitalIn>(); |
okini3939 | 0:7e0e5391432a | 37 | RPC::add_rpc_class<RpcDigitalOut>(); |
okini3939 | 0:7e0e5391432a | 38 | RPC::add_rpc_class<RpcDigitalInOut>(); |
okini3939 | 0:7e0e5391432a | 39 | RPC::add_rpc_class<RpcPwmOut>(); |
okini3939 | 0:7e0e5391432a | 40 | RPC::add_rpc_class<RpcTimer>(); |
okini3939 | 0:7e0e5391432a | 41 | RPC::add_rpc_class<RpcSPI>(); |
okini3939 | 0:7e0e5391432a | 42 | RPC::add_rpc_class<RpcSerial>(); |
okini3939 | 0:7e0e5391432a | 43 | |
okini3939 | 0:7e0e5391432a | 44 | // receive commands, and send back the responses |
mosi | 2:94d791a36afe | 45 | pc.printf(" ************** Serial RPC example starting ************************* \r\n"); |
mosi | 2:94d791a36afe | 46 | // Setup a serial interrupt function to receive data |
mosi | 2:94d791a36afe | 47 | pc.attach(&Rx_interrupt, Serial::RxIrq); |
mosi | 2:94d791a36afe | 48 | // Setup a serial interrupt function to transmit data |
mosi | 2:94d791a36afe | 49 | //pc.attach(&Tx_interrupt, Serial::TxIrq); |
mosi | 2:94d791a36afe | 50 | |
mosi | 2:94d791a36afe | 51 | |
okini3939 | 0:7e0e5391432a | 52 | while(1) { |
mosi | 2:94d791a36afe | 53 | // Read a line from the large rx buffer from rx interrupt routine |
mosi | 2:94d791a36afe | 54 | read_line(); |
mosi | 2:94d791a36afe | 55 | |
mosi | 2:94d791a36afe | 56 | //pc.gets(buf, 4); |
mosi | 2:94d791a36afe | 57 | //pc.printf("#> '%s'\r\n", buf); |
mosi | 2:94d791a36afe | 58 | |
mosi | 2:94d791a36afe | 59 | /************************************ |
mosi | 2:94d791a36afe | 60 | This is an example of the RPC command required to create an LED object and turn it on: |
mosi | 2:94d791a36afe | 61 | /DigitalOut/new LED1 myled |
mosi | 2:94d791a36afe | 62 | /myled/write 1 |
mosi | 2:94d791a36afe | 63 | ************************************* |
mosi | 2:94d791a36afe | 64 | */ |
mosi | 2:94d791a36afe | 65 | |
mosi | 2:94d791a36afe | 66 | |
okini3939 | 0:7e0e5391432a | 67 | RPC::call(buf, outbuf); |
mosi | 2:94d791a36afe | 68 | RPC::call(rx_line, outbuf); |
mosi | 2:94d791a36afe | 69 | |
okini3939 | 0:7e0e5391432a | 70 | pc.printf("%s\r\n", outbuf); |
okini3939 | 0:7e0e5391432a | 71 | } |
okini3939 | 0:7e0e5391432a | 72 | } |
mosi | 2:94d791a36afe | 73 | |
mosi | 2:94d791a36afe | 74 | |
mosi | 2:94d791a36afe | 75 | |
mosi | 2:94d791a36afe | 76 | // Copy tx line buffer to large tx buffer for tx interrupt routine |
mosi | 2:94d791a36afe | 77 | void send_line() { |
mosi | 2:94d791a36afe | 78 | int i; |
mosi | 2:94d791a36afe | 79 | char temp_char; |
mosi | 2:94d791a36afe | 80 | bool empty; |
mosi | 2:94d791a36afe | 81 | i = 0; |
mosi | 2:94d791a36afe | 82 | // Start Critical Section - don't interrupt while changing global buffer variables |
mosi | 2:94d791a36afe | 83 | NVIC_DisableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 84 | empty = (tx_in == tx_out); |
mosi | 2:94d791a36afe | 85 | while ((i==0) || (tx_line[i-1] != '\n')) { |
mosi | 2:94d791a36afe | 86 | // Wait if buffer full |
mosi | 2:94d791a36afe | 87 | if (((tx_in + 1) % buffer_size) == tx_out) { |
mosi | 2:94d791a36afe | 88 | // End Critical Section - need to let interrupt routine empty buffer by sending |
mosi | 2:94d791a36afe | 89 | NVIC_EnableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 90 | while (((tx_in + 1) % buffer_size) == tx_out) { |
mosi | 2:94d791a36afe | 91 | } |
mosi | 2:94d791a36afe | 92 | // Start Critical Section - don't interrupt while changing global buffer variables |
mosi | 2:94d791a36afe | 93 | NVIC_DisableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 94 | } |
mosi | 2:94d791a36afe | 95 | tx_buffer[tx_in] = tx_line[i]; |
mosi | 2:94d791a36afe | 96 | i++; |
mosi | 2:94d791a36afe | 97 | tx_in = (tx_in + 1) % buffer_size; |
mosi | 2:94d791a36afe | 98 | } |
mosi | 2:94d791a36afe | 99 | if (pc.writeable() && (empty)) { |
mosi | 2:94d791a36afe | 100 | temp_char = tx_buffer[tx_out]; |
mosi | 2:94d791a36afe | 101 | tx_out = (tx_out + 1) % buffer_size; |
mosi | 2:94d791a36afe | 102 | // Send first character to start tx interrupts, if stopped |
mosi | 2:94d791a36afe | 103 | pc.putc(temp_char); |
mosi | 2:94d791a36afe | 104 | } |
mosi | 2:94d791a36afe | 105 | // End Critical Section |
mosi | 2:94d791a36afe | 106 | NVIC_EnableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 107 | return; |
mosi | 2:94d791a36afe | 108 | } |
mosi | 2:94d791a36afe | 109 | |
mosi | 2:94d791a36afe | 110 | |
mosi | 2:94d791a36afe | 111 | // Read a line from the large rx buffer from rx interrupt routine |
mosi | 2:94d791a36afe | 112 | void read_line() { |
mosi | 2:94d791a36afe | 113 | int i; |
mosi | 2:94d791a36afe | 114 | i = 0; |
mosi | 2:94d791a36afe | 115 | // Start Critical Section - don't interrupt while changing global buffer variables |
mosi | 2:94d791a36afe | 116 | NVIC_DisableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 117 | // Loop reading rx buffer characters until end of line character |
mosi | 2:94d791a36afe | 118 | while ((i==0) || (rx_line[i-1] != '\r')) { |
mosi | 2:94d791a36afe | 119 | // Wait if buffer empty |
mosi | 2:94d791a36afe | 120 | if (rx_in == rx_out) { |
mosi | 2:94d791a36afe | 121 | // End Critical Section - need to allow rx interrupt to get new characters for buffer |
mosi | 2:94d791a36afe | 122 | NVIC_EnableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 123 | while (rx_in == rx_out) { |
mosi | 2:94d791a36afe | 124 | } |
mosi | 2:94d791a36afe | 125 | // Start Critical Section - don't interrupt while changing global buffer variables |
mosi | 2:94d791a36afe | 126 | NVIC_DisableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 127 | } |
mosi | 2:94d791a36afe | 128 | rx_line[i] = rx_buffer[rx_out]; |
mosi | 2:94d791a36afe | 129 | i++; |
mosi | 2:94d791a36afe | 130 | rx_out = (rx_out + 1) % buffer_size; |
mosi | 2:94d791a36afe | 131 | } |
mosi | 2:94d791a36afe | 132 | // End Critical Section |
mosi | 2:94d791a36afe | 133 | NVIC_EnableIRQ(UART1_IRQn); |
mosi | 2:94d791a36afe | 134 | rx_line[i-1] = 0; |
mosi | 2:94d791a36afe | 135 | return; |
mosi | 2:94d791a36afe | 136 | } |
mosi | 2:94d791a36afe | 137 | |
mosi | 2:94d791a36afe | 138 | |
mosi | 2:94d791a36afe | 139 | // Interupt Routine to read in data from serial port |
mosi | 2:94d791a36afe | 140 | void Rx_interrupt() { |
mosi | 2:94d791a36afe | 141 | // led1=1; |
mosi | 2:94d791a36afe | 142 | // Loop just in case more than one character is in UART's receive FIFO buffer |
mosi | 2:94d791a36afe | 143 | // Stop if buffer full |
mosi | 2:94d791a36afe | 144 | while ((pc.readable()) && (((rx_in + 1) % buffer_size) != rx_out)) { |
mosi | 2:94d791a36afe | 145 | rx_buffer[rx_in] = pc.getc(); |
mosi | 2:94d791a36afe | 146 | // Uncomment to Echo to USB serial to watch data flow |
mosi | 2:94d791a36afe | 147 | pc.putc(rx_buffer[rx_in]); |
mosi | 2:94d791a36afe | 148 | rx_in = (rx_in + 1) % buffer_size; |
mosi | 2:94d791a36afe | 149 | } |
mosi | 2:94d791a36afe | 150 | // led1=0; |
mosi | 2:94d791a36afe | 151 | return; |
mosi | 2:94d791a36afe | 152 | } |
mosi | 2:94d791a36afe | 153 | |
mosi | 2:94d791a36afe | 154 | |
mosi | 2:94d791a36afe | 155 | // Interupt Routine to write out data to serial port |
mosi | 2:94d791a36afe | 156 | void Tx_interrupt() { |
mosi | 2:94d791a36afe | 157 | // led2=1; |
mosi | 2:94d791a36afe | 158 | // Loop to fill more than one character in UART's transmit FIFO buffer |
mosi | 2:94d791a36afe | 159 | // Stop if buffer empty |
mosi | 2:94d791a36afe | 160 | while ((pc.writeable()) && (tx_in != tx_out)) { |
mosi | 2:94d791a36afe | 161 | pc.putc(tx_buffer[tx_out]); |
mosi | 2:94d791a36afe | 162 | tx_out = (tx_out + 1) % buffer_size; |
mosi | 2:94d791a36afe | 163 | } |
mosi | 2:94d791a36afe | 164 | // led2=0; |
mosi | 2:94d791a36afe | 165 | return; |
mosi | 2:94d791a36afe | 166 | } |