Ethernet for the NUCLEO STM32F746 Board Testprogram uses DHCP and NTP to set the clock. At the moment there are dependencies to the used compiler. It works with the online compiler

Dependencies:   F7_Ethernet mbed

Committer:
DieterGraef
Date:
Sat Jun 18 10:49:12 2016 +0000
Revision:
0:f9b6112278fe
Ethernet for the NUCLEO STM32F746 Board Testprogram uses DHCP and NTP to set the clock

Who changed what in which revision?

UserRevisionLine numberNew contents of line
DieterGraef 0:f9b6112278fe 1 /* NTPClient.cpp */
DieterGraef 0:f9b6112278fe 2 /* Copyright (C) 2012 mbed.org, MIT License
DieterGraef 0:f9b6112278fe 3 *
DieterGraef 0:f9b6112278fe 4 * Permission is hereby granted, free of charge, to any person obtaining a copy of this software
DieterGraef 0:f9b6112278fe 5 * and associated documentation files (the "Software"), to deal in the Software without restriction,
DieterGraef 0:f9b6112278fe 6 * including without limitation the rights to use, copy, modify, merge, publish, distribute,
DieterGraef 0:f9b6112278fe 7 * sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is
DieterGraef 0:f9b6112278fe 8 * furnished to do so, subject to the following conditions:
DieterGraef 0:f9b6112278fe 9 *
DieterGraef 0:f9b6112278fe 10 * The above copyright notice and this permission notice shall be included in all copies or
DieterGraef 0:f9b6112278fe 11 * substantial portions of the Software.
DieterGraef 0:f9b6112278fe 12 *
DieterGraef 0:f9b6112278fe 13 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
DieterGraef 0:f9b6112278fe 14 * BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
DieterGraef 0:f9b6112278fe 15 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
DieterGraef 0:f9b6112278fe 16 * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
DieterGraef 0:f9b6112278fe 17 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
DieterGraef 0:f9b6112278fe 18 */
DieterGraef 0:f9b6112278fe 19
DieterGraef 0:f9b6112278fe 20 //Debug is disabled by default
DieterGraef 0:f9b6112278fe 21 #if 0
DieterGraef 0:f9b6112278fe 22 //Enable debug
DieterGraef 0:f9b6112278fe 23 #define __DEBUG__
DieterGraef 0:f9b6112278fe 24 #include <cstdio>
DieterGraef 0:f9b6112278fe 25 #define DBG(x, ...) std::printf("[NTPClient : DBG]"x"\r\n", ##__VA_ARGS__);
DieterGraef 0:f9b6112278fe 26 #define WARN(x, ...) std::printf("[NTPClient : WARN]"x"\r\n", ##__VA_ARGS__);
DieterGraef 0:f9b6112278fe 27 #define ERR(x, ...) std::printf("[NTPClient : ERR]"x"\r\n", ##__VA_ARGS__);
DieterGraef 0:f9b6112278fe 28
DieterGraef 0:f9b6112278fe 29 #else
DieterGraef 0:f9b6112278fe 30 //Disable debug
DieterGraef 0:f9b6112278fe 31 #define DBG(x, ...)
DieterGraef 0:f9b6112278fe 32 #define WARN(x, ...)
DieterGraef 0:f9b6112278fe 33 #define ERR(x, ...)
DieterGraef 0:f9b6112278fe 34
DieterGraef 0:f9b6112278fe 35 #endif
DieterGraef 0:f9b6112278fe 36
DieterGraef 0:f9b6112278fe 37 #include "NTPClient.h"
DieterGraef 0:f9b6112278fe 38
DieterGraef 0:f9b6112278fe 39 #include "UDPSocket.h"
DieterGraef 0:f9b6112278fe 40
DieterGraef 0:f9b6112278fe 41 #include "mbed.h" //time() and set_time()
DieterGraef 0:f9b6112278fe 42
DieterGraef 0:f9b6112278fe 43 #define NTP_PORT 123
DieterGraef 0:f9b6112278fe 44 #define NTP_CLIENT_PORT 0 //Random port
DieterGraef 0:f9b6112278fe 45 #define NTP_TIMESTAMP_DELTA 2208988800ull //Diff btw a UNIX timestamp (Starting Jan, 1st 1970) and a NTP timestamp (Starting Jan, 1st 1900)
DieterGraef 0:f9b6112278fe 46
DieterGraef 0:f9b6112278fe 47 NTPClient::NTPClient() : m_sock()
DieterGraef 0:f9b6112278fe 48 {
DieterGraef 0:f9b6112278fe 49
DieterGraef 0:f9b6112278fe 50
DieterGraef 0:f9b6112278fe 51 }
DieterGraef 0:f9b6112278fe 52
DieterGraef 0:f9b6112278fe 53 NTPResult NTPClient::setTime(const char* host, uint16_t port, uint32_t timeout)
DieterGraef 0:f9b6112278fe 54 {
DieterGraef 0:f9b6112278fe 55 #ifdef __DEBUG__
DieterGraef 0:f9b6112278fe 56 time_t ctTime;
DieterGraef 0:f9b6112278fe 57 ctTime = time(NULL);
DieterGraef 0:f9b6112278fe 58 DBG("Time is set to (UTC): %s", ctime(&ctTime));
DieterGraef 0:f9b6112278fe 59 #endif
DieterGraef 0:f9b6112278fe 60
DieterGraef 0:f9b6112278fe 61 //Create & bind socket
DieterGraef 0:f9b6112278fe 62 DBG("Binding socket");
DieterGraef 0:f9b6112278fe 63 m_sock.bind(0); //Bind to a random port
DieterGraef 0:f9b6112278fe 64
DieterGraef 0:f9b6112278fe 65 m_sock.set_blocking(false, timeout); //Set not blocking
DieterGraef 0:f9b6112278fe 66
DieterGraef 0:f9b6112278fe 67 struct NTPPacket pkt;
DieterGraef 0:f9b6112278fe 68
DieterGraef 0:f9b6112278fe 69 //Now ping the server and wait for response
DieterGraef 0:f9b6112278fe 70 DBG("Ping");
DieterGraef 0:f9b6112278fe 71 //Prepare NTP Packet:
DieterGraef 0:f9b6112278fe 72 pkt.li = 0; //Leap Indicator : No warning
DieterGraef 0:f9b6112278fe 73 pkt.vn = 4; //Version Number : 4
DieterGraef 0:f9b6112278fe 74 pkt.mode = 3; //Client mode
DieterGraef 0:f9b6112278fe 75 pkt.stratum = 0; //Not relevant here
DieterGraef 0:f9b6112278fe 76 pkt.poll = 0; //Not significant as well
DieterGraef 0:f9b6112278fe 77 pkt.precision = 0; //Neither this one is
DieterGraef 0:f9b6112278fe 78
DieterGraef 0:f9b6112278fe 79 pkt.rootDelay = 0; //Or this one
DieterGraef 0:f9b6112278fe 80 pkt.rootDispersion = 0; //Or that one
DieterGraef 0:f9b6112278fe 81 pkt.refId = 0; //...
DieterGraef 0:f9b6112278fe 82
DieterGraef 0:f9b6112278fe 83 pkt.refTm_s = 0;
DieterGraef 0:f9b6112278fe 84 pkt.origTm_s = 0;
DieterGraef 0:f9b6112278fe 85 pkt.rxTm_s = 0;
DieterGraef 0:f9b6112278fe 86 pkt.txTm_s = htonl( NTP_TIMESTAMP_DELTA + time(NULL) ); //WARN: We are in LE format, network byte order is BE
DieterGraef 0:f9b6112278fe 87
DieterGraef 0:f9b6112278fe 88 pkt.refTm_f = pkt.origTm_f = pkt.rxTm_f = pkt.txTm_f = 0;
DieterGraef 0:f9b6112278fe 89
DieterGraef 0:f9b6112278fe 90 Endpoint outEndpoint;
DieterGraef 0:f9b6112278fe 91
DieterGraef 0:f9b6112278fe 92 if( outEndpoint.set_address(host, port) < 0)
DieterGraef 0:f9b6112278fe 93 {
DieterGraef 0:f9b6112278fe 94 m_sock.close();
DieterGraef 0:f9b6112278fe 95 return NTP_DNS;
DieterGraef 0:f9b6112278fe 96 }
DieterGraef 0:f9b6112278fe 97
DieterGraef 0:f9b6112278fe 98 //Set timeout, non-blocking and wait using select
DieterGraef 0:f9b6112278fe 99 int ret = m_sock.sendTo( outEndpoint, (char*)&pkt, sizeof(NTPPacket) );
DieterGraef 0:f9b6112278fe 100 if (ret < 0 )
DieterGraef 0:f9b6112278fe 101 {
DieterGraef 0:f9b6112278fe 102 ERR("Could not send packet");
DieterGraef 0:f9b6112278fe 103 m_sock.close();
DieterGraef 0:f9b6112278fe 104 return NTP_CONN;
DieterGraef 0:f9b6112278fe 105 }
DieterGraef 0:f9b6112278fe 106
DieterGraef 0:f9b6112278fe 107 //Read response
DieterGraef 0:f9b6112278fe 108 Endpoint inEndpoint;
DieterGraef 0:f9b6112278fe 109 // Set the inEndpoint address property
DieterGraef 0:f9b6112278fe 110 inEndpoint.set_address(outEndpoint.get_address(), 0);
DieterGraef 0:f9b6112278fe 111 DBG("Pong");
DieterGraef 0:f9b6112278fe 112 do
DieterGraef 0:f9b6112278fe 113 {
DieterGraef 0:f9b6112278fe 114 ret = m_sock.receiveFrom( inEndpoint, (char*)&pkt, sizeof(NTPPacket) ); //FIXME need a DNS Resolver to actually compare the incoming address with the DNS name
DieterGraef 0:f9b6112278fe 115 if(ret < 0)
DieterGraef 0:f9b6112278fe 116 {
DieterGraef 0:f9b6112278fe 117 ERR("Could not receive packet");
DieterGraef 0:f9b6112278fe 118 m_sock.close();
DieterGraef 0:f9b6112278fe 119 return NTP_CONN;
DieterGraef 0:f9b6112278fe 120 }
DieterGraef 0:f9b6112278fe 121 } while( strcmp(outEndpoint.get_address(), inEndpoint.get_address()) != 0 );
DieterGraef 0:f9b6112278fe 122
DieterGraef 0:f9b6112278fe 123 if(ret < sizeof(NTPPacket)) //TODO: Accept chunks
DieterGraef 0:f9b6112278fe 124 {
DieterGraef 0:f9b6112278fe 125 ERR("Receive packet size does not match");
DieterGraef 0:f9b6112278fe 126 m_sock.close();
DieterGraef 0:f9b6112278fe 127 return NTP_PRTCL;
DieterGraef 0:f9b6112278fe 128 }
DieterGraef 0:f9b6112278fe 129
DieterGraef 0:f9b6112278fe 130 if( pkt.stratum == 0) //Kiss of death message : Not good !
DieterGraef 0:f9b6112278fe 131 {
DieterGraef 0:f9b6112278fe 132 ERR("Kissed to death!");
DieterGraef 0:f9b6112278fe 133 m_sock.close();
DieterGraef 0:f9b6112278fe 134 return NTP_PRTCL;
DieterGraef 0:f9b6112278fe 135 }
DieterGraef 0:f9b6112278fe 136
DieterGraef 0:f9b6112278fe 137 //Correct Endianness
DieterGraef 0:f9b6112278fe 138 pkt.refTm_s = ntohl( pkt.refTm_s );
DieterGraef 0:f9b6112278fe 139 pkt.refTm_f = ntohl( pkt.refTm_f );
DieterGraef 0:f9b6112278fe 140 pkt.origTm_s = ntohl( pkt.origTm_s );
DieterGraef 0:f9b6112278fe 141 pkt.origTm_f = ntohl( pkt.origTm_f );
DieterGraef 0:f9b6112278fe 142 pkt.rxTm_s = ntohl( pkt.rxTm_s );
DieterGraef 0:f9b6112278fe 143 pkt.rxTm_f = ntohl( pkt.rxTm_f );
DieterGraef 0:f9b6112278fe 144 pkt.txTm_s = ntohl( pkt.txTm_s );
DieterGraef 0:f9b6112278fe 145 pkt.txTm_f = ntohl( pkt.txTm_f );
DieterGraef 0:f9b6112278fe 146
DieterGraef 0:f9b6112278fe 147 //Compute offset, see RFC 4330 p.13
DieterGraef 0:f9b6112278fe 148 uint32_t destTm_s = (NTP_TIMESTAMP_DELTA + time(NULL));
DieterGraef 0:f9b6112278fe 149 int64_t offset = ( (int64_t)( pkt.rxTm_s - pkt.origTm_s ) + (int64_t) ( pkt.txTm_s - destTm_s ) ) / 2; //Avoid overflow
DieterGraef 0:f9b6112278fe 150 DBG("Sent @%ul", pkt.txTm_s);
DieterGraef 0:f9b6112278fe 151 DBG("Offset: %lld", offset);
DieterGraef 0:f9b6112278fe 152 //Set time accordingly
DieterGraef 0:f9b6112278fe 153 set_time( time(NULL) + offset );
DieterGraef 0:f9b6112278fe 154
DieterGraef 0:f9b6112278fe 155 #ifdef __DEBUG__
DieterGraef 0:f9b6112278fe 156 ctTime = time(NULL);
DieterGraef 0:f9b6112278fe 157 DBG("Time is now (UTC): %s", ctime(&ctTime));
DieterGraef 0:f9b6112278fe 158 #endif
DieterGraef 0:f9b6112278fe 159
DieterGraef 0:f9b6112278fe 160 m_sock.close();
DieterGraef 0:f9b6112278fe 161
DieterGraef 0:f9b6112278fe 162 return NTP_OK;
DieterGraef 0:f9b6112278fe 163 }
DieterGraef 0:f9b6112278fe 164