?lang_form? ?lang_select? ?lang_submit? ?lang_endform?
{HEADER END}
{BLAME START}

library

?curdirlinks? -

Blame information for rev 32

Line No. Rev Author Line
1 32 kaklik /*********************************************************************
2 *
3 * Simple Network Time Protocol (SNTP) Client Version 3
4 * Module for Microchip TCP/IP Stack
5 * -Locates an NTP Server from public site using DNS
6 * -Requests UTC time using SNTP and updates SNTPTime structure
7 * periodically, according to NTP_QUERY_INTERVAL value
8 * - Reference: RFC 1305
9 *
10 *********************************************************************
11 * FileName: SNTP.c
12 * Dependencies: UDP, ARP, DNS, Tick
13 * Processor: PIC18, PIC24F, PIC24H, dsPIC30F, dsPIC33F, PIC32
14 * Compiler: Microchip C32 v1.05 or higher
15 * Microchip C30 v3.12 or higher
16 * Microchip C18 v3.30 or higher
17 * HI-TECH PICC-18 PRO 9.63PL2 or higher
18 * Company: Microchip Technology, Inc.
19 *
20 * Software License Agreement
21 *
22 * Copyright (C) 2002-2009 Microchip Technology Inc. All rights
23 * reserved.
24 *
25 * Microchip licenses to you the right to use, modify, copy, and
26 * distribute:
27 * (i) the Software when embedded on a Microchip microcontroller or
28 * digital signal controller product ("Device") which is
29 * integrated into Licensee's product; or
30 * (ii) ONLY the Software driver source files ENC28J60.c, ENC28J60.h,
31 * ENCX24J600.c and ENCX24J600.h ported to a non-Microchip device
32 * used in conjunction with a Microchip ethernet controller for
33 * the sole purpose of interfacing with the ethernet controller.
34 *
35 * You should refer to the license agreement accompanying this
36 * Software for additional information regarding your rights and
37 * obligations.
38 *
39 * THE SOFTWARE AND DOCUMENTATION ARE PROVIDED "AS IS" WITHOUT
40 * WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT
41 * LIMITATION, ANY WARRANTY OF MERCHANTABILITY, FITNESS FOR A
42 * PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT SHALL
43 * MICROCHIP BE LIABLE FOR ANY INCIDENTAL, SPECIAL, INDIRECT OR
44 * CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF
45 * PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY OR SERVICES, ANY CLAIMS
46 * BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE
47 * THEREOF), ANY CLAIMS FOR INDEMNITY OR CONTRIBUTION, OR OTHER
48 * SIMILAR COSTS, WHETHER ASSERTED ON THE BASIS OF CONTRACT, TORT
49 * (INCLUDING NEGLIGENCE), BREACH OF WARRANTY, OR OTHERWISE.
50 *
51 *
52 * Author Date Comment
53 *~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
54 * Darren Wenn 03/08/07 Original
55 * Howard Schlunder 06/20/07 Modified for release
56 ********************************************************************/
57 #define __SNTP_C
58  
59 #include "TCPIPConfig.h"
60  
61 #if defined(STACK_USE_SNTP_CLIENT)
62  
63 #include "TCPIP Stack/TCPIP.h"
64  
65  
66 // Defines how frequently to resynchronize the date/time (default: 10 minutes)
67 #define NTP_QUERY_INTERVAL (10ull*60ull * TICK_SECOND)
68  
69 // Defines how long to wait to retry an update after a failure.
70 // Updates may take up to 6 seconds to fail, so this 14 second delay is actually only an 8-second retry.
71 #define NTP_FAST_QUERY_INTERVAL (14ull * TICK_SECOND)
72  
73 // Port for contacting NTP servers
74 #define NTP_SERVER_PORT (123ul)
75  
76 // Reference Epoch to use. (default: 01-Jan-1970 00:00:00)
77 #define NTP_EPOCH (86400ul * (365ul * 70ul + 17ul))
78  
79 // Defines how long to wait before assuming the query has failed
80 #define NTP_REPLY_TIMEOUT (6ul*TICK_SECOND)
81  
82 // These are normally available network time servers.
83 // The actual IP returned from the pool will vary every
84 // minute so as to spread the load around stratum 1 timeservers.
85 // For best accuracy and network overhead you should locate the
86 // pool server closest to your geography, but it will still work
87 // if you use the global pool.ntp.org address or choose the wrong
88 // one or ship your embedded device to another geography.
89 #define NTP_SERVER "pool.ntp.org"
90 //#define NTP_SERVER "europe.pool.ntp.org"
91 //#define NTP_SERVER "asia.pool.ntp.org"
92 //#define NTP_SERVER "oceania.pool.ntp.org"
93 //#define NTP_SERVER "north-america.pool.ntp.org"
94 //#define NTP_SERVER "south-america.pool.ntp.org"
95 //#define NTP_SERVER "africa.pool.ntp.org"
96  
97 // Defines the structure of an NTP packet
98 typedef struct
99 {
100 struct
101 {
102 BYTE mode : 3; // NTP mode
103 BYTE versionNumber : 3; // SNTP version number
104 BYTE leapIndicator : 2; // Leap second indicator
105 } flags; // Flags for the packet
106  
107 BYTE stratum; // Stratum level of local clock
108 CHAR poll; // Poll interval
109 CHAR precision; // Precision (seconds to nearest power of 2)
110 DWORD root_delay; // Root delay between local machine and server
111 DWORD root_dispersion; // Root dispersion (maximum error)
112 DWORD ref_identifier; // Reference clock identifier
113 DWORD ref_ts_secs; // Reference timestamp (in seconds)
114 DWORD ref_ts_fraq; // Reference timestamp (fractions)
115 DWORD orig_ts_secs; // Origination timestamp (in seconds)
116 DWORD orig_ts_fraq; // Origination timestamp (fractions)
117 DWORD recv_ts_secs; // Time at which request arrived at sender (seconds)
118 DWORD recv_ts_fraq; // Time at which request arrived at sender (fractions)
119 DWORD tx_ts_secs; // Time at which request left sender (seconds)
120 DWORD tx_ts_fraq; // Time at which request left sender (fractions)
121 } NTP_PACKET;
122  
123 // Seconds value obtained by last update
124 static DWORD dwSNTPSeconds = 0;
125  
126 // Tick count of last update
127 static DWORD dwLastUpdateTick = 0;
128  
129  
130 /*****************************************************************************
131 Function:
132 void SNTPClient(void)
133  
134 Summary:
135 Periodically checks the current time from a pool of servers.
136  
137 Description:
138 This function periodically checks a pool of time servers to obtain the
139 current date/time.
140  
141 Precondition:
142 UDP is initialized.
143  
144 Parameters:
145 None
146  
147 Returns:
148 None
149  
150 Remarks:
151 This function requires once available UDP socket while processing, but
152 frees that socket when the SNTP module is idle.
153 ***************************************************************************/
154 void SNTPClient(void)
155 {
156 NTP_PACKET pkt;
157 WORD w;
158 static NODE_INFO Server;
159 static DWORD dwTimer;
160 static UDP_SOCKET MySocket;
161 static enum
162 {
163 SM_HOME = 0,
164 SM_NAME_RESOLVE,
165 SM_ARP_START_RESOLVE,
166 SM_ARP_RESOLVE,
167 SM_ARP_START_RESOLVE2,
168 SM_ARP_RESOLVE2,
169 SM_ARP_START_RESOLVE3,
170 SM_ARP_RESOLVE3,
171 SM_ARP_RESOLVE_FAIL,
172 SM_UDP_SEND,
173 SM_UDP_RECV,
174 SM_SHORT_WAIT,
175 SM_WAIT
176 } SNTPState = SM_HOME;
177  
178 switch(SNTPState)
179 {
180 case SM_HOME:
181 // Obtain ownership of the DNS resolution module
182 if(!DNSBeginUsage())
183 break;
184  
185 // Obtain the IP address associated with the server name
186 DNSResolveROM((ROM BYTE*)NTP_SERVER, DNS_TYPE_A);
187 dwTimer = TickGet();
188 SNTPState = SM_NAME_RESOLVE;
189 break;
190  
191 case SM_NAME_RESOLVE:
192 // Wait for DNS resolution to complete
193 if(!DNSIsResolved(&Server.IPAddr))
194 {
195 if((TickGet() - dwTimer) > (5 * TICK_SECOND))
196 {
197 DNSEndUsage();
198 dwTimer = TickGetDiv64K();
199 SNTPState = SM_SHORT_WAIT;
200 }
201 break;
202 }
203  
204 // Obtain DNS resolution result
205 if(!DNSEndUsage())
206 {
207 // No valid IP address was returned from the DNS
208 // server. Quit and fail for a while if host is not valid.
209 dwTimer = TickGetDiv64K();
210 SNTPState = SM_SHORT_WAIT;
211 break;
212 }
213 SNTPState = SM_ARP_START_RESOLVE;
214 // No need to break
215  
216 case SM_ARP_START_RESOLVE:
217 case SM_ARP_START_RESOLVE2:
218 case SM_ARP_START_RESOLVE3:
219 // Obtain the MAC address associated with the server's IP address
220 ARPResolve(&Server.IPAddr);
221 dwTimer = TickGet();
222 SNTPState++;
223 break;
224  
225 case SM_ARP_RESOLVE:
226 case SM_ARP_RESOLVE2:
227 case SM_ARP_RESOLVE3:
228 // Wait for the MAC address to finish being obtained
229 if(!ARPIsResolved(&Server.IPAddr, &Server.MACAddr))
230 {
231 // Time out if too much time is spent in this state
232 if(TickGet() - dwTimer > 1*TICK_SECOND)
233 {
234 // Retransmit ARP request by going to next SM_ARP_START_RESOLVE state or fail by going to SM_ARP_RESOLVE_FAIL state.
235 SNTPState++;
236 }
237 break;
238 }
239 SNTPState = SM_UDP_SEND;
240 break;
241  
242 case SM_ARP_RESOLVE_FAIL:
243 // ARP failed after 3 tries, abort and wait for next time query
244 dwTimer = TickGetDiv64K();
245 SNTPState = SM_SHORT_WAIT;
246 break;
247  
248 case SM_UDP_SEND:
249 // Open up the sending UDP socket
250 MySocket = UDPOpen(0, &Server, NTP_SERVER_PORT);
251 if(MySocket == INVALID_UDP_SOCKET)
252 break;
253  
254 // Make certain the socket can be written to
255 if(!UDPIsPutReady(MySocket))
256 {
257 UDPClose(MySocket);
258 break;
259 }
260  
261 // Transmit a time request packet
262 memset(&pkt, 0, sizeof(pkt));
263 pkt.flags.versionNumber = 3; // NTP Version 3
264 pkt.flags.mode = 3; // NTP Client
265 pkt.orig_ts_secs = swapl(NTP_EPOCH);
266 UDPPutArray((BYTE*) &pkt, sizeof(pkt));
267 UDPFlush();
268  
269 dwTimer = TickGet();
270 SNTPState = SM_UDP_RECV;
271 break;
272  
273 case SM_UDP_RECV:
274 // Look for a response time packet
275 if(!UDPIsGetReady(MySocket))
276 {
277 if((TickGet()) - dwTimer > NTP_REPLY_TIMEOUT)
278 {
279 // Abort the request and wait until the next timeout period
280 UDPClose(MySocket);
281 dwTimer = TickGetDiv64K();
282 SNTPState = SM_SHORT_WAIT;
283 break;
284 }
285 break;
286 }
287  
288 // Get the response time packet
289 w = UDPGetArray((BYTE*) &pkt, sizeof(pkt));
290 UDPClose(MySocket);
291 dwTimer = TickGetDiv64K();
292 SNTPState = SM_WAIT;
293  
294 // Validate packet size
295 if(w != sizeof(pkt))
296 {
297 break;
298 }
299  
300 // Set out local time to match the returned time
301 dwLastUpdateTick = TickGet();
302 dwSNTPSeconds = swapl(pkt.tx_ts_secs) - NTP_EPOCH;
303 // Do rounding. If the partial seconds is > 0.5 then add 1 to the seconds count.
304 if(((BYTE*)&pkt.tx_ts_fraq)[0] & 0x80)
305 dwSNTPSeconds++;
306  
307 break;
308  
309 case SM_SHORT_WAIT:
310 // Attempt to requery the NTP server after a specified NTP_FAST_QUERY_INTERVAL time (ex: 8 seconds) has elapsed.
311 if(TickGetDiv64K() - dwTimer > (NTP_FAST_QUERY_INTERVAL/65536ull))
312 SNTPState = SM_HOME;
313 break;
314  
315 case SM_WAIT:
316 // Requery the NTP server after a specified NTP_QUERY_INTERVAL time (ex: 10 minutes) has elapsed.
317 if(TickGetDiv64K() - dwTimer > (NTP_QUERY_INTERVAL/65536ull))
318 SNTPState = SM_HOME;
319  
320 break;
321 }
322 }
323  
324  
325 /*****************************************************************************
326 Function:
327 DWORD SNTPGetUTCSeconds(void)
328  
329 Summary:
330 Obtains the current time from the SNTP module.
331  
332 Description:
333 This function obtains the current time as reported by the SNTP module.
334 Use this value for absolute time stamping. The value returned is (by
335 default) the number of seconds since 01-Jan-1970 00:00:00.
336  
337 Precondition:
338 None
339  
340 Parameters:
341 None
342  
343 Returns:
344 The number of seconds since the Epoch. (Default 01-Jan-1970 00:00:00)
345  
346 Remarks:
347 Do not use this function for time difference measurements. The Tick
348 module is more appropriate for those requirements.
349 ***************************************************************************/
350 DWORD SNTPGetUTCSeconds(void)
351 {
352 DWORD dwTickDelta;
353 DWORD dwTick;
354  
355 // Update the dwSNTPSeconds variable with the number of seconds
356 // that has elapsed
357 dwTick = TickGet();
358 dwTickDelta = dwTick - dwLastUpdateTick;
359 while(dwTickDelta > TICK_SECOND)
360 {
361 dwSNTPSeconds++;
362 dwTickDelta -= TICK_SECOND;
363 }
364  
365 // Save the tick and residual fractional seconds for the next call
366 dwLastUpdateTick = dwTick - dwTickDelta;
367  
368 return dwSNTPSeconds;
369 }
370  
371 #endif //if defined(STACK_USE_SNTP_CLIENT)
{BLAME END}
{FOOTER START}

Powered by WebSVN v2.8.3