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