mirror of
https://github.com/espressif/esp-idf.git
synced 2025-08-20 16:46:14 +00:00
sntp/lwip: Add some modes for time synchronization
Closes: IDF-236 Closes: https://github.com/espressif/esp-idf/pull/1668 Closes: https://github.com/espressif/esp-idf/pull/4103
This commit is contained in:

committed by
bot

parent
626684578a
commit
07a3eca372
@@ -1,5 +1,6 @@
|
||||
set(COMPONENT_ADD_INCLUDEDIRS
|
||||
include/apps
|
||||
include/apps/sntp
|
||||
lwip/src/include
|
||||
port/esp32/include
|
||||
port/esp32/include/arch
|
||||
@@ -9,6 +10,7 @@ set(COMPONENT_ADD_INCLUDEDIRS
|
||||
set(COMPONENT_SRCS "apps/dhcpserver/dhcpserver.c"
|
||||
"apps/ping/esp_ping.c"
|
||||
"apps/ping/ping.c"
|
||||
"apps/sntp/sntp.c"
|
||||
"lwip/src/api/api_lib.c"
|
||||
"lwip/src/api/api_msg.c"
|
||||
"lwip/src/api/err.c"
|
||||
|
93
components/lwip/apps/sntp/sntp.c
Normal file
93
components/lwip/apps/sntp/sntp.c
Normal file
@@ -0,0 +1,93 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/time.h>
|
||||
#include "esp_log.h"
|
||||
#include "sntp.h"
|
||||
|
||||
static const char *TAG = "sntp";
|
||||
|
||||
static volatile sntp_sync_mode_t sntp_sync_mode = SNTP_SYNC_MODE_IMMED;
|
||||
static volatile sntp_sync_status_t sntp_sync_status = SNTP_SYNC_STATUS_RESET;
|
||||
static sntp_sync_time_cb_t time_sync_notification_cb = NULL;
|
||||
|
||||
inline void sntp_set_sync_status(sntp_sync_status_t sync_status)
|
||||
{
|
||||
sntp_sync_status = sync_status;
|
||||
}
|
||||
|
||||
void __attribute__((weak)) sntp_sync_time(struct timeval *tv)
|
||||
{
|
||||
if (sntp_sync_mode == SNTP_SYNC_MODE_IMMED) {
|
||||
settimeofday(tv, NULL);
|
||||
sntp_set_sync_status(SNTP_SYNC_STATUS_COMPLETED);
|
||||
} else if (sntp_sync_mode == SNTP_SYNC_MODE_SMOOTH) {
|
||||
struct timeval tv_now;
|
||||
gettimeofday(&tv_now, NULL);
|
||||
int64_t cpu_time = (int64_t)tv_now.tv_sec * 1000000L + (int64_t)tv_now.tv_usec;
|
||||
int64_t sntp_time = (int64_t)tv->tv_sec * 1000000L + (int64_t)tv->tv_usec;
|
||||
int64_t delta = sntp_time - cpu_time;
|
||||
struct timeval tv_delta = { .tv_sec = delta / 1000000L, .tv_usec = delta % 1000000L };
|
||||
if (adjtime(&tv_delta, NULL) == -1) {
|
||||
ESP_LOGD(TAG, "Function adjtime don't update time because the error is very big");
|
||||
settimeofday(tv, NULL);
|
||||
ESP_LOGD(TAG, "Time was synchronized through settimeofday");
|
||||
sntp_set_sync_status(SNTP_SYNC_STATUS_COMPLETED);
|
||||
} else {
|
||||
sntp_set_sync_status(SNTP_SYNC_STATUS_IN_PROGRESS);
|
||||
}
|
||||
}
|
||||
if (time_sync_notification_cb) {
|
||||
time_sync_notification_cb(tv);
|
||||
}
|
||||
}
|
||||
|
||||
void sntp_set_sync_mode(sntp_sync_mode_t sync_mode)
|
||||
{
|
||||
sntp_sync_mode = sync_mode;
|
||||
}
|
||||
|
||||
sntp_sync_mode_t sntp_get_sync_mode(void)
|
||||
{
|
||||
return sntp_sync_mode;
|
||||
}
|
||||
|
||||
// set a callback function for time synchronization notification
|
||||
void sntp_set_time_sync_notification_cb(sntp_sync_time_cb_t callback)
|
||||
{
|
||||
time_sync_notification_cb = callback;
|
||||
}
|
||||
|
||||
sntp_sync_status_t sntp_get_sync_status(void)
|
||||
{
|
||||
sntp_sync_status_t ret_sync_status = SNTP_SYNC_STATUS_RESET;
|
||||
sntp_sync_status_t sync_status = sntp_sync_status;
|
||||
if (sync_status == SNTP_SYNC_STATUS_COMPLETED) {
|
||||
sntp_set_sync_status(SNTP_SYNC_STATUS_RESET);
|
||||
ret_sync_status = SNTP_SYNC_STATUS_COMPLETED;
|
||||
} else if (sync_status == SNTP_SYNC_STATUS_IN_PROGRESS) {
|
||||
struct timeval outdelta;
|
||||
adjtime(NULL, &outdelta);
|
||||
if (outdelta.tv_sec == 0 && outdelta.tv_usec == 0) {
|
||||
sntp_set_sync_status(SNTP_SYNC_STATUS_RESET);
|
||||
ret_sync_status = SNTP_SYNC_STATUS_COMPLETED;
|
||||
} else {
|
||||
ret_sync_status = SNTP_SYNC_STATUS_IN_PROGRESS;
|
||||
}
|
||||
}
|
||||
return ret_sync_status;
|
||||
}
|
@@ -5,6 +5,7 @@ COMPONENT_SUBMODULES += lwip
|
||||
|
||||
COMPONENT_ADD_INCLUDEDIRS := \
|
||||
include/apps \
|
||||
include/apps/sntp \
|
||||
lwip/src/include \
|
||||
port/esp32/include \
|
||||
port/esp32/include/arch \
|
||||
@@ -13,6 +14,7 @@ COMPONENT_ADD_INCLUDEDIRS := \
|
||||
COMPONENT_SRCDIRS := \
|
||||
apps/dhcpserver \
|
||||
apps/ping \
|
||||
apps/sntp \
|
||||
lwip/src/api \
|
||||
lwip/src/apps/sntp \
|
||||
lwip/src/core \
|
||||
|
22
components/lwip/include/apps/esp_sntp.h
Normal file
22
components/lwip/include/apps/esp_sntp.h
Normal file
@@ -0,0 +1,22 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __ESP_SNTP_H__
|
||||
#define __ESP_SNTP_H__
|
||||
|
||||
#include "lwip/err.h"
|
||||
#include "lwip/apps/sntp.h"
|
||||
#include "sntp.h"
|
||||
|
||||
#endif // __ESP_SNTP_H__
|
119
components/lwip/include/apps/sntp/sntp.h
Normal file
119
components/lwip/include/apps/sntp/sntp.h
Normal file
@@ -0,0 +1,119 @@
|
||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
#ifndef __SNTP_H__
|
||||
#define __SNTP_H__
|
||||
|
||||
/*
|
||||
* The time update takes place in the sntp_sync_time() function.
|
||||
* The user has the ability to redefine this function in order
|
||||
* to re-define its functionality. This function has two time update modes,
|
||||
* which can be set via the sntp_set_sync_mode() function.
|
||||
* Two modes are available:
|
||||
* - the first is an immediate update when receiving time from the sntp server,
|
||||
* - the second is a smooth time update (if the time error is no more than 35 minutes,
|
||||
* and an immediate update if the error is more than 35 minutes).
|
||||
*
|
||||
* To receive notification of time synchronization,
|
||||
* you can use the callback function or get the synchronization status
|
||||
* via the sntp_get_sync_status() function.
|
||||
*
|
||||
* To determine the time synchronization time on the device, you can use:
|
||||
* 1) sntp_set_time_sync_notification_cb() function to set the callback function,
|
||||
* which is convenient to use to receive notification of the update time.
|
||||
* 2) sntp_get_sync_status() function for getting time synchronization status.
|
||||
* After the time synchronization is completed, the status will be
|
||||
* SNTP_SYNC_STATUS_COMPLETED, after, it will be reseted to SNTP_SYNC_STATUS_RESET
|
||||
* to wait for the next sync cycle.
|
||||
*/
|
||||
|
||||
/// SNTP time update mode
|
||||
typedef enum {
|
||||
SNTP_SYNC_MODE_IMMED, /*!< Update system time immediately when receiving a response from the SNTP server. */
|
||||
SNTP_SYNC_MODE_SMOOTH, /*!< Smooth time updating. Time error is gradually reduced using adjtime function. If the difference between SNTP response time and system time is large (more than 35 minutes) then update immediately. */
|
||||
} sntp_sync_mode_t;
|
||||
|
||||
/// SNTP sync status
|
||||
typedef enum {
|
||||
SNTP_SYNC_STATUS_RESET, // Reset status.
|
||||
SNTP_SYNC_STATUS_COMPLETED, // Time is synchronized.
|
||||
SNTP_SYNC_STATUS_IN_PROGRESS, // Smooth time sync in progress.
|
||||
} sntp_sync_status_t;
|
||||
|
||||
/**
|
||||
* @brief SNTP callback function for notifying about time sync event
|
||||
*
|
||||
* @param tv Time received from SNTP server.
|
||||
*/
|
||||
typedef void (*sntp_sync_time_cb_t) (struct timeval *tv);
|
||||
|
||||
/**
|
||||
* @brief This function updates the system time.
|
||||
*
|
||||
* This is a weak-linked function. It is possible to replace all SNTP update functionality
|
||||
* by placing a sntp_sync_time() function in the app firmware source.
|
||||
* If the default implementation is used, calling sntp_set_sync_mode() allows
|
||||
* the time synchronization mode to be changed to instant or smooth.
|
||||
* If a callback function is registered via sntp_set_time_sync_notification_cb(),
|
||||
* it will be called following time synchronization.
|
||||
*
|
||||
* @param tv Time received from SNTP server.
|
||||
*/
|
||||
void sntp_sync_time(struct timeval *tv);
|
||||
|
||||
/**
|
||||
* @brief Set the sync mode
|
||||
*
|
||||
* Allowable two mode: SNTP_SYNC_MODE_IMMED and SNTP_SYNC_MODE_SMOOTH.
|
||||
* @param sync_mode Sync mode.
|
||||
*/
|
||||
void sntp_set_sync_mode(sntp_sync_mode_t sync_mode);
|
||||
|
||||
/**
|
||||
* @brief Get set sync mode
|
||||
*
|
||||
* @return SNTP_SYNC_MODE_IMMED: Update time immediately.
|
||||
* SNTP_SYNC_MODE_SMOOTH: Smooth time updating.
|
||||
*/
|
||||
sntp_sync_mode_t sntp_get_sync_mode(void);
|
||||
|
||||
/**
|
||||
* @brief Get status of time sync
|
||||
*
|
||||
* After the update is completed, the status will be returned as SNTP_SYNC_STATUS_COMPLETED.
|
||||
* After that, the status will be reset to SNTP_SYNC_STATUS_RESET.
|
||||
* If the update operation is not completed yet, the status will be SNTP_SYNC_STATUS_RESET.
|
||||
* If a smooth mode was chosen and the synchronization is still continuing (adjtime works), then it will be SNTP_SYNC_STATUS_IN_PROGRESS.
|
||||
*
|
||||
* @return SNTP_SYNC_STATUS_RESET: Reset status.
|
||||
* SNTP_SYNC_STATUS_COMPLETED: Time is synchronized.
|
||||
* SNTP_SYNC_STATUS_IN_PROGRESS: Smooth time sync in progress.
|
||||
*/
|
||||
sntp_sync_status_t sntp_get_sync_status(void);
|
||||
|
||||
/**
|
||||
* @brief Set status of time sync
|
||||
*
|
||||
* @param sync_status status of time sync (see sntp_sync_status_t)
|
||||
*/
|
||||
void sntp_set_sync_status(sntp_sync_status_t sync_status);
|
||||
|
||||
/**
|
||||
* @brief Set a callback function for time synchronization notification
|
||||
*
|
||||
* @param callback a callback function
|
||||
*/
|
||||
void sntp_set_time_sync_notification_cb(sntp_sync_time_cb_t callback);
|
||||
|
||||
#endif // __SNTP_H__
|
@@ -1,3 +1,3 @@
|
||||
#pragma once
|
||||
#warning "This header file is deprecated, please include lwip/apps/sntp.h instead."
|
||||
#include "lwip/apps/sntp.h"
|
||||
#warning "This header file is deprecated, please include esp_sntp.h instead."
|
||||
#include "esp_sntp.h"
|
||||
|
@@ -43,7 +43,7 @@
|
||||
#include "esp_task.h"
|
||||
#include "esp_system.h"
|
||||
#include "sdkconfig.h"
|
||||
|
||||
#include "sntp.h"
|
||||
#include "netif/dhcp_state.h"
|
||||
|
||||
/* Enable all Espressif-only options */
|
||||
@@ -836,7 +836,7 @@ enum {
|
||||
#define SNTP_SET_SYSTEM_TIME_US(sec, us) \
|
||||
do { \
|
||||
struct timeval tv = { .tv_sec = sec, .tv_usec = us }; \
|
||||
settimeofday(&tv, NULL); \
|
||||
sntp_sync_time(&tv); \
|
||||
} while (0);
|
||||
|
||||
#define SNTP_GET_SYSTEM_TIME(sec, us) \
|
||||
@@ -845,6 +845,7 @@ enum {
|
||||
gettimeofday(&tv, NULL); \
|
||||
(sec) = tv.tv_sec; \
|
||||
(us) = tv.tv_usec; \
|
||||
sntp_set_sync_status(SNTP_SYNC_STATUS_RESET); \
|
||||
} while (0);
|
||||
|
||||
#define SOC_SEND_LOG //printf
|
||||
|
Reference in New Issue
Block a user