Super lightweight, not at all robust, TFTP server for FRDM-K64F eval board.
Dependencies: EthernetInterface mbed-rtos mbed
Fork of FRDM_K64F-Ethernet by
Super lightweight, not at all robust, TFTP server for FRDM-K64F eval board. This tool supports read-only access to two files. It does not support NACK responses or timeouts. The tool is intended for use by our test department to check out Ethernet functionality on our main processor board.
main.cpp@2:28ddb9b073ec, 2018-10-11 (annotated)
- Committer:
- audim
- Date:
- Thu Oct 11 20:45:38 2018 +0000
- Revision:
- 2:28ddb9b073ec
- Parent:
- 1:2944c0d494ff
clean up some comments
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
audim | 1:2944c0d494ff | 1 | /* |
audim | 1:2944c0d494ff | 2 | ** Super lightweight, not at all robust, TFTP server for FRDM-K64F eval board. |
audim | 2:28ddb9b073ec | 3 | ** This tool supports read-only access to a couple of files. It does not support |
audim | 2:28ddb9b073ec | 4 | ** NACK responses or timeouts. The tool is intended for use by our test department |
audim | 2:28ddb9b073ec | 5 | ** to check out Ethernet functionality on our main processor board. |
audim | 1:2944c0d494ff | 6 | ** |
audim | 1:2944c0d494ff | 7 | ** 11 October 2018 |
audim | 1:2944c0d494ff | 8 | ** - am |
audim | 1:2944c0d494ff | 9 | */ |
audim | 1:2944c0d494ff | 10 | |
issaiass | 0:bbc9cfdee3bc | 11 | #include "mbed.h" |
issaiass | 0:bbc9cfdee3bc | 12 | #include "EthernetInterface.h" |
audim | 1:2944c0d494ff | 13 | #include "string.h" |
audim | 1:2944c0d494ff | 14 | |
audim | 1:2944c0d494ff | 15 | #include "env.h" |
audim | 1:2944c0d494ff | 16 | |
audim | 1:2944c0d494ff | 17 | #define IP_ADDR "192.168.1.10" |
audim | 1:2944c0d494ff | 18 | #define NET_MASK "255.255.255.0" |
audim | 1:2944c0d494ff | 19 | #define GATEWAY "192.168.1.1" |
audim | 1:2944c0d494ff | 20 | #define TFTP_PORT 69 |
audim | 1:2944c0d494ff | 21 | |
audim | 1:2944c0d494ff | 22 | #define LED_ON 0 |
audim | 1:2944c0d494ff | 23 | #define LED_OFF 1 |
audim | 1:2944c0d494ff | 24 | |
audim | 1:2944c0d494ff | 25 | // status LEDs |
audim | 1:2944c0d494ff | 26 | DigitalOut led_error(LED1); // red |
audim | 1:2944c0d494ff | 27 | DigitalOut led_waiting(LED2); // green |
audim | 1:2944c0d494ff | 28 | DigitalOut led_connected(LED3); // blue |
audim | 1:2944c0d494ff | 29 | |
audim | 1:2944c0d494ff | 30 | // TFTP opcodes |
audim | 1:2944c0d494ff | 31 | enum opcode { RRQ=1, WRQ, DATA, ACK, ERROR }; |
audim | 1:2944c0d494ff | 32 | |
audim | 1:2944c0d494ff | 33 | // TFTP packet structure |
audim | 1:2944c0d494ff | 34 | typedef union { |
audim | 1:2944c0d494ff | 35 | |
audim | 1:2944c0d494ff | 36 | uint16_t opcode; |
audim | 1:2944c0d494ff | 37 | |
audim | 1:2944c0d494ff | 38 | struct { |
audim | 1:2944c0d494ff | 39 | uint16_t opcode; // RRQ or WRQ |
audim | 1:2944c0d494ff | 40 | char filename_and_mode[512]; |
audim | 1:2944c0d494ff | 41 | } request; |
issaiass | 0:bbc9cfdee3bc | 42 | |
audim | 1:2944c0d494ff | 43 | struct { |
audim | 1:2944c0d494ff | 44 | uint16_t opcode; // DATA |
audim | 1:2944c0d494ff | 45 | uint16_t block_number; |
audim | 1:2944c0d494ff | 46 | char data[512]; |
audim | 1:2944c0d494ff | 47 | } data; |
audim | 1:2944c0d494ff | 48 | |
audim | 1:2944c0d494ff | 49 | struct { |
audim | 1:2944c0d494ff | 50 | uint16_t opcode; // ACK |
audim | 1:2944c0d494ff | 51 | uint16_t block_number; |
audim | 1:2944c0d494ff | 52 | } ack; |
audim | 1:2944c0d494ff | 53 | |
audim | 1:2944c0d494ff | 54 | struct { |
audim | 1:2944c0d494ff | 55 | uint16_t opcode; // ERROR |
audim | 1:2944c0d494ff | 56 | uint16_t error_code; |
audim | 1:2944c0d494ff | 57 | char error_string[512]; |
audim | 1:2944c0d494ff | 58 | } error; |
audim | 1:2944c0d494ff | 59 | |
audim | 1:2944c0d494ff | 60 | } tftp_packet_t; |
audim | 1:2944c0d494ff | 61 | |
audim | 1:2944c0d494ff | 62 | int tftp_send_error(UDPSocket socket, Endpoint end_point, int error_code, char *error_string) { |
audim | 1:2944c0d494ff | 63 | |
audim | 1:2944c0d494ff | 64 | tftp_packet_t packet; |
audim | 1:2944c0d494ff | 65 | char *packet_ptr = (char *)&packet; |
audim | 1:2944c0d494ff | 66 | |
audim | 1:2944c0d494ff | 67 | packet.opcode = htons(ERROR); |
audim | 1:2944c0d494ff | 68 | packet.error.error_code = htons(error_code); |
audim | 1:2944c0d494ff | 69 | strcpy(packet.error.error_string, error_string); |
audim | 1:2944c0d494ff | 70 | |
audim | 1:2944c0d494ff | 71 | return socket.sendTo(end_point, packet_ptr, 4 + strlen(error_string)); // 4 = sizeof(opcode + error_code) |
audim | 1:2944c0d494ff | 72 | } |
audim | 1:2944c0d494ff | 73 | |
issaiass | 0:bbc9cfdee3bc | 74 | int main (void) { |
audim | 1:2944c0d494ff | 75 | |
audim | 2:28ddb9b073ec | 76 | // Ethernet infrastructure |
issaiass | 0:bbc9cfdee3bc | 77 | EthernetInterface eth; |
audim | 1:2944c0d494ff | 78 | UDPSocket tftp_server; |
audim | 1:2944c0d494ff | 79 | Endpoint client; |
audim | 1:2944c0d494ff | 80 | |
audim | 2:28ddb9b073ec | 81 | // data packet storage |
audim | 1:2944c0d494ff | 82 | tftp_packet_t packet; |
audim | 1:2944c0d494ff | 83 | char *packet_ptr = (char *)&packet; |
audim | 1:2944c0d494ff | 84 | |
audim | 1:2944c0d494ff | 85 | // assign ip address, net mask and gateway to Ethernet interface |
audim | 1:2944c0d494ff | 86 | eth.init(IP_ADDR, NET_MASK, GATEWAY); |
issaiass | 0:bbc9cfdee3bc | 87 | eth.connect(); |
issaiass | 0:bbc9cfdee3bc | 88 | |
audim | 1:2944c0d494ff | 89 | // main loop |
issaiass | 0:bbc9cfdee3bc | 90 | while (true) { |
audim | 1:2944c0d494ff | 91 | |
audim | 1:2944c0d494ff | 92 | // clear status LEDs |
audim | 1:2944c0d494ff | 93 | led_error = LED_OFF; |
audim | 1:2944c0d494ff | 94 | led_waiting = LED_OFF; |
audim | 1:2944c0d494ff | 95 | led_connected = LED_OFF; |
audim | 1:2944c0d494ff | 96 | wait(1); // one second |
audim | 1:2944c0d494ff | 97 | |
audim | 1:2944c0d494ff | 98 | // wait for request |
audim | 1:2944c0d494ff | 99 | led_waiting = LED_ON; |
audim | 1:2944c0d494ff | 100 | tftp_server.bind(TFTP_PORT); |
audim | 1:2944c0d494ff | 101 | tftp_server.receiveFrom(client, packet_ptr, sizeof(packet)); |
audim | 2:28ddb9b073ec | 102 | led_waiting = LED_OFF; |
audim | 1:2944c0d494ff | 103 | |
audim | 1:2944c0d494ff | 104 | // if it's a read request |
audim | 1:2944c0d494ff | 105 | if (ntohs(packet.opcode) == RRQ) { |
audim | 1:2944c0d494ff | 106 | // and it's for the environment file |
audim | 1:2944c0d494ff | 107 | if (!strncmp(packet.request.filename_and_mode, "/production/u-boot-env_txt", 26)) { |
audim | 1:2944c0d494ff | 108 | // send file |
audim | 1:2944c0d494ff | 109 | int i_block = 1; |
audim | 1:2944c0d494ff | 110 | int i_string = 0; |
audim | 1:2944c0d494ff | 111 | int i_char = 0; |
audim | 1:2944c0d494ff | 112 | int i_buff = 512; |
audim | 1:2944c0d494ff | 113 | while (i_buff == 512) { |
audim | 1:2944c0d494ff | 114 | led_connected = LED_ON; |
audim | 1:2944c0d494ff | 115 | i_buff = 0; |
audim | 1:2944c0d494ff | 116 | packet.opcode = htons(DATA); |
audim | 1:2944c0d494ff | 117 | packet.data.block_number = htons(i_block++); |
audim | 1:2944c0d494ff | 118 | do { |
audim | 1:2944c0d494ff | 119 | packet.data.data[i_buff++] = env_string[i_string][i_char++]; |
audim | 1:2944c0d494ff | 120 | // check for end of string |
audim | 1:2944c0d494ff | 121 | if (env_string[i_string][i_char] == '\0') { |
audim | 1:2944c0d494ff | 122 | i_char = 0; |
audim | 1:2944c0d494ff | 123 | i_string++; |
audim | 1:2944c0d494ff | 124 | } |
audim | 1:2944c0d494ff | 125 | } while ((i_buff < 512) && (env_string[i_string][0] != '\0')); |
audim | 1:2944c0d494ff | 126 | tftp_server.sendTo(client, packet_ptr, 4 + i_buff); // 4 = sizeof(opcode + block_number) |
audim | 1:2944c0d494ff | 127 | led_connected = LED_OFF; |
audim | 1:2944c0d494ff | 128 | led_error = LED_ON; |
audim | 1:2944c0d494ff | 129 | tftp_server.receiveFrom(client, packet_ptr, sizeof(packet)); // wait for ACK |
audim | 1:2944c0d494ff | 130 | led_error = LED_OFF; |
audim | 1:2944c0d494ff | 131 | }; |
audim | 1:2944c0d494ff | 132 | } |
audim | 2:28ddb9b073ec | 133 | // or the binary test file |
audim | 2:28ddb9b073ec | 134 | else if (!strncmp(packet.request.filename_and_mode, "/production/ethtest_bin", 23)) { |
audim | 2:28ddb9b073ec | 135 | // send a 4M byte file (8192 512-byte blocks) |
audim | 2:28ddb9b073ec | 136 | for (int block = 1; block < 8194; block++) { // blocks 1-8192 are full, block 8193 is empty (end of file) |
audim | 2:28ddb9b073ec | 137 | led_connected = LED_ON; |
audim | 2:28ddb9b073ec | 138 | packet.opcode = htons(DATA); |
audim | 2:28ddb9b073ec | 139 | packet.data.block_number = htons(block); |
audim | 2:28ddb9b073ec | 140 | // fill packet with Gray code |
audim | 2:28ddb9b073ec | 141 | for (uint16_t w=0; w<256; w++) { |
audim | 2:28ddb9b073ec | 142 | packet.data.data[w] = (char)((w>>1)^w); |
audim | 2:28ddb9b073ec | 143 | packet.data.data[256+w] = ~packet.data.data[w]; |
audim | 2:28ddb9b073ec | 144 | } |
audim | 2:28ddb9b073ec | 145 | tftp_server.sendTo(client, packet_ptr, (block<8193) ? 516 : 4); // 4 = sizeof(opcode + block_number) |
audim | 2:28ddb9b073ec | 146 | led_connected = LED_OFF; |
audim | 2:28ddb9b073ec | 147 | led_error = LED_ON; |
audim | 2:28ddb9b073ec | 148 | tftp_server.receiveFrom(client, packet_ptr, sizeof(packet)); // wait for ACK |
audim | 2:28ddb9b073ec | 149 | led_error = LED_OFF; |
audim | 2:28ddb9b073ec | 150 | } |
audim | 2:28ddb9b073ec | 151 | } |
audim | 2:28ddb9b073ec | 152 | // error, we only support a couple of files |
audim | 2:28ddb9b073ec | 153 | else { |
audim | 2:28ddb9b073ec | 154 | led_error = LED_ON; |
audim | 2:28ddb9b073ec | 155 | tftp_send_error(tftp_server, client, 0, "file not found, this board only has u-boot-env_txt and ethtest_bin"); |
audim | 2:28ddb9b073ec | 156 | wait(3); // three seconds |
audim | 2:28ddb9b073ec | 157 | led_error = LED_OFF; |
audim | 2:28ddb9b073ec | 158 | } |
issaiass | 0:bbc9cfdee3bc | 159 | } |
audim | 1:2944c0d494ff | 160 | // error, we only support read requests |
audim | 2:28ddb9b073ec | 161 | else { |
audim | 2:28ddb9b073ec | 162 | led_error = LED_ON; |
audim | 2:28ddb9b073ec | 163 | tftp_send_error(tftp_server, client, 0, "this test board only supports read requests"); |
audim | 2:28ddb9b073ec | 164 | wait(3); // three seconds |
audim | 2:28ddb9b073ec | 165 | led_error = LED_OFF; |
audim | 2:28ddb9b073ec | 166 | } |
audim | 1:2944c0d494ff | 167 | |
audim | 1:2944c0d494ff | 168 | led_connected = LED_ON; |
audim | 1:2944c0d494ff | 169 | led_waiting = LED_ON; |
audim | 1:2944c0d494ff | 170 | wait(1); // one second |
audim | 1:2944c0d494ff | 171 | tftp_server.close(); |
issaiass | 0:bbc9cfdee3bc | 172 | } |
audim | 1:2944c0d494ff | 173 | } |