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 15:25:58 2018 +0000
Revision:
1:2944c0d494ff
Parent:
0:bbc9cfdee3bc
Child:
2:28ddb9b073ec
first working concept; only supports ETH0 due to "eTSEC1" setting in environment variables

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 1:2944c0d494ff 3 ** This tool supports read-only access to one file. It does not support NACK responses
audim 1:2944c0d494ff 4 ** or timeouts. The tool is intended for use by our test department to check out Ethernet
audim 1:2944c0d494ff 5 ** 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
issaiass 0:bbc9cfdee3bc 76 EthernetInterface eth;
audim 1:2944c0d494ff 77 UDPSocket tftp_server;
audim 1:2944c0d494ff 78 Endpoint client;
audim 1:2944c0d494ff 79
audim 1:2944c0d494ff 80 // create data packet storage
audim 1:2944c0d494ff 81 tftp_packet_t packet;
audim 1:2944c0d494ff 82 char *packet_ptr = (char *)&packet;
audim 1:2944c0d494ff 83
audim 1:2944c0d494ff 84 // assign ip address, net mask and gateway to Ethernet interface
audim 1:2944c0d494ff 85 eth.init(IP_ADDR, NET_MASK, GATEWAY);
issaiass 0:bbc9cfdee3bc 86 eth.connect();
issaiass 0:bbc9cfdee3bc 87
audim 1:2944c0d494ff 88 // main loop
issaiass 0:bbc9cfdee3bc 89 while (true) {
audim 1:2944c0d494ff 90
audim 1:2944c0d494ff 91 // clear status LEDs
audim 1:2944c0d494ff 92 led_error = LED_OFF;
audim 1:2944c0d494ff 93 led_waiting = LED_OFF;
audim 1:2944c0d494ff 94 led_connected = LED_OFF;
audim 1:2944c0d494ff 95 wait(1); // one second
audim 1:2944c0d494ff 96
audim 1:2944c0d494ff 97 // wait for request
audim 1:2944c0d494ff 98 led_waiting = LED_ON;
audim 1:2944c0d494ff 99 tftp_server.bind(TFTP_PORT);
audim 1:2944c0d494ff 100 tftp_server.receiveFrom(client, packet_ptr, sizeof(packet));
audim 1:2944c0d494ff 101
audim 1:2944c0d494ff 102 // if it's a read request
audim 1:2944c0d494ff 103 if (ntohs(packet.opcode) == RRQ) {
audim 1:2944c0d494ff 104 // and it's for the environment file
audim 1:2944c0d494ff 105 if (!strncmp(packet.request.filename_and_mode, "/production/u-boot-env_txt", 26)) {
audim 1:2944c0d494ff 106 led_waiting = LED_OFF;
audim 1:2944c0d494ff 107 // send file
audim 1:2944c0d494ff 108 int i_block = 1;
audim 1:2944c0d494ff 109 int i_string = 0;
audim 1:2944c0d494ff 110 int i_char = 0;
audim 1:2944c0d494ff 111 int i_buff = 512;
audim 1:2944c0d494ff 112 while (i_buff == 512) {
audim 1:2944c0d494ff 113 led_connected = LED_ON;
audim 1:2944c0d494ff 114 i_buff = 0;
audim 1:2944c0d494ff 115 packet.opcode = htons(DATA);
audim 1:2944c0d494ff 116 packet.data.block_number = htons(i_block++);
audim 1:2944c0d494ff 117 do {
audim 1:2944c0d494ff 118 packet.data.data[i_buff++] = env_string[i_string][i_char++];
audim 1:2944c0d494ff 119 // check for end of string
audim 1:2944c0d494ff 120 if (env_string[i_string][i_char] == '\0') {
audim 1:2944c0d494ff 121 i_char = 0;
audim 1:2944c0d494ff 122 i_string++;
audim 1:2944c0d494ff 123 }
audim 1:2944c0d494ff 124 } while ((i_buff < 512) && (env_string[i_string][0] != '\0'));
audim 1:2944c0d494ff 125 tftp_server.sendTo(client, packet_ptr, 4 + i_buff); // 4 = sizeof(opcode + block_number)
audim 1:2944c0d494ff 126 led_connected = LED_OFF;
audim 1:2944c0d494ff 127 led_error = LED_ON;
audim 1:2944c0d494ff 128 tftp_server.receiveFrom(client, packet_ptr, sizeof(packet)); // wait for ACK
audim 1:2944c0d494ff 129 led_error = LED_OFF;
audim 1:2944c0d494ff 130 };
audim 1:2944c0d494ff 131 }
audim 1:2944c0d494ff 132 // error, we only support the u-boot-env.txt file
audim 1:2944c0d494ff 133 else tftp_send_error(tftp_server, client, 0, "this test board only supports reading the u-boot-env.txt file");
issaiass 0:bbc9cfdee3bc 134 }
audim 1:2944c0d494ff 135 // error, we only support read requests
audim 1:2944c0d494ff 136 else tftp_send_error(tftp_server, client, 0, "this test board only supports reading the u-boot-env.txt file");
audim 1:2944c0d494ff 137
audim 1:2944c0d494ff 138 led_connected = LED_ON;
audim 1:2944c0d494ff 139 led_waiting = LED_ON;
audim 1:2944c0d494ff 140 wait(1); // one second
audim 1:2944c0d494ff 141 tftp_server.close();
issaiass 0:bbc9cfdee3bc 142 }
audim 1:2944c0d494ff 143 }