Super lightweight, not at all robust, TFTP server for FRDM-K64F eval board.

Dependencies:   EthernetInterface mbed-rtos mbed

Fork of FRDM_K64F-Ethernet by Rangel Alvarado

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.

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?

UserRevisionLine numberNew 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 }