mirror of
https://github.com/esp8266/Arduino.git
synced 2025-04-21 10:26:06 +03:00
sntp: use one time source and fix unsynchronized sntp time stamp (#7595)
* sntp: use one time source and fix unsynchronized sntp time stamp * show subsecond synchro between time() and gettimeofday()
This commit is contained in:
parent
8418aaf4ef
commit
40eb5747e4
@ -12,9 +12,6 @@ extern "C" {
|
|||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <cont.h> // g_pcont declaration
|
#include <cont.h> // g_pcont declaration
|
||||||
|
|
||||||
extern bool timeshift64_is_set;
|
|
||||||
extern uint32_t sntp_real_timestamp;
|
|
||||||
|
|
||||||
bool can_yield();
|
bool can_yield();
|
||||||
void esp_yield();
|
void esp_yield();
|
||||||
void esp_schedule();
|
void esp_schedule();
|
||||||
|
@ -1,93 +0,0 @@
|
|||||||
/*
|
|
||||||
* sntp-lwip2.c - ESP8266-specific functions for SNTP and lwIP-v2
|
|
||||||
* Copyright (c) 2015 Espressif (license is tools/sdk/lwip/src/core/sntp.c's)
|
|
||||||
* Redistribution and use in source and binary forms, with or without modification,
|
|
||||||
* are permitted provided that the following conditions are met:
|
|
||||||
*
|
|
||||||
* 1. Redistributions of source code must retain the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer.
|
|
||||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
|
||||||
* this list of conditions and the following disclaimer in the documentation
|
|
||||||
* and/or other materials provided with the distribution.
|
|
||||||
* 3. The name of the author may not be used to endorse or promote products
|
|
||||||
* derived from this software without specific prior written permission.
|
|
||||||
*
|
|
||||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
|
|
||||||
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
||||||
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT
|
|
||||||
* SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
|
|
||||||
* EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT
|
|
||||||
* OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
|
||||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
|
||||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
|
|
||||||
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY
|
|
||||||
* OF SUCH DAMAGE.
|
|
||||||
*
|
|
||||||
*
|
|
||||||
* History:
|
|
||||||
* This code is extracted from lwip1.4-espressif's sntp.c
|
|
||||||
* which is a patched version of the original lwip1's sntp.
|
|
||||||
* (check the mix-up in tools/sdk/lwip/src/core/sntp.c)
|
|
||||||
* It is moved here as-is and cleaned for maintainability and
|
|
||||||
* because it does not belong to lwip.
|
|
||||||
*
|
|
||||||
* TODOs:
|
|
||||||
* settimeofday(): handle tv->tv_usec
|
|
||||||
* sntp_mktm_r(): review, fix DST handling (this one is currently untouched from lwip-1.4)
|
|
||||||
* implement adjtime()
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <lwip/init.h>
|
|
||||||
#include <time.h>
|
|
||||||
#include <sys/time.h>
|
|
||||||
#include <errno.h>
|
|
||||||
#include <osapi.h>
|
|
||||||
#include <os_type.h>
|
|
||||||
#include "coredecls.h"
|
|
||||||
#include "Schedule.h"
|
|
||||||
|
|
||||||
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>
|
|
||||||
|
|
||||||
uint32_t sntp_real_timestamp = 0;
|
|
||||||
LOCAL os_timer_t sntp_timer;
|
|
||||||
|
|
||||||
void ICACHE_RAM_ATTR sntp_time_inc (void)
|
|
||||||
{
|
|
||||||
sntp_real_timestamp++;
|
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
|
|
||||||
sntp_real_timestamp = tv->tv_sec;
|
|
||||||
os_timer_disarm(&sntp_timer);
|
|
||||||
os_timer_setfn(&sntp_timer, (os_timer_func_t *)sntp_time_inc, NULL);
|
|
||||||
os_timer_arm(&sntp_timer, 1000, 1);
|
|
||||||
|
|
||||||
if (_settimeofday_cb)
|
|
||||||
schedule_recurrent_function_us([](){ _settimeofday_cb(); return false; }, 0);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
};
|
|
@ -1,6 +0,0 @@
|
|||||||
#ifndef __sntp_lwip2_h__
|
|
||||||
#define __sntp_lwip2_h__
|
|
||||||
|
|
||||||
#include <coredecls.h>
|
|
||||||
|
|
||||||
#endif
|
|
@ -14,19 +14,24 @@
|
|||||||
* License along with this library; if not, write to the Free Software
|
* License along with this library; if not, write to the Free Software
|
||||||
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
|
* 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 <stdlib.h>
|
||||||
#include <../include/time.h> // See issue #6714
|
#include <../include/time.h> // See issue #6714
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <sys/reent.h>
|
#include <sys/reent.h>
|
||||||
#include "sntp.h"
|
#include <errno.h>
|
||||||
#include "coredecls.h"
|
|
||||||
|
#include <sntp.h> // nonos-sdk
|
||||||
|
#include <coredecls.h>
|
||||||
|
#include <Schedule.h>
|
||||||
|
|
||||||
#include <Arduino.h> // configTime()
|
#include <Arduino.h> // configTime()
|
||||||
|
|
||||||
#include "sntp-lwip2.h"
|
|
||||||
|
|
||||||
extern "C" {
|
extern "C" {
|
||||||
|
|
||||||
#ifndef _TIMEVAL_DEFINED
|
#ifndef _TIMEVAL_DEFINED
|
||||||
@ -42,16 +47,11 @@ extern struct tm* sntp_localtime(const time_t *clock);
|
|||||||
extern uint64_t micros64();
|
extern uint64_t micros64();
|
||||||
extern void sntp_set_daylight(int daylight);
|
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;
|
static uint64_t timeshift64 = 0;
|
||||||
|
|
||||||
void tune_timeshift64 (uint64_t now_us)
|
void tune_timeshift64 (uint64_t now_us)
|
||||||
{
|
{
|
||||||
timeshift64 = now_us - micros64();
|
timeshift64 = now_us - micros64();
|
||||||
timeshift64_is_set = true;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static void setServer(int id, const char* name_or_ip)
|
static void setServer(int id, const char* name_or_ip)
|
||||||
@ -73,7 +73,8 @@ int clock_gettime(clockid_t unused, struct timespec *tp)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// backport Espressif api
|
///////////////////////////////////////////
|
||||||
|
// backport legacy nonos-sdk Espressif api
|
||||||
|
|
||||||
bool sntp_set_timezone_in_seconds (int32_t timezone_sec)
|
bool sntp_set_timezone_in_seconds (int32_t timezone_sec)
|
||||||
{
|
{
|
||||||
@ -93,16 +94,20 @@ char* sntp_get_real_time(time_t t)
|
|||||||
|
|
||||||
uint32 sntp_get_current_timestamp()
|
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 time(time_t * t)
|
||||||
{
|
{
|
||||||
|
time_t currentTime_s = (micros64() + timeshift64) / 1000000ULL;
|
||||||
if (t)
|
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)
|
int _gettimeofday_r(struct _reent* unused, struct timeval *tp, void *tzp)
|
||||||
@ -111,8 +116,6 @@ int _gettimeofday_r(struct _reent* unused, struct timeval *tp, void *tzp)
|
|||||||
(void) tzp;
|
(void) tzp;
|
||||||
if (tp)
|
if (tp)
|
||||||
{
|
{
|
||||||
if (!timeshift64_is_set)
|
|
||||||
tune_timeshift64(sntp_real_timestamp * 1000000ULL);
|
|
||||||
uint64_t currentTime_us = timeshift64 + micros64();
|
uint64_t currentTime_us = timeshift64 + micros64();
|
||||||
tp->tv_sec = currentTime_us / 1000000ULL;
|
tp->tv_sec = currentTime_us / 1000000ULL;
|
||||||
tp->tv_usec = currentTime_us % 1000000ULL;
|
tp->tv_usec = currentTime_us % 1000000ULL;
|
||||||
@ -146,7 +149,7 @@ void configTime(int timezone_sec, int daylightOffset_sec, const char* server1, c
|
|||||||
newlib inspection and internal structure hacking
|
newlib inspection and internal structure hacking
|
||||||
(no sprintf, no sscanf, -7584 flash bytes):
|
(no sprintf, no sscanf, -7584 flash bytes):
|
||||||
|
|
||||||
***/
|
*** hack starts here: ***/
|
||||||
|
|
||||||
static char gmt[] = "GMT";
|
static char gmt[] = "GMT";
|
||||||
|
|
||||||
@ -169,12 +172,12 @@ void configTime(int timezone_sec, int daylightOffset_sec, const char* server1, c
|
|||||||
tzr->offset = -_timezone;
|
tzr->offset = -_timezone;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*** end of hack ***/
|
||||||
|
|
||||||
// sntp servers
|
// sntp servers
|
||||||
setServer(0, server1);
|
setServer(0, server1);
|
||||||
setServer(1, server2);
|
setServer(1, server2);
|
||||||
setServer(2, server3);
|
setServer(2, server3);
|
||||||
|
|
||||||
/*** end of posix replacement ***/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void setTZ(const char* tz){
|
void setTZ(const char* tz){
|
||||||
@ -197,3 +200,35 @@ void configTime(const char* tz, const char* server1, const char* server2, const
|
|||||||
sntp_init();
|
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;
|
||||||
|
}
|
||||||
|
|
||||||
|
};
|
||||||
|
@ -158,6 +158,24 @@ void showTime() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
Serial.println();
|
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() {
|
void time_is_set_scheduled() {
|
||||||
|
@ -169,7 +169,7 @@ DEBUG += -DDEBUG_ESP_SSL -DDEBUG_ESP_TLS_MEM -DDEBUG_ESP_HTTP_CLIENT -DDEBUG_ESP
|
|||||||
endif
|
endif
|
||||||
|
|
||||||
FLAGS += $(DEBUG) -Wall $(OPTZ) -fno-common -g $(M32)
|
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 += -DHTTPCLIENT_1_1_COMPATIBLE=0
|
||||||
FLAGS += -DLWIP_IPV6=0
|
FLAGS += -DLWIP_IPV6=0
|
||||||
FLAGS += -DHOST_MOCK=1
|
FLAGS += -DHOST_MOCK=1
|
||||||
|
Loading…
x
Reference in New Issue
Block a user