Skip to content

Commit

Permalink
sntp: use one time source and fix unsynchronized sntp time stamp (#7595)
Browse files Browse the repository at this point in the history
* sntp: use one time source and fix unsynchronized sntp time stamp
* show subsecond synchro between time() and gettimeofday()
  • Loading branch information
d-a-v committed Sep 12, 2020
1 parent 8418aaf commit 40eb574
Show file tree
Hide file tree
Showing 6 changed files with 72 additions and 121 deletions.
3 changes: 0 additions & 3 deletions cores/esp8266/coredecls.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,6 @@ extern "C" {
#include <stdint.h>
#include <cont.h> // g_pcont declaration

extern bool timeshift64_is_set;
extern uint32_t sntp_real_timestamp;

bool can_yield();
void esp_yield();
void esp_schedule();
Expand Down
93 changes: 0 additions & 93 deletions cores/esp8266/sntp-lwip2.cpp

This file was deleted.

6 changes: 0 additions & 6 deletions cores/esp8266/sntp-lwip2.h

This file was deleted.

71 changes: 53 additions & 18 deletions cores/esp8266/time.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,18 +14,23 @@
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
*
* reworked for newlib and lwIP-v2:
* time source is SNTP/settimeofday()
* system time is micros64() / NONOS-SDK's system_get_time()
* synchronisation of the two through timeshift64
*/

#include <stdlib.h>
#include <../include/time.h> // See issue #6714
#include <sys/time.h>
#include <sys/reent.h>
#include "sntp.h"
#include "coredecls.h"
#include <errno.h>

#include <Arduino.h> // configTime()
#include <sntp.h> // nonos-sdk
#include <coredecls.h>
#include <Schedule.h>

#include "sntp-lwip2.h"
#include <Arduino.h> // configTime()

extern "C" {

Expand All @@ -42,16 +47,11 @@ extern struct tm* sntp_localtime(const time_t *clock);
extern uint64_t micros64();
extern void sntp_set_daylight(int daylight);

// time gap in seconds from 01.01.1900 (NTP time) to 01.01.1970 (UNIX time)
#define DIFF1900TO1970 2208988800UL

bool timeshift64_is_set = false;
static uint64_t timeshift64 = 0;

void tune_timeshift64 (uint64_t now_us)
{
timeshift64 = now_us - micros64();
timeshift64_is_set = true;
}

static void setServer(int id, const char* name_or_ip)
Expand All @@ -73,7 +73,8 @@ int clock_gettime(clockid_t unused, struct timespec *tp)
return 0;
}

// backport Espressif api
///////////////////////////////////////////
// backport legacy nonos-sdk Espressif api

bool sntp_set_timezone_in_seconds (int32_t timezone_sec)
{
Expand All @@ -93,16 +94,20 @@ char* sntp_get_real_time(time_t t)

uint32 sntp_get_current_timestamp()
{
return sntp_real_timestamp;
return time(nullptr);
}

// backport legacy nonos-sdk Espressif api
///////////////////////////////////////////

time_t time(time_t * t)
{
time_t currentTime_s = (micros64() + timeshift64) / 1000000ULL;
if (t)
{
*t = sntp_real_timestamp;
*t = currentTime_s;
}
return sntp_real_timestamp;
return currentTime_s;
}

int _gettimeofday_r(struct _reent* unused, struct timeval *tp, void *tzp)
Expand All @@ -111,8 +116,6 @@ int _gettimeofday_r(struct _reent* unused, struct timeval *tp, void *tzp)
(void) tzp;
if (tp)
{
if (!timeshift64_is_set)
tune_timeshift64(sntp_real_timestamp * 1000000ULL);
uint64_t currentTime_us = timeshift64 + micros64();
tp->tv_sec = currentTime_us / 1000000ULL;
tp->tv_usec = currentTime_us % 1000000ULL;
Expand Down Expand Up @@ -146,7 +149,7 @@ void configTime(int timezone_sec, int daylightOffset_sec, const char* server1, c
newlib inspection and internal structure hacking
(no sprintf, no sscanf, -7584 flash bytes):
***/
*** hack starts here: ***/

static char gmt[] = "GMT";

Expand All @@ -169,12 +172,12 @@ void configTime(int timezone_sec, int daylightOffset_sec, const char* server1, c
tzr->offset = -_timezone;
}

/*** end of hack ***/

// sntp servers
setServer(0, server1);
setServer(1, server2);
setServer(2, server3);

/*** end of posix replacement ***/
}

void setTZ(const char* tz){
Expand All @@ -197,3 +200,35 @@ void configTime(const char* tz, const char* server1, const char* server2, const
sntp_init();
}

static TrivialCB _settimeofday_cb;

void settimeofday_cb (TrivialCB&& cb)
{
_settimeofday_cb = std::move(cb);
}

void settimeofday_cb (const TrivialCB& cb)
{
_settimeofday_cb = cb;
}

extern "C" {

#include <lwip/apps/sntp.h>

int settimeofday(const struct timeval* tv, const struct timezone* tz)
{
if (tz || !tv)
// tz is obsolete (cf. man settimeofday)
return EINVAL;

// reset time subsystem
tune_timeshift64(tv->tv_sec * 1000000ULL + tv->tv_usec);

if (_settimeofday_cb)
schedule_recurrent_function_us([](){ _settimeofday_cb(); return false; }, 0);

return 0;
}

};
18 changes: 18 additions & 0 deletions libraries/esp8266/examples/NTP-TZ-DST/NTP-TZ-DST.ino
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,24 @@ void showTime() {
}

Serial.println();

// subsecond synchronisation
gettimeofday(&tv, nullptr);
time_t sec = tv.tv_sec;
do {
gettimeofday(&tv, nullptr);
Serial.printf("time(): %u gettimeofday(): %u.%06u",
(uint32_t)time(nullptr),
(uint32_t)tv.tv_sec, (uint32_t)tv.tv_usec);
if (tv.tv_sec == sec) {
Serial.println(" second unchanged");
} else {
Serial.println(" <-- second changed");
}
delay(50);
} while (tv.tv_sec == sec);

Serial.println();
}

void time_is_set_scheduled() {
Expand Down
2 changes: 1 addition & 1 deletion tests/host/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ DEBUG += -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP
endif

FLAGS += $(DEBUG) -Wall $(OPTZ) -fno-common -g $(M32)
FLAGS += -fstack-check -fstack-protector-all
FLAGS += -fstack-protector-all
FLAGS += -DHTTPCLIENT_1_1_COMPATIBLE=0
FLAGS += -DLWIP_IPV6=0
FLAGS += -DHOST_MOCK=1
Expand Down

0 comments on commit 40eb574

Please sign in to comment.