void testEpochValidate (void) { struct timeval tv; unsigned long utt; hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = 0; BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); hBSP430uptimeTimer()->overflow_count += HALF_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeAsTimeval(utt, &tv)); BSP430_UNITTEST_ASSERT_TRUE(0 > iBSP430uptimeCheckEpochValidity()); hBSP430uptimeTimer()->overflow_count = 0; BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); hBSP430uptimeTimer()->overflow_count += HALF_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlx((time_t)-1, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_TRUE(0 > iBSP430uptimeCheckEpochValidity()); }
void testSetEpochFromTimeval (void) { unsigned long utt; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(0UL, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, utt)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec, xBSP430uptimeAsPOSIXTime(utt)); hBSP430uptimeTimer()->overflow_count = 10; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(655360UL, utt); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+20, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec-20, xBSP430uptimeAsPOSIXTime(0UL)); hBSP430uptimeTimer()->overflow_count = 0; }
void testEpochEra (void) { unsigned long utt; struct timeval tv; BSP430_UNITTEST_ASSERT_EQUAL_FMTlx(BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT, QUARTER_ERA + EIGHTH_ERA); /* Test boundaries and wrap into previous era */ hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = EIGHTH_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(EIGHTH_ERA, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+2*hBSP430uptimeTimer()->overflow_count, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(0)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(QUARTER_ERA)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeEpochEra(-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeEpochEra(-EIGHTH_ERA)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeEpochEra(-(QUARTER_ERA-1))); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(-QUARTER_ERA)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(0UL, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec, tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(-EIGHTH_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec - UTT_TO_S(EIGHTH_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); /* Test boundaries in current era */ hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = HALF_ERA >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(HALF_ERA, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+2*hBSP430uptimeTimer()->overflow_count, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(0)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt-BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt-(BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1))); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(-1)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(HALF_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(HALF_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(HALF_ERA + QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(HALF_ERA + QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); /* Test boundaries and wrap to next era */ hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = (HALF_ERA + QUARTER_ERA + EIGHTH_ERA) >> 16; utt = ulBSP430uptime(); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(HALF_ERA + QUARTER_ERA + EIGHTH_ERA, utt); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeCheckEpochValidity()); BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(basetv.tv_sec+2*hBSP430uptimeTimer()->overflow_count, xBSP430uptimeAsPOSIXTime(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt-BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt-(BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1))); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(utt)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(2, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(-1, iBSP430uptimeEpochEra(utt+BSP430_UPTIME_EPOCH_VALID_OFFSET_UTT)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(1, iBSP430uptimeEpochEra(-1)); BSP430_UNITTEST_ASSERT_EQUAL_FMTd(2, iBSP430uptimeEpochEra(0)); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(HALF_ERA + QUARTER_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(HALF_ERA + QUARTER_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(0L, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(FULL_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeAsTimeval(EIGHTH_ERA, &tv)); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_sec + UTT_TO_S(FULL_ERA + EIGHTH_ERA), tv.tv_sec); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(basetv.tv_usec, tv.tv_usec); }
void testInitialConditions (void) { BSP430_UNITTEST_ASSERT_EQUAL_FMTlu(0, ulBSP430uptime()); BSP430_UNITTEST_ASSERT_TRUE(0 > iBSP430uptimeCheckEpochValidity()); }
void testNTPSequence (void) { const uint8_t data0[] = { 0x24, 0x03, 0x03, 0xea, 0x00, 0x00, 0x11, 0x1d, 0x00, 0x00, 0x11, 0xcb, 0x32, 0x74, 0x26, 0x9d, 0xd6, 0xd1, 0xc5, 0x6c, 0x55, 0x49, 0x1f, 0x0a, 0xd6, 0x6d, 0xd9, 0x01, 0xbf, 0xf4, 0x00, 0x00, 0xd6, 0xd1, 0xc8, 0xda, 0xfc, 0x61, 0x70, 0x5f, 0xd6, 0xd1, 0xc8, 0xda, 0xfc, 0x65, 0x26, 0x4f, }; const uint64_t recv0_ntp = 15451244498192695296ULL; const int64_t adj0_ntp = 28129738957212503LL; const int32_t adj0_ms = 2147483647L; const uint32_t rtt0_us = 17643; /* recvfrom got 48 from 192.168.65.10:123 fam 2 Recv time 57918 is 15451244498192695296 rc 0 ; invalid epoch 1 t1=15451244498116673536 t2=15479374237111775327 t3=15479374237112018511 t4=15451244498192695296 Process got 0, adjustment 28129738957212503 ntp -2040469365 ms, rtt 17643 us */ const uint8_t data1[] = { 0x24, 0x03, 0x03, 0xea, 0x00, 0x00, 0x11, 0x1d, 0x00, 0x00, 0x12, 0x06, 0x32, 0x74, 0x26, 0x9d, 0xd6, 0xd1, 0xc5, 0x6c, 0x55, 0x49, 0x1f, 0x0a, 0xd6, 0xd1, 0xc9, 0x16, 0xfb, 0xe9, 0x4b, 0x57, 0xd6, 0xd1, 0xc9, 0x16, 0xfd, 0xf6, 0x2d, 0x28, 0xd6, 0xd1, 0xc9, 0x16, 0xfd, 0xf8, 0x75, 0x2b, }; const uint64_t recv1_ntp = 15479374494877961047ULL; const int64_t adj1_ntp = -3537453LL; const int32_t adj1_ms = -1; const uint32_t rtt1_us = 17665; /* recvfrom got 48 from 192.168.65.10:123 fam 2 Recv time 2024227 is 15479374494877961047 rc 0 ; invalid epoch 0 t1=15479374494801939287 t2=15479374494836337960 t3=15479374494836487467 t4=15479374494877961047 Process got 0, adjustment -3537453 ntp -1 ms, rtt 17665 us */ const sBSP430uptimeNTPPacketHeader * ph; int64_t adjustment_ntp; int32_t adjustment_ms; uint32_t rtt_us; hBSP430uptimeTimer()->hpl->r = 0; hBSP430uptimeTimer()->overflow_count = 0; BSP430_UNITTEST_ASSERT_TRUE(0 == iBSP430uptimeSetEpochFromTimeval(&basetv, 0UL)); BSP430_UNITTEST_ASSERT_EQUAL_FMTlx((time_t)-1, xBSP430uptimeAsPOSIXTime(HALF_ERA)); BSP430_UNITTEST_ASSERT_TRUE(0 > iBSP430uptimeCheckEpochValidity()); ph = (const sBSP430uptimeNTPPacketHeader *)data0; BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeProcessNTPResponse(NULL, ph, recv0_ntp, &adjustment_ntp, &adjustment_ms, &rtt_us)); BSP430_UNITTEST_ASSERT_EQUAL(adj0_ntp, adjustment_ntp); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(adj0_ms, adjustment_ms); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(rtt0_us, rtt_us); ph = (const sBSP430uptimeNTPPacketHeader *)data1; BSP430_UNITTEST_ASSERT_EQUAL_FMTd(0, iBSP430uptimeProcessNTPResponse(NULL, ph, recv1_ntp, &adjustment_ntp, &adjustment_ms, &rtt_us)); BSP430_UNITTEST_ASSERT_EQUAL(adj1_ntp, adjustment_ntp); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(adj1_ms, adjustment_ms); BSP430_UNITTEST_ASSERT_EQUAL_FMTld(rtt1_us, rtt_us); }
void main (void) { unsigned long wake_utt; int rc; long lrc; char as_text[BSP430_UPTIME_AS_TEXT_LENGTH]; uint32_u ntp_addr; uint32_u self_addr; vBSP430platformInitialize_ni(); (void)iBSP430consoleInitialize(); cprintf("\nntp " __DATE__ " " __TIME__ "\n"); /* Initialization can be done with interrupts disabled, since the * function does nothing but store callbacks. We use the same * callback for all three update capabilities. */ rc = iBSP430cc3000spiInitialize(wlan_cb, NULL, NULL, NULL); if (0 > rc) { cprintf("ERR: Initialization failed: %d\n", rc); return; } BSP430_CORE_ENABLE_INTERRUPT(); /* Local addresses use all zeros for inet addr. bind does not * support dynamic assignment of unused port through sin_port=0. */ memset(&local_addr, 0, sizeof(local_addr)); local_addr.sai.sin_family = AF_INET; local_addr.sai.sin_port = htons(60123); /* Remote server will be determined by DNS from the NTP pool once we * start. */ remote_addr = local_addr; remote_addr.sai.sin_port = htons(123); ntp_addr.u32 = 0; self_addr.u32 = 0; cprintf("Remote: %s:%u\n", net_ipv4AsText(&remote_addr.sai.sin_addr), ntohs(remote_addr.sai.sin_port)); rc = sizeof(sBSP430uptimeNTPPacketHeader); if (48 != rc) { cprintf("ERR: NTP header size %d\n", rc); return; } wake_utt = ulBSP430uptime(); (void)rc; while (1) { unsigned long timeout_utt; do { tNetappIpconfigRetArgs ipc; unsigned long start_utt; unsigned long finished_utt; int sfd; int nfds; fd_set rfds; int servers_left; int retries_left; /* Clear everything as we're starting a cycle */ BSP430_CORE_DISABLE_INTERRUPT(); do { event_flags_v = 0; start_utt = ulBSP430uptime_ni(); } while (0); BSP430_CORE_ENABLE_INTERRUPT(); /* Start the WAN process. This is asynchronous; wait up to 2 * seconds for it to complete. */ cprintf("%s: ", xBSP430uptimeAsText(start_utt, as_text)); cputchar('W'); wlan_start(0); vBSP430ledSet(BSP430_LED_RED, 1); (void)wlan_set_event_mask(0UL); lrc = BSP430_UPTIME_MS_TO_UTT(2000); timeout_utt = ulBSP430uptime() + lrc; while ((! (EVENT_FLAG_WLANCONN & event_flags_v)) && (0 < ((lrc = lBSP430uptimeSleepUntil(timeout_utt, LPM0_bits))))) { } if (! (EVENT_FLAG_WLANCONN & event_flags_v)) { cprintf("WLAN start failed\n"); break; } /* Wait for IP connectivity (signalled by a DHCP event). * Continue using the previous timeout. */ cputchar('D'); while ((! (EVENT_FLAG_IPCONN & event_flags_v)) && (0 < ((lrc = lBSP430uptimeSleepUntil(timeout_utt, LPM0_bits))))) { } if (! (EVENT_FLAG_IPCONN & event_flags_v)) { cprintf("IP conn failed\n"); break; } /* Inspect the IP configuration. Sometimes we get the event, * but there's no IP assigned. */ netapp_ipconfig(&ipc); memcpy(self_addr.u8, ipc.aucIP, sizeof(self_addr)); if (! self_addr.u32) { cprintf("IP assignment failed\n"); break; } vBSP430ledSet(BSP430_LED_GREEN, 1); /* Obtain a UDP socket and bind it for local operations. */ cputchar('I'); sfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP); if (0 > sfd) { cprintf("socket() failed: %d\n", sfd); break; } cputchar('S'); lrc = bind(sfd, &local_addr.sa, sizeof(local_addr.sa)); if (0 > lrc) { cprintf("bind() failed: %ld\n", lrc); break; } cputchar('B'); servers_left = NTP_SERVERS_PER_ATTEMPT; retries_left = NTP_REQUESTS_PER_SERVER; do { sBSP430uptimeNTPPacketHeader ntp0; sBSP430uptimeNTPPacketHeader ntp1; int have_invalid_epoch; struct timeval tv; sockaddr_u src; socklen_t slen = sizeof(src); unsigned long recv_utt; uint64_t recv_ntp; int64_t adjustment_ntp; long adjustment_ms; unsigned long rtt_us; have_invalid_epoch = 0 != iBSP430uptimeCheckEpochValidity(); if (! remote_addr.sai.sin_addr.s_addr) { const char ntp_fqdn[] = "0.pool.ntp.org"; ntp_addr.u32 = 0; rc = gethostbyname((char *)ntp_fqdn, sizeof(ntp_fqdn)-1, &ntp_addr.u32); cputchar('d'); if (-95 == rc) { /* ARP request failed; retry usually works */ rc = gethostbyname((char *)ntp_fqdn, sizeof(ntp_fqdn)-1, &ntp_addr.u32); cputchar('d'); } if (0 == ntp_addr.u32) { cprintf("gethostbyname(%s) failed: %d\n", ntp_fqdn, rc); rc = -1; break; } remote_addr.sai.sin_addr.s_addr = htonl(ntp_addr.u32); cprintf("{%s}", net_ipv4AsText(&remote_addr.sai.sin_addr)); retries_left = NTP_REQUESTS_PER_SERVER; } /* Configure the NTP request and send it */ iBSP430uptimeInitializeNTPRequest(&ntp0); iBSP430uptimeSetNTPXmtField(&ntp0, NULL); BSP430_CORE_DISABLE_INTERRUPT(); do { /* Clear the shutdown bit, so we know when it's ok to shut * down after this send */ event_flags_v &= ~EVENT_FLAG_SHUTDOWN; } while (0); BSP430_CORE_ENABLE_INTERRUPT(); rc = sendto(sfd, &ntp0, sizeof(ntp0), 0, &remote_addr.sa, sizeof(remote_addr.sai)); if (sizeof(ntp0) != rc) { cprintf("sendto %s:%u failed: %d\n", net_ipv4AsText(&remote_addr.sai.sin_addr), ntohs(remote_addr.sai.sin_port), rc); rc = -1; break; } cputchar('s'); /* If we get an answer it should be here in less than 100 * ms, but give it 400 ms just to be kind. */ tv.tv_sec = 0; tv.tv_usec = 400000UL; FD_ZERO(&rfds); FD_SET(sfd, &rfds); nfds = sfd+1; rc = select(nfds, &rfds, NULL, NULL, &tv); if (! FD_ISSET(sfd, &rfds)) { /* We didn't get an answer. If there are any retries left, use them. */ if (0 < retries_left--) { rc = 1; continue; } /* No retries left on this server: forget about it. If * there are any servers left, try another. */ cputchar('!'); remote_addr.sai.sin_addr.s_addr = 0; if (0 < servers_left--) { rc = 1; continue; } /* No retries from all available servers. Fail this attempt */ cprintf("no responsive NTP server found\n"); rc = -1; break; } /* Got a response. Record the time it came in and then read * it (no high-resolution packet RX time available, but we * believe it's here already so set the RX time first). The * message is unacceptable if it isn't an NTP packet. */ recv_utt = ulBSP430uptime(); rc = recvfrom(sfd, &ntp1, sizeof(ntp1), 0, &src.sa, &slen); if (sizeof(ntp1) != rc) { cprintf("recv failed: %d\n", rc); rc = -1; break; } cputchar('r'); /* Convert the RX time to NTP, then process the message to * determine the offset. */ rc = iBSP430uptimeAsNTP(recv_utt, &recv_ntp, have_invalid_epoch); if (0 != rc) { cprintf("NTP decode failed: %d\n", rc); continue; } rc = iBSP430uptimeProcessNTPResponse(&ntp0, &ntp1, recv_ntp, &adjustment_ntp, &adjustment_ms, &rtt_us); if (0 != rc) { cprintf("Process failed: %d\n", rc); continue; } if (have_invalid_epoch) { rc = iBSP430uptimeSetEpochFromNTP(BSP430_UPTIME_BYPASS_EPOCH_NTP + adjustment_ntp); cputchar('E'); if (0 != rc) { cprintf("\nERR: SetEpoch failed: %d\n", rc); } #if (NTP_ADJUST_EACH_ITER - 0) } else { rc = iBSP430uptimeAdjustEpochFromNTP(adjustment_ntp); cputchar('A'); if (0 != rc) { cprintf("\nERR: AdjustEpoch failed: %d\n", rc); } #endif } cprintf("[%s:%u adj %lld ntp = %ld ms, rtt %lu us]", net_ipv4AsText(&remote_addr.sai.sin_addr), ntohs(remote_addr.sai.sin_port), adjustment_ntp, adjustment_ms, rtt_us); } while (0 != rc); if (0 != rc) { cprintf("NTP query failed\n"); break; } #if 0 /* The shutdown OK seems to arrive about 1000 ms after the last * transmit, which is unnecessarily long. As we're not doing * TCP, there's no reason to wait for it. */ lrc = BSP430_UPTIME_MS_TO_UTT(4000); timeout_utt = ulBSP430uptime() + lrc; while ((! (EVENT_FLAG_SHUTDOWN & event_flags_v)) && (0 < ((lrc = lBSP430uptimeSleepUntil(timeout_utt, LPM0_bits))))) { } if (! (EVENT_FLAG_SHUTDOWN & event_flags_v)) { cprintf("SHUTDOWN ok never received\n"); break; } #endif finished_utt = ulBSP430uptime(); cprintf("[%s]\n", xBSP430uptimeAsText(finished_utt - start_utt, as_text)); } while (0); BSP430_CORE_DISABLE_INTERRUPT(); do { event_flags_v = 0; } while (0); BSP430_CORE_ENABLE_INTERRUPT(); wlan_stop(); vBSP430ledSet(BSP430_LED_GREEN, 0); vBSP430ledSet(BSP430_LED_RED, 0); wake_utt += 60 * ulBSP430uptimeConversionFrequency_Hz(); while (0 < lBSP430uptimeSleepUntil(wake_utt, LPM2_bits)) { } } cprintf("Fell off end\n"); }