16
16
17
17
typedef struct NTP_T_ {
18
18
ip_addr_t ntp_server_address ;
19
- bool dns_request_sent ;
20
19
struct udp_pcb * ntp_pcb ;
21
- absolute_time_t ntp_test_time ;
22
- alarm_id_t ntp_resend_alarm ;
20
+ async_at_time_worker_t request_worker ;
21
+ async_at_time_worker_t resend_worker ;
23
22
} NTP_T ;
24
23
25
24
#define NTP_SERVER "pool.ntp.org"
26
25
#define NTP_MSG_LEN 48
27
26
#define NTP_PORT 123
28
27
#define NTP_DELTA 2208988800 // seconds between 1 Jan 1900 and 1 Jan 1970
29
- #define NTP_TEST_TIME (30 * 1000)
30
- #define NTP_RESEND_TIME (10 * 1000)
28
+ #define NTP_TEST_TIME_MS (30 * 1000)
29
+ #define NTP_RESEND_TIME_MS (10 * 1000)
31
30
32
31
// Called with results of operation
33
32
static void ntp_result (NTP_T * state , int status , time_t * result ) {
@@ -36,17 +35,11 @@ static void ntp_result(NTP_T* state, int status, time_t *result) {
36
35
printf ("got ntp response: %02d/%02d/%04d %02d:%02d:%02d\n" , utc -> tm_mday , utc -> tm_mon + 1 , utc -> tm_year + 1900 ,
37
36
utc -> tm_hour , utc -> tm_min , utc -> tm_sec );
38
37
}
39
-
40
- if (state -> ntp_resend_alarm > 0 ) {
41
- cancel_alarm (state -> ntp_resend_alarm );
42
- state -> ntp_resend_alarm = 0 ;
43
- }
44
- state -> ntp_test_time = make_timeout_time_ms (NTP_TEST_TIME );
45
- state -> dns_request_sent = false;
38
+ async_context_remove_at_time_worker (cyw43_arch_async_context (), & state -> resend_worker );
39
+ hard_assert (async_context_add_at_time_worker_in_ms (cyw43_arch_async_context (), & state -> request_worker , NTP_TEST_TIME_MS )); // repeat the request in future
40
+ printf ("Next request in %ds\n" , NTP_TEST_TIME_MS / 1000 );
46
41
}
47
42
48
- static int64_t ntp_failed_handler (alarm_id_t id , void * user_data );
49
-
50
43
// Make an NTP request
51
44
static void ntp_request (NTP_T * state ) {
52
45
// cyw43_arch_lwip_begin/end should be used around calls into lwIP to ensure correct locking.
@@ -63,14 +56,6 @@ static void ntp_request(NTP_T *state) {
63
56
cyw43_arch_lwip_end ();
64
57
}
65
58
66
- static int64_t ntp_failed_handler (alarm_id_t id , void * user_data )
67
- {
68
- NTP_T * state = (NTP_T * )user_data ;
69
- printf ("ntp request failed\n" );
70
- ntp_result (state , -1 , NULL );
71
- return 0 ;
72
- }
73
-
74
59
// Call back with a DNS result
75
60
static void ntp_dns_found (const char * hostname , const ip_addr_t * ipaddr , void * arg ) {
76
61
NTP_T * state = (NTP_T * )arg ;
@@ -106,6 +91,26 @@ static void ntp_recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_ad
106
91
pbuf_free (p );
107
92
}
108
93
94
+ // Called to make a NTP request
95
+ static void request_worker_fn (__unused async_context_t * context , async_at_time_worker_t * worker ) {
96
+ NTP_T * state = (NTP_T * )worker -> user_data ;
97
+ hard_assert (async_context_add_at_time_worker_in_ms (cyw43_arch_async_context (), & state -> resend_worker , NTP_RESEND_TIME_MS )); // in case UDP request is lost
98
+ int err = dns_gethostbyname (NTP_SERVER , & state -> ntp_server_address , ntp_dns_found , state );
99
+ if (err == ERR_OK ) {
100
+ ntp_request (state ); // Cached DNS result, make NTP request
101
+ } else if (err != ERR_INPROGRESS ) { // ERR_INPROGRESS means expect a callback
102
+ printf ("dns request failed\n" );
103
+ ntp_result (state , -1 , NULL );
104
+ }
105
+ }
106
+
107
+ // Called to resend an NTP request if it appears to get lost
108
+ static void resend_worker_fn (__unused async_context_t * context , async_at_time_worker_t * worker ) {
109
+ NTP_T * state = (NTP_T * )worker -> user_data ;
110
+ printf ("ntp request failed\n" );
111
+ ntp_result (state , -1 , NULL );
112
+ }
113
+
109
114
// Perform initialisation
110
115
static NTP_T * ntp_init (void ) {
111
116
NTP_T * state = (NTP_T * )calloc (1 , sizeof (NTP_T ));
@@ -120,6 +125,10 @@ static NTP_T* ntp_init(void) {
120
125
return NULL ;
121
126
}
122
127
udp_recv (state -> ntp_pcb , ntp_recv , state );
128
+ state -> request_worker .do_work = request_worker_fn ;
129
+ state -> request_worker .user_data = state ;
130
+ state -> resend_worker .do_work = resend_worker_fn ;
131
+ state -> resend_worker .user_data = state ;
123
132
return state ;
124
133
}
125
134
@@ -128,34 +137,20 @@ void run_ntp_test(void) {
128
137
NTP_T * state = ntp_init ();
129
138
if (!state )
130
139
return ;
140
+ printf ("Press 'q' to quit\n" );
141
+ hard_assert (async_context_add_at_time_worker_in_ms (cyw43_arch_async_context (), & state -> request_worker , 0 )); // make the first request
131
142
while (true) {
132
- if (absolute_time_diff_us (get_absolute_time (), state -> ntp_test_time ) < 0 && !state -> dns_request_sent ) {
133
- // Set alarm in case udp requests are lost
134
- state -> ntp_resend_alarm = add_alarm_in_ms (NTP_RESEND_TIME , ntp_failed_handler , state , true);
135
-
136
- // cyw43_arch_lwip_begin/end should be used around calls into lwIP to ensure correct locking.
137
- // You can omit them if you are in a callback from lwIP. Note that when using pico_cyw_arch_poll
138
- // these calls are a no-op and can be omitted, but it is a good practice to use them in
139
- // case you switch the cyw43_arch type later.
140
- cyw43_arch_lwip_begin ();
141
- int err = dns_gethostbyname (NTP_SERVER , & state -> ntp_server_address , ntp_dns_found , state );
142
- cyw43_arch_lwip_end ();
143
-
144
- state -> dns_request_sent = true;
145
- if (err == ERR_OK ) {
146
- ntp_request (state ); // Cached result
147
- } else if (err != ERR_INPROGRESS ) { // ERR_INPROGRESS means expect a callback
148
- printf ("dns request failed\n" );
149
- ntp_result (state , -1 , NULL );
150
- }
143
+ int key = getchar_timeout_us (0 );
144
+ if (key == 'q' || key == 'Q' ) {
145
+ break ;
151
146
}
152
147
#if PICO_CYW43_ARCH_POLL
153
148
// if you are using pico_cyw43_arch_poll, then you must poll periodically from your
154
149
// main loop (not from a timer interrupt) to check for Wi-Fi driver or lwIP work that needs to be done.
155
150
cyw43_arch_poll ();
156
151
// you can poll as often as you like, however if you have nothing else to do you can
157
152
// choose to sleep until either a specified time, or cyw43_arch_poll() has work to do:
158
- cyw43_arch_wait_for_work_until (state -> dns_request_sent ? at_the_end_of_time : state -> ntp_test_time );
153
+ cyw43_arch_wait_for_work_until (at_the_end_of_time );
159
154
#else
160
155
// if you are not using pico_cyw43_arch_poll, then WiFI driver and lwIP work
161
156
// is done via interrupt in the background. This sleep is just an example of some (blocking)
@@ -176,7 +171,7 @@ int main() {
176
171
177
172
cyw43_arch_enable_sta_mode ();
178
173
179
- if (cyw43_arch_wifi_connect_timeout_ms (WIFI_SSID , WIFI_PASSWORD , CYW43_AUTH_WPA2_AES_PSK , 10000 )) {
174
+ if (cyw43_arch_wifi_connect_timeout_ms (WIFI_SSID , WIFI_PASSWORD , CYW43_AUTH_WPA2_AES_PSK , 30000 )) {
180
175
printf ("failed to connect\n" );
181
176
return 1 ;
182
177
}
0 commit comments