mirror of
https://github.com/espressif/esp-idf.git
synced 2024-10-05 20:47:46 -04:00
esp_netif/lwip: Fix core-locking config
* Fix thread safety issues in non-core locking * Add option to verify thread safety issues in lwip (core-lock assertion) * Make esp_sntp.h thread safe API * Fix sntp examples * Fix openthread libs Closes https://github.com/espressif/esp-idf/issues/9908 Closes https://github.com/espressif/esp-idf/issues/10502 Closes https://github.com/espressif/esp-idf/issues/10466
This commit is contained in:
parent
9e24739228
commit
a71fa82177
@ -8,6 +8,7 @@ endif()
|
|||||||
|
|
||||||
set(srcs_lwip
|
set(srcs_lwip
|
||||||
"lwip/esp_netif_lwip.c"
|
"lwip/esp_netif_lwip.c"
|
||||||
|
"lwip/esp_netif_sntp.c"
|
||||||
"lwip/esp_netif_lwip_defaults.c"
|
"lwip/esp_netif_lwip_defaults.c"
|
||||||
"lwip/netif/wlanif.c"
|
"lwip/netif/wlanif.c"
|
||||||
"lwip/netif/ethernetif.c"
|
"lwip/netif/ethernetif.c"
|
||||||
@ -55,3 +56,4 @@ endif()
|
|||||||
|
|
||||||
|
|
||||||
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
target_compile_options(${COMPONENT_LIB} PRIVATE "-Wno-format")
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} PRIVATE ESP_NETIF_COMPONENT_BUILD)
|
||||||
|
@ -306,6 +306,34 @@ esp_err_t esp_netif_bridge_fdb_add(esp_netif_t *esp_netif_br, uint8_t *addr, uin
|
|||||||
esp_err_t esp_netif_bridge_fdb_remove(esp_netif_t *esp_netif_br, uint8_t *addr);
|
esp_err_t esp_netif_bridge_fdb_remove(esp_netif_t *esp_netif_br, uint8_t *addr);
|
||||||
#endif // CONFIG_ESP_NETIF_BRIDGE_EN
|
#endif // CONFIG_ESP_NETIF_BRIDGE_EN
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cause the TCP/IP stack to join a IPv6 multicast group
|
||||||
|
*
|
||||||
|
* @param[in] esp_netif Handle to esp-netif instance
|
||||||
|
* @param[in] addr The multicast group to join
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK
|
||||||
|
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
||||||
|
* - ESP_ERR_ESP_NETIF_MLD6_FAILED
|
||||||
|
* - ESP_ERR_NO_MEM
|
||||||
|
*/
|
||||||
|
esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Cause the TCP/IP stack to leave a IPv6 multicast group
|
||||||
|
*
|
||||||
|
* @param[in] esp_netif Handle to esp-netif instance
|
||||||
|
* @param[in] addr The multicast group to leave
|
||||||
|
*
|
||||||
|
* @return
|
||||||
|
* - ESP_OK
|
||||||
|
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
||||||
|
* - ESP_ERR_ESP_NETIF_MLD6_FAILED
|
||||||
|
* - ESP_ERR_NO_MEM
|
||||||
|
*/
|
||||||
|
esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
@ -940,6 +968,27 @@ void esp_netif_netstack_buf_ref(void *netstack_buf);
|
|||||||
*/
|
*/
|
||||||
void esp_netif_netstack_buf_free(void *netstack_buf);
|
void esp_netif_netstack_buf_free(void *netstack_buf);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup ESP_NETIF_TCPIP_EXEC
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief TCPIP thread safe callback used with esp_netif_tcpip_exec()
|
||||||
|
*/
|
||||||
|
typedef esp_err_t (*esp_netif_callback_fn)(void *ctx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Utility to execute the supplied callback in TCP/IP context
|
||||||
|
* @param fn Pointer to the callback
|
||||||
|
* @param ctx Parameter to the callback
|
||||||
|
* @return The error code (esp_err_t) returned by the callback
|
||||||
|
*/
|
||||||
|
esp_err_t esp_netif_tcpip_exec(esp_netif_callback_fn fn, void *ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @}
|
* @}
|
||||||
*/
|
*/
|
||||||
|
116
components/esp_netif/include/esp_netif_sntp.h
Normal file
116
components/esp_netif/include/esp_netif_sntp.h
Normal file
@ -0,0 +1,116 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "esp_err.h"
|
||||||
|
#include "esp_netif_types.h"
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @defgroup ESP_NETIF_SNTP_API ESP-NETIF SNTP API
|
||||||
|
* @brief SNTP API for underlying TCP/IP stack
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/** @addtogroup ESP_NETIF_SNTP_API
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Time sync notification function
|
||||||
|
*/
|
||||||
|
typedef void (*esp_sntp_time_cb_t)(struct timeval *tv);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Utility macro for providing multiple servers in parentheses
|
||||||
|
*/
|
||||||
|
#define ESP_SNTP_SERVER_LIST(...) { __VA_ARGS__ }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default configuration to init SNTP with multiple servers
|
||||||
|
* @param servers_in_list Number of servers in the list
|
||||||
|
* @param list_of_servers List of servers (use ESP_SNTP_SERVER_LIST(...))
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#define ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(servers_in_list, list_of_servers) { \
|
||||||
|
.smooth_sync = false, \
|
||||||
|
.server_from_dhcp = false, \
|
||||||
|
.wait_for_sync = true, \
|
||||||
|
.start = true, \
|
||||||
|
.sync_cb = NULL, \
|
||||||
|
.renew_servers_after_new_IP = false, \
|
||||||
|
.ip_event_to_renew = 0, \
|
||||||
|
.index_of_first_server = 0, \
|
||||||
|
.num_of_servers = (servers_in_list), \
|
||||||
|
.servers = list_of_servers, \
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Default configuration with a single server
|
||||||
|
*/
|
||||||
|
#define ESP_NETIF_SNTP_DEFAULT_CONFIG(server) \
|
||||||
|
ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(1, {server})
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief SNTP configuration struct
|
||||||
|
*/
|
||||||
|
typedef struct esp_sntp_config {
|
||||||
|
bool smooth_sync; ///< set to true if smooth sync required
|
||||||
|
bool server_from_dhcp; ///< set to true to request NTP server config from DHCP
|
||||||
|
bool wait_for_sync; ///< if true, we create a semaphore to signal time sync event
|
||||||
|
bool start; ///< set to true to automatically start the SNTP service
|
||||||
|
esp_sntp_time_cb_t sync_cb; ///< optionally sets callback function on time sync event
|
||||||
|
bool renew_servers_after_new_IP; ///< this is used to refresh server list if NTP provided by DHCP (which cleans other pre-configured servers)
|
||||||
|
ip_event_t ip_event_to_renew; ///< set the IP event id on which we refresh server list (if renew_servers_after_new_IP=true)
|
||||||
|
size_t index_of_first_server; ///< refresh server list after this server (if renew_servers_after_new_IP=true)
|
||||||
|
size_t num_of_servers; ///< number of preconfigured NTP servers
|
||||||
|
const char* servers[CONFIG_LWIP_SNTP_MAX_SERVERS]; ///< list of servers
|
||||||
|
} esp_sntp_config_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize SNTP with supplied config struct
|
||||||
|
* @param config Config struct
|
||||||
|
* @return ESP_OK on success
|
||||||
|
*/
|
||||||
|
esp_err_t esp_netif_sntp_init(const esp_sntp_config_t * config);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Start SNTP service
|
||||||
|
* if it wasn't started during init (config.start = false)
|
||||||
|
* or restart it if already started
|
||||||
|
* @return ESP_OK on success
|
||||||
|
*/
|
||||||
|
esp_err_t esp_netif_sntp_start(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Deinitialize esp_netif SNTP module
|
||||||
|
*/
|
||||||
|
void esp_netif_sntp_deinit(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Wait for time sync event
|
||||||
|
* @param tout Specified timeout in RTOS ticks
|
||||||
|
* @return ESP_TIMEOUT if sync event didn't came withing the timeout
|
||||||
|
* ESP_ERR_NOT_FINISHED if the sync event came, but we're in smooth update mode and still in progress (SNTP_SYNC_STATUS_IN_PROGRESS)
|
||||||
|
* ESP_OK if time sync'ed
|
||||||
|
*/
|
||||||
|
esp_err_t esp_netif_sntp_sync_wait(TickType_t tout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @}
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
@ -97,12 +97,8 @@ typedef enum esp_netif_action {
|
|||||||
//
|
//
|
||||||
// Internal variables for this module
|
// Internal variables for this module
|
||||||
//
|
//
|
||||||
extern sys_thread_t g_lwip_task;
|
|
||||||
|
|
||||||
static const char *TAG = "esp_netif_lwip";
|
static const char *TAG = "esp_netif_lwip";
|
||||||
|
|
||||||
static bool tcpip_initialized = false;
|
|
||||||
|
|
||||||
#if LWIP_ESP_NETIF_DATA
|
#if LWIP_ESP_NETIF_DATA
|
||||||
static u8_t lwip_netif_client_id = 0xff;
|
static u8_t lwip_netif_client_id = 0xff;
|
||||||
#endif
|
#endif
|
||||||
@ -131,17 +127,28 @@ static void netif_callback_fn(struct netif* netif, netif_nsc_reason_t reason, co
|
|||||||
#endif /* #if LWIP_IPV6 */
|
#endif /* #if LWIP_IPV6 */
|
||||||
}
|
}
|
||||||
|
|
||||||
static void set_lwip_netif_callback(void)
|
#if LWIP_ESP_NETIF_DATA
|
||||||
|
static esp_err_t alloc_client_data_id(esp_netif_api_msg_t *msg)
|
||||||
{
|
{
|
||||||
if (netif_callback.callback_fn == NULL ) {
|
uint8_t *client_data_id = msg->data;
|
||||||
netif_add_ext_callback(&netif_callback, netif_callback_fn);
|
*client_data_id = netif_alloc_client_data_id();
|
||||||
}
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
#endif // LWIP_ESP_NETIF_DATA
|
||||||
|
|
||||||
|
static esp_err_t set_lwip_netif_callback(struct esp_netif_api_msg_s *msg)
|
||||||
|
{
|
||||||
|
(void)msg;
|
||||||
|
netif_add_ext_callback(&netif_callback, netif_callback_fn);
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void remove_lwip_netif_callback(void)
|
static esp_err_t remove_lwip_netif_callback(struct esp_netif_api_msg_s *msg)
|
||||||
{
|
{
|
||||||
|
(void)msg;
|
||||||
netif_remove_ext_callback(&netif_callback);
|
netif_remove_ext_callback(&netif_callback);
|
||||||
memset(&netif_callback, 0, sizeof(netif_callback));
|
memset(&netif_callback, 0, sizeof(netif_callback));
|
||||||
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void dns_clear_servers(bool keep_fallback)
|
static void dns_clear_servers(bool keep_fallback)
|
||||||
@ -181,6 +188,7 @@ static void netif_unset_garp_flag(struct netif *netif)
|
|||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
#if !LWIP_TCPIP_CORE_LOCKING
|
||||||
static sys_sem_t api_sync_sem = NULL;
|
static sys_sem_t api_sync_sem = NULL;
|
||||||
static sys_sem_t api_lock_sem = NULL;
|
static sys_sem_t api_lock_sem = NULL;
|
||||||
|
#endif
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Api callback from tcpip thread used to call esp-netif
|
* @brief Api callback from tcpip thread used to call esp-netif
|
||||||
@ -197,33 +205,59 @@ static void esp_netif_api_cb(void *api_msg)
|
|||||||
|
|
||||||
msg->ret = msg->api_fn(msg);
|
msg->ret = msg->api_fn(msg);
|
||||||
ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret);
|
ESP_LOGD(TAG, "call api in lwip: ret=0x%x, give sem", msg->ret);
|
||||||
|
#if !LWIP_TCPIP_CORE_LOCKING
|
||||||
sys_sem_signal(&api_sync_sem);
|
sys_sem_signal(&api_sync_sem);
|
||||||
|
|
||||||
}
|
|
||||||
#endif
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Initiates a tcpip remote call if called from another task
|
* @brief Initiates a tcpip remote call if called from another task
|
||||||
* or calls the function directly if executed from lwip task
|
* or calls the function directly if executed from lwip task
|
||||||
*/
|
*/
|
||||||
static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t *netif, void *data)
|
static inline esp_err_t esp_netif_lwip_ipc_call_msg(esp_netif_api_msg_t *msg)
|
||||||
|
{
|
||||||
|
if (!sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)) {
|
||||||
|
ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", msg->esp_netif, msg->api_fn);
|
||||||
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
|
tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, NULL);
|
||||||
|
#else
|
||||||
|
sys_arch_sem_wait(&api_lock_sem, 0);
|
||||||
|
tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, msg, &api_sync_sem);
|
||||||
|
sys_sem_signal(&api_lock_sem);
|
||||||
|
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||||
|
return msg->ret;
|
||||||
|
}
|
||||||
|
ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", msg->esp_netif, msg->api_fn);
|
||||||
|
return msg->api_fn(msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline esp_err_t esp_netif_lwip_ipc_call(esp_netif_api_fn fn, esp_netif_t* netif, void *data)
|
||||||
{
|
{
|
||||||
esp_netif_api_msg_t msg = {
|
esp_netif_api_msg_t msg = {
|
||||||
.esp_netif = netif,
|
.esp_netif = netif,
|
||||||
.data = data,
|
.data = data,
|
||||||
.api_fn = fn
|
.api_fn = fn
|
||||||
};
|
};
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
return esp_netif_lwip_ipc_call_msg(&msg);
|
||||||
if (tcpip_initialized && g_lwip_task != xTaskGetCurrentTaskHandle()) {
|
}
|
||||||
ESP_LOGD(TAG, "check: remote, if=%p fn=%p\n", netif, fn);
|
|
||||||
sys_arch_sem_wait(&api_lock_sem, 0);
|
static inline esp_err_t esp_netif_lwip_ipc_call_fn(esp_netif_api_fn fn, esp_netif_callback_fn user_fn, void *ctx)
|
||||||
tcpip_send_msg_wait_sem((tcpip_callback_fn)esp_netif_api_cb, &msg, &api_sync_sem);
|
{
|
||||||
sys_sem_signal(&api_lock_sem);
|
esp_netif_api_msg_t msg = {
|
||||||
return msg.ret;
|
.user_fn = user_fn,
|
||||||
}
|
.data = ctx,
|
||||||
#endif /* !LWIP_TCPIP_CORE_LOCKING */
|
.api_fn = fn
|
||||||
ESP_LOGD(TAG, "check: local, if=%p fn=%p\n", netif, fn);
|
};
|
||||||
return fn(&msg);
|
return esp_netif_lwip_ipc_call_msg(&msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline esp_err_t esp_netif_lwip_ipc_no_args(esp_netif_api_fn fn)
|
||||||
|
{
|
||||||
|
esp_netif_api_msg_t msg = {
|
||||||
|
.api_fn = fn
|
||||||
|
};
|
||||||
|
return esp_netif_lwip_ipc_call_msg(&msg);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -451,10 +485,15 @@ void* esp_netif_get_netif_impl(esp_netif_t *esp_netif)
|
|||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void tcpip_init_done(void *arg)
|
||||||
|
{
|
||||||
|
sys_sem_t *init_sem = arg;
|
||||||
|
sys_sem_signal(init_sem);
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_netif_init(void)
|
esp_err_t esp_netif_init(void)
|
||||||
{
|
{
|
||||||
if (tcpip_initialized == false) {
|
if (!sys_thread_tcpip(LWIP_CORE_IS_TCPIP_INITIALIZED)) {
|
||||||
tcpip_initialized = true;
|
|
||||||
#if CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
|
#if CONFIG_LWIP_HOOK_TCP_ISN_DEFAULT
|
||||||
uint8_t rand_buf[16];
|
uint8_t rand_buf[16];
|
||||||
/*
|
/*
|
||||||
@ -467,13 +506,21 @@ esp_err_t esp_netif_init(void)
|
|||||||
esp_fill_random(rand_buf, sizeof(rand_buf));
|
esp_fill_random(rand_buf, sizeof(rand_buf));
|
||||||
lwip_init_tcp_isn(esp_log_timestamp(), rand_buf);
|
lwip_init_tcp_isn(esp_log_timestamp(), rand_buf);
|
||||||
#endif
|
#endif
|
||||||
tcpip_init(NULL, NULL);
|
sys_sem_t init_sem;
|
||||||
ESP_LOGD(TAG, "LwIP stack has been initialized");
|
if (sys_sem_new(&init_sem, 0) != ERR_OK) {
|
||||||
#if LWIP_ESP_NETIF_DATA
|
ESP_LOGE(TAG, "esp netif cannot create tcpip_init semaphore");
|
||||||
if (lwip_netif_client_id == 0xFF) {
|
return ESP_FAIL;
|
||||||
lwip_netif_client_id = netif_alloc_client_data_id();
|
|
||||||
}
|
}
|
||||||
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
|
/* TCPIP thread is not initialized yet,
|
||||||
|
* pretend that the calling thread is holder
|
||||||
|
* to correctly set up the TCPIP task */
|
||||||
|
sys_thread_tcpip(LWIP_CORE_LOCK_MARK_HOLDER);
|
||||||
#endif
|
#endif
|
||||||
|
tcpip_init(tcpip_init_done, &init_sem);
|
||||||
|
sys_sem_wait(&init_sem);
|
||||||
|
sys_sem_free(&init_sem);
|
||||||
|
ESP_LOGD(TAG, "LwIP stack has been initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
#if !LWIP_TCPIP_CORE_LOCKING
|
#if !LWIP_TCPIP_CORE_LOCKING
|
||||||
@ -492,18 +539,22 @@ esp_err_t esp_netif_init(void)
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#if LWIP_ESP_NETIF_DATA
|
||||||
|
if (lwip_netif_client_id == 0xFF) {
|
||||||
|
esp_netif_lwip_ipc_call(alloc_client_data_id, NULL, &lwip_netif_client_id);
|
||||||
|
}
|
||||||
|
#endif
|
||||||
ESP_LOGD(TAG, "esp-netif has been successfully initialized");
|
ESP_LOGD(TAG, "esp-netif has been successfully initialized");
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_netif_deinit(void)
|
esp_err_t esp_netif_deinit(void)
|
||||||
{
|
{
|
||||||
if (tcpip_initialized == true) {
|
if (sys_thread_tcpip(LWIP_CORE_IS_TCPIP_INITIALIZED)) {
|
||||||
/* deinit of LwIP not supported:
|
/* deinit of LwIP not supported:
|
||||||
* do not deinit semaphores and states,
|
* do not deinit semaphores and states,
|
||||||
* so init could be called multiple times
|
* so init could be called multiple times
|
||||||
*
|
*
|
||||||
tcpip_initialized = false;
|
|
||||||
sys_sem_free(&api_sync_sem);
|
sys_sem_free(&api_sync_sem);
|
||||||
sys_sem_free(&api_lock_sem);
|
sys_sem_free(&api_lock_sem);
|
||||||
*/
|
*/
|
||||||
@ -605,6 +656,16 @@ static esp_err_t esp_netif_init_configuration(esp_netif_t *esp_netif, const esp_
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static esp_err_t tcpip_exec_api(esp_netif_api_msg_t *msg)
|
||||||
|
{
|
||||||
|
return msg->user_fn(msg->data);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_tcpip_exec(esp_netif_callback_fn fn, void*ctx)
|
||||||
|
{
|
||||||
|
return esp_netif_lwip_ipc_call_fn(tcpip_exec_api, fn, ctx);
|
||||||
|
}
|
||||||
|
|
||||||
esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
|
esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
|
||||||
{
|
{
|
||||||
// mandatory configuration must be provided when creating esp_netif object
|
// mandatory configuration must be provided when creating esp_netif object
|
||||||
@ -650,7 +711,7 @@ esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
|
|||||||
// Optionally allocate netif client data for esp-netif ptr
|
// Optionally allocate netif client data for esp-netif ptr
|
||||||
// to allow for running esp_netif_new() before esp_netif_init()
|
// to allow for running esp_netif_new() before esp_netif_init()
|
||||||
if (lwip_netif_client_id == 0xFF) {
|
if (lwip_netif_client_id == 0xFF) {
|
||||||
lwip_netif_client_id = netif_alloc_client_data_id();
|
esp_netif_lwip_ipc_call(alloc_client_data_id, NULL, &lwip_netif_client_id);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -689,7 +750,9 @@ esp_netif_t *esp_netif_new(const esp_netif_config_t *esp_netif_config)
|
|||||||
}
|
}
|
||||||
lwip_set_esp_netif(lwip_netif, esp_netif);
|
lwip_set_esp_netif(lwip_netif, esp_netif);
|
||||||
|
|
||||||
set_lwip_netif_callback();
|
if (netif_callback.callback_fn == NULL ) {
|
||||||
|
esp_netif_lwip_ipc_no_args(set_lwip_netif_callback);
|
||||||
|
}
|
||||||
|
|
||||||
return esp_netif;
|
return esp_netif;
|
||||||
}
|
}
|
||||||
@ -771,18 +834,24 @@ static void esp_netif_destroy_related(esp_netif_t *esp_netif)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static esp_err_t esp_netif_lwip_remove_api(esp_netif_api_msg_t *msg)
|
||||||
|
{
|
||||||
|
esp_netif_lwip_remove(msg->esp_netif);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
void esp_netif_destroy(esp_netif_t *esp_netif)
|
void esp_netif_destroy(esp_netif_t *esp_netif)
|
||||||
{
|
{
|
||||||
if (esp_netif) {
|
if (esp_netif) {
|
||||||
esp_netif_remove_from_list(esp_netif);
|
esp_netif_remove_from_list(esp_netif);
|
||||||
if (esp_netif_get_nr_of_ifs() == 0) {
|
if (esp_netif_get_nr_of_ifs() == 0) {
|
||||||
remove_lwip_netif_callback();
|
esp_netif_lwip_ipc_no_args(remove_lwip_netif_callback);
|
||||||
}
|
}
|
||||||
free(esp_netif->ip_info);
|
free(esp_netif->ip_info);
|
||||||
free(esp_netif->ip_info_old);
|
free(esp_netif->ip_info_old);
|
||||||
free(esp_netif->if_key);
|
free(esp_netif->if_key);
|
||||||
free(esp_netif->if_desc);
|
free(esp_netif->if_desc);
|
||||||
esp_netif_lwip_remove(esp_netif);
|
esp_netif_lwip_ipc_call(esp_netif_lwip_remove_api, esp_netif, NULL);
|
||||||
esp_netif_destroy_related(esp_netif);
|
esp_netif_destroy_related(esp_netif);
|
||||||
free(esp_netif->lwip_netif);
|
free(esp_netif->lwip_netif);
|
||||||
free(esp_netif->hostname);
|
free(esp_netif->hostname);
|
||||||
@ -830,6 +899,15 @@ static esp_err_t esp_netif_reset_ip_info(esp_netif_t *esp_netif)
|
|||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_set_mac_api(esp_netif_api_msg_t *msg)
|
||||||
|
{
|
||||||
|
uint8_t *mac = msg->data;
|
||||||
|
esp_netif_t* esp_netif = msg->esp_netif;
|
||||||
|
memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN);
|
||||||
|
memcpy(esp_netif->lwip_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
|
esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
|
||||||
{
|
{
|
||||||
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
|
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
|
||||||
@ -838,9 +916,7 @@ esp_err_t esp_netif_set_mac(esp_netif_t *esp_netif, uint8_t mac[])
|
|||||||
if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
|
if (_IS_NETIF_ANY_POINT2POINT_TYPE(esp_netif)) {
|
||||||
return ESP_ERR_NOT_SUPPORTED;
|
return ESP_ERR_NOT_SUPPORTED;
|
||||||
}
|
}
|
||||||
memcpy(esp_netif->mac, mac, NETIF_MAX_HWADDR_LEN);
|
return esp_netif_lwip_ipc_call(esp_netif_set_mac_api, esp_netif, mac);
|
||||||
memcpy(esp_netif->lwip_netif->hwaddr, mac, NETIF_MAX_HWADDR_LEN);
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[])
|
esp_err_t esp_netif_get_mac(esp_netif_t *esp_netif, uint8_t mac[])
|
||||||
@ -1952,70 +2028,75 @@ int32_t esp_netif_get_event_id(esp_netif_t *esp_netif, esp_netif_ip_event_type_t
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct dhcp_params {
|
||||||
|
esp_netif_dhcp_option_mode_t op;
|
||||||
|
esp_netif_dhcp_option_id_t id;
|
||||||
|
void *val;
|
||||||
|
uint32_t len;
|
||||||
|
};
|
||||||
|
|
||||||
#if ESP_DHCPS
|
#if ESP_DHCPS
|
||||||
esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
|
esp_err_t esp_netif_dhcps_option_api(esp_netif_api_msg_t *msg)
|
||||||
uint32_t opt_len)
|
|
||||||
{
|
{
|
||||||
if (esp_netif == NULL || esp_netif->dhcps == NULL) {
|
esp_netif_t *esp_netif = msg->esp_netif;
|
||||||
return ESP_ERR_ESP_NETIF_IF_NOT_READY;
|
struct dhcp_params *opt = msg->data;
|
||||||
}
|
void *opt_info = dhcps_option_info(esp_netif->dhcps, opt->id, opt->len);
|
||||||
void *opt_info = dhcps_option_info(esp_netif->dhcps, opt_id, opt_len);
|
|
||||||
|
|
||||||
esp_netif_dhcp_status_t dhcps_status = esp_netif->dhcps_status;
|
esp_netif_dhcp_status_t dhcps_status = esp_netif->dhcps_status;
|
||||||
if (opt_info == NULL || opt_val == NULL) {
|
if (opt_info == NULL || opt->val == NULL) {
|
||||||
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (opt_op == ESP_NETIF_OP_GET) {
|
if (opt->op == ESP_NETIF_OP_GET) {
|
||||||
if (dhcps_status == ESP_NETIF_DHCP_STOPPED) {
|
if (dhcps_status == ESP_NETIF_DHCP_STOPPED) {
|
||||||
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
|
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opt_id) {
|
switch (opt->id) {
|
||||||
case IP_ADDRESS_LEASE_TIME: {
|
case IP_ADDRESS_LEASE_TIME: {
|
||||||
*(uint32_t *)opt_val = *(uint32_t *)opt_info;
|
*(uint32_t *)opt->val = *(uint32_t *)opt_info;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_NETIF_SUBNET_MASK:
|
case ESP_NETIF_SUBNET_MASK:
|
||||||
case REQUESTED_IP_ADDRESS: {
|
case REQUESTED_IP_ADDRESS: {
|
||||||
memcpy(opt_val, opt_info, opt_len);
|
memcpy(opt->val, opt_info, opt->len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ROUTER_SOLICITATION_ADDRESS: {
|
case ROUTER_SOLICITATION_ADDRESS: {
|
||||||
if ((*(uint8_t *)opt_info) & OFFER_ROUTER) {
|
if ((*(uint8_t *)opt_info) & OFFER_ROUTER) {
|
||||||
*(uint8_t *)opt_val = 1;
|
*(uint8_t *)opt->val = 1;
|
||||||
} else {
|
} else {
|
||||||
*(uint8_t *)opt_val = 0;
|
*(uint8_t *)opt->val = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DOMAIN_NAME_SERVER: {
|
case DOMAIN_NAME_SERVER: {
|
||||||
if ((*(uint8_t *)opt_info) & OFFER_DNS) {
|
if ((*(uint8_t *)opt_info) & OFFER_DNS) {
|
||||||
*(uint8_t *)opt_val = 1;
|
*(uint8_t *)opt->val = 1;
|
||||||
} else {
|
} else {
|
||||||
*(uint8_t *)opt_val = 0;
|
*(uint8_t *)opt->val = 0;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} else if (opt_op == ESP_NETIF_OP_SET) {
|
} else if (opt->op == ESP_NETIF_OP_SET) {
|
||||||
if (dhcps_status == ESP_NETIF_DHCP_STARTED) {
|
if (dhcps_status == ESP_NETIF_DHCP_STARTED) {
|
||||||
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
|
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (opt_id) {
|
switch (opt->id) {
|
||||||
case IP_ADDRESS_LEASE_TIME: {
|
case IP_ADDRESS_LEASE_TIME: {
|
||||||
if (*(uint32_t *)opt_val != 0) {
|
if (*(uint32_t *)opt->val != 0) {
|
||||||
*(uint32_t *)opt_info = *(uint32_t *)opt_val;
|
*(uint32_t *)opt_info = *(uint32_t *)opt->val;
|
||||||
} else {
|
} else {
|
||||||
*(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF;
|
*(uint32_t *)opt_info = DHCPS_LEASE_TIME_DEF;
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ESP_NETIF_SUBNET_MASK: {
|
case ESP_NETIF_SUBNET_MASK: {
|
||||||
memcpy(opt_info, opt_val, opt_len);
|
memcpy(opt_info, opt->val, opt->len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case REQUESTED_IP_ADDRESS: {
|
case REQUESTED_IP_ADDRESS: {
|
||||||
@ -2023,7 +2104,7 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
|
|||||||
uint32_t softap_ip = 0;
|
uint32_t softap_ip = 0;
|
||||||
uint32_t start_ip = 0;
|
uint32_t start_ip = 0;
|
||||||
uint32_t end_ip = 0;
|
uint32_t end_ip = 0;
|
||||||
dhcps_lease_t *poll = opt_val;
|
dhcps_lease_t *poll = opt->val;
|
||||||
|
|
||||||
if (poll->enable) {
|
if (poll->enable) {
|
||||||
memset(&info, 0x00, sizeof(esp_netif_ip_info_t));
|
memset(&info, 0x00, sizeof(esp_netif_ip_info_t));
|
||||||
@ -2050,11 +2131,11 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
memcpy(opt_info, opt_val, opt_len);
|
memcpy(opt_info, opt->val, opt->len);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case ROUTER_SOLICITATION_ADDRESS: {
|
case ROUTER_SOLICITATION_ADDRESS: {
|
||||||
if (*(uint8_t *)opt_val) {
|
if (*(uint8_t *)opt->val) {
|
||||||
*(uint8_t *)opt_info |= OFFER_ROUTER;
|
*(uint8_t *)opt_info |= OFFER_ROUTER;
|
||||||
} else {
|
} else {
|
||||||
*(uint8_t *)opt_info &= ((~OFFER_ROUTER) & 0xFF);
|
*(uint8_t *)opt_info &= ((~OFFER_ROUTER) & 0xFF);
|
||||||
@ -2062,7 +2143,7 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case DOMAIN_NAME_SERVER: {
|
case DOMAIN_NAME_SERVER: {
|
||||||
if (*(uint8_t *)opt_val) {
|
if (*(uint8_t *)opt->val) {
|
||||||
*(uint8_t *)opt_info |= OFFER_DNS;
|
*(uint8_t *)opt_info |= OFFER_DNS;
|
||||||
} else {
|
} else {
|
||||||
*(uint8_t *)opt_info &= ((~OFFER_DNS) & 0xFF);
|
*(uint8_t *)opt_info &= ((~OFFER_DNS) & 0xFF);
|
||||||
@ -2073,63 +2154,82 @@ esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_m
|
|||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
dhcps_set_option_info(esp_netif->dhcps, opt_id, opt_info, opt_len);
|
dhcps_set_option_info(esp_netif->dhcps, opt->id, opt_info, opt->len);
|
||||||
} else {
|
} else {
|
||||||
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
|
|
||||||
return ESP_OK;
|
return ESP_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_dhcps_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
|
||||||
|
uint32_t opt_len)
|
||||||
|
{
|
||||||
|
if (esp_netif == NULL || esp_netif->dhcps == NULL) {
|
||||||
|
return ESP_ERR_ESP_NETIF_IF_NOT_READY;
|
||||||
|
}
|
||||||
|
struct dhcp_params opts = { .op = opt_op, .id = opt_id, .len = opt_len, .val = opt_val };
|
||||||
|
return esp_netif_lwip_ipc_call(esp_netif_dhcps_option_api, esp_netif, &opts);
|
||||||
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
esp_err_t esp_netif_dhcpc_option_api(esp_netif_api_msg_t *msg)
|
||||||
|
{
|
||||||
|
esp_netif_t *esp_netif = msg->esp_netif;
|
||||||
|
struct dhcp_params *opt = msg->data;
|
||||||
|
|
||||||
|
struct dhcp *dhcp = netif_dhcp_data(esp_netif->lwip_netif);
|
||||||
|
if (dhcp == NULL || opt->val == NULL) {
|
||||||
|
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
||||||
|
}
|
||||||
|
if (opt->op == ESP_NETIF_OP_GET) {
|
||||||
|
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
|
||||||
|
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
|
||||||
|
}
|
||||||
|
switch (opt->id) {
|
||||||
|
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
|
||||||
|
if (opt->len == sizeof(dhcp->tries)) {
|
||||||
|
*(uint8_t *)opt->val = dhcp->tries;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
|
||||||
|
case ESP_NETIF_VENDOR_SPECIFIC_INFO:
|
||||||
|
return dhcp_get_vendor_specific_information(opt->len, opt->val);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
||||||
|
}
|
||||||
|
} else if (opt->op == ESP_NETIF_OP_SET) {
|
||||||
|
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
|
||||||
|
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
|
||||||
|
}
|
||||||
|
switch (opt->id) {
|
||||||
|
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
|
||||||
|
if (opt->len == sizeof(dhcp->tries)) {
|
||||||
|
dhcp->tries = *(uint8_t *)opt->val;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
|
||||||
|
case ESP_NETIF_VENDOR_CLASS_IDENTIFIER:
|
||||||
|
return dhcp_set_vendor_class_identifier(opt->len, opt->val);
|
||||||
|
#endif
|
||||||
|
default:
|
||||||
|
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_netif_dhcpc_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
|
esp_err_t esp_netif_dhcpc_option(esp_netif_t *esp_netif, esp_netif_dhcp_option_mode_t opt_op, esp_netif_dhcp_option_id_t opt_id, void *opt_val,
|
||||||
uint32_t opt_len)
|
uint32_t opt_len)
|
||||||
{
|
{
|
||||||
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
|
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
|
||||||
return ESP_ERR_ESP_NETIF_IF_NOT_READY;
|
return ESP_ERR_ESP_NETIF_IF_NOT_READY;
|
||||||
}
|
}
|
||||||
struct dhcp *dhcp = netif_dhcp_data(esp_netif->lwip_netif);
|
struct dhcp_params opts = { .op = opt_op, .id = opt_id, .len = opt_len, .val = opt_val };
|
||||||
if (dhcp == NULL || opt_val == NULL) {
|
return esp_netif_lwip_ipc_call(esp_netif_dhcpc_option_api, esp_netif, &opts);
|
||||||
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
|
||||||
}
|
|
||||||
if (opt_op == ESP_NETIF_OP_GET) {
|
|
||||||
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STOPPED) {
|
|
||||||
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STOPPED;
|
|
||||||
}
|
|
||||||
switch (opt_id) {
|
|
||||||
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
|
|
||||||
if (opt_len == sizeof(dhcp->tries)) {
|
|
||||||
*(uint8_t *)opt_val = dhcp->tries;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
|
|
||||||
case ESP_NETIF_VENDOR_SPECIFIC_INFO:
|
|
||||||
return dhcp_get_vendor_specific_information(opt_len, opt_val);
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
|
||||||
}
|
|
||||||
} else if (opt_op == ESP_NETIF_OP_SET) {
|
|
||||||
if (esp_netif->dhcpc_status == ESP_NETIF_DHCP_STARTED) {
|
|
||||||
return ESP_ERR_ESP_NETIF_DHCP_ALREADY_STARTED;
|
|
||||||
}
|
|
||||||
switch (opt_id) {
|
|
||||||
case ESP_NETIF_IP_REQUEST_RETRY_TIME:
|
|
||||||
if (opt_len == sizeof(dhcp->tries)) {
|
|
||||||
dhcp->tries = *(uint8_t *)opt_val;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
#if ESP_DHCP && !ESP_DHCP_DISABLE_VENDOR_CLASS_IDENTIFIER
|
|
||||||
case ESP_NETIF_VENDOR_CLASS_IDENTIFIER:
|
|
||||||
return dhcp_set_vendor_class_identifier(opt_len, opt_val);
|
|
||||||
#endif
|
|
||||||
default:
|
|
||||||
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
|
||||||
}
|
|
||||||
return ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
|
int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
|
||||||
@ -2140,6 +2240,13 @@ int esp_netif_get_netif_impl_index(esp_netif_t *esp_netif)
|
|||||||
return netif_get_index(esp_netif->lwip_netif);
|
return netif_get_index(esp_netif->lwip_netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_get_netif_impl_name_api(esp_netif_api_msg_t *msg)
|
||||||
|
{
|
||||||
|
struct netif* netif = msg->esp_netif->lwip_netif;
|
||||||
|
netif_index_to_name(netif_get_index(netif), msg->data);
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
|
esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
|
||||||
{
|
{
|
||||||
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
|
ESP_LOGD(TAG, "%s esp_netif:%p", __func__, esp_netif);
|
||||||
@ -2147,8 +2254,7 @@ esp_err_t esp_netif_get_netif_impl_name(esp_netif_t *esp_netif, char* name)
|
|||||||
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
|
if (esp_netif == NULL || esp_netif->lwip_netif == NULL) {
|
||||||
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
return ESP_ERR_ESP_NETIF_INVALID_PARAMS;
|
||||||
}
|
}
|
||||||
netif_index_to_name(netif_get_index(esp_netif->lwip_netif), name);
|
return esp_netif_lwip_ipc_call(esp_netif_get_netif_impl_name_api, esp_netif, name);
|
||||||
return ESP_OK;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if MIB2_STATS
|
#if MIB2_STATS
|
||||||
|
@ -19,7 +19,10 @@ typedef struct esp_netif_api_msg_s {
|
|||||||
int type; /**< The first field MUST be int */
|
int type; /**< The first field MUST be int */
|
||||||
int ret;
|
int ret;
|
||||||
esp_netif_api_fn api_fn;
|
esp_netif_api_fn api_fn;
|
||||||
esp_netif_t *esp_netif;
|
union {
|
||||||
|
esp_netif_t *esp_netif;
|
||||||
|
esp_netif_callback_fn user_fn;
|
||||||
|
};
|
||||||
void *data;
|
void *data;
|
||||||
} esp_netif_api_msg_t;
|
} esp_netif_api_msg_t;
|
||||||
|
|
||||||
|
179
components/esp_netif/lwip/esp_netif_sntp.c
Normal file
179
components/esp_netif/lwip/esp_netif_sntp.c
Normal file
@ -0,0 +1,179 @@
|
|||||||
|
/*
|
||||||
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
|
*
|
||||||
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "freertos/FreeRTOS.h"
|
||||||
|
#include "freertos/event_groups.h"
|
||||||
|
#include "esp_event.h"
|
||||||
|
#include "esp_log.h"
|
||||||
|
#include "esp_check.h"
|
||||||
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_sntp.h"
|
||||||
|
#include "esp_sntp.h"
|
||||||
|
|
||||||
|
// Remove compat macro and include lwip API
|
||||||
|
#undef SNTP_OPMODE_POLL
|
||||||
|
#include "lwip/apps/sntp.h"
|
||||||
|
|
||||||
|
static const char *TAG = "esp_netif_sntp";
|
||||||
|
|
||||||
|
typedef struct sntp_storage {
|
||||||
|
esp_sntp_time_cb_t sync_cb;
|
||||||
|
SemaphoreHandle_t sync_sem;
|
||||||
|
ip_event_t ip_event_to_renew;
|
||||||
|
size_t index_of_first_server;
|
||||||
|
size_t num_of_servers;
|
||||||
|
char* servers[];
|
||||||
|
} sntp_storage_t;
|
||||||
|
|
||||||
|
static sntp_storage_t *s_storage = NULL;
|
||||||
|
|
||||||
|
static void sync_time_cb(struct timeval *tv)
|
||||||
|
{
|
||||||
|
if (s_storage && s_storage->sync_sem) {
|
||||||
|
xSemaphoreGive(s_storage->sync_sem);
|
||||||
|
}
|
||||||
|
if (s_storage && s_storage->sync_cb) {
|
||||||
|
s_storage->sync_cb(tv);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t sntp_init_api(void *ctx)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
|
||||||
|
esp_sntp_config_t * config = ctx;
|
||||||
|
ESP_GOTO_ON_FALSE(config->num_of_servers <= SNTP_MAX_SERVERS, ESP_ERR_INVALID_ARG, err, TAG, "Tried to configure more servers than enabled in lwip. Please update CONFIG_SNTP_MAX_SERVERS");
|
||||||
|
|
||||||
|
sntp_set_time_sync_notification_cb(sync_time_cb);
|
||||||
|
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||||
|
|
||||||
|
for (int i = 0; i < config->num_of_servers; ++i) {
|
||||||
|
sntp_setservername(i, config->servers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->server_from_dhcp) {
|
||||||
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
|
sntp_servermode_dhcp(1);
|
||||||
|
#else
|
||||||
|
ESP_GOTO_ON_FALSE(false, ESP_ERR_INVALID_ARG, err, TAG, "Tried to configure SNTP server from DHCP, while disabled. Please enable CONFIG_LWIP_DHCP_GET_NTP_SRV");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->smooth_sync) {
|
||||||
|
sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (config->start) {
|
||||||
|
sntp_init();
|
||||||
|
}
|
||||||
|
err:
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t renew_servers_api(void *ctx)
|
||||||
|
{
|
||||||
|
if (s_storage && s_storage->num_of_servers) {
|
||||||
|
for (int i = 0; i < s_storage->num_of_servers; ++i) {
|
||||||
|
sntp_setservername(i + s_storage->index_of_first_server, s_storage->servers[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_netif_sntp_renew_servers(void *handler_args, esp_event_base_t base, int32_t event_id, void *event_data)
|
||||||
|
{
|
||||||
|
esp_netif_tcpip_exec(renew_servers_api, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_sntp_init(const esp_sntp_config_t * config)
|
||||||
|
{
|
||||||
|
esp_err_t ret = ESP_OK;
|
||||||
|
s_storage = calloc(1, sizeof(sntp_storage_t) + // allocate space for servers only if we are supposed to refresh the settings
|
||||||
|
(config->renew_servers_after_new_IP ? config->num_of_servers * sizeof(char*) : 0));
|
||||||
|
ESP_GOTO_ON_FALSE(s_storage != NULL, ESP_ERR_NO_MEM, err, TAG, "Failed to allocate SNTP storage");
|
||||||
|
if (config->wait_for_sync) {
|
||||||
|
s_storage->sync_sem = xSemaphoreCreateBinary();
|
||||||
|
ESP_GOTO_ON_FALSE(s_storage->sync_sem != NULL, ESP_ERR_NO_MEM, err, TAG, "Failed to SNTP sync semaphore");
|
||||||
|
}
|
||||||
|
if (config->renew_servers_after_new_IP && config->num_of_servers > 0) {
|
||||||
|
s_storage->num_of_servers = config->num_of_servers;
|
||||||
|
s_storage->index_of_first_server = config->index_of_first_server;
|
||||||
|
// store the server names, as we'd have to refresh the config after IP event
|
||||||
|
for (int i = 0; i < config->num_of_servers; ++i) {
|
||||||
|
s_storage->servers[i] = strdup(config->servers[i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_GOTO_ON_ERROR(esp_event_handler_register(IP_EVENT, config->ip_event_to_renew, esp_netif_sntp_renew_servers, NULL),
|
||||||
|
err, TAG, "Failed to register IP event");
|
||||||
|
s_storage->ip_event_to_renew = config->ip_event_to_renew;
|
||||||
|
|
||||||
|
}
|
||||||
|
if (config->sync_cb) {
|
||||||
|
s_storage->sync_cb = config->sync_cb;
|
||||||
|
}
|
||||||
|
|
||||||
|
ESP_GOTO_ON_ERROR(esp_netif_tcpip_exec(sntp_init_api, (void*)config), err, TAG, "Failed initialize SNTP service");
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
err:
|
||||||
|
esp_netif_sntp_deinit();
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t sntp_stop_api(void *ctx)
|
||||||
|
{
|
||||||
|
sntp_stop();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_netif_sntp_deinit(void)
|
||||||
|
{
|
||||||
|
if (s_storage) {
|
||||||
|
sntp_storage_t *storage = s_storage;
|
||||||
|
s_storage = NULL;
|
||||||
|
sntp_set_time_sync_notification_cb(NULL);
|
||||||
|
esp_netif_tcpip_exec(sntp_stop_api, NULL);
|
||||||
|
if (storage->num_of_servers) {
|
||||||
|
for (int i = 0; i < storage->num_of_servers; ++i) {
|
||||||
|
free(storage->servers[i]);
|
||||||
|
}
|
||||||
|
esp_event_handler_unregister(IP_EVENT, storage->ip_event_to_renew, esp_netif_sntp_renew_servers);
|
||||||
|
}
|
||||||
|
if (storage->sync_sem) {
|
||||||
|
vSemaphoreDelete(storage->sync_sem);
|
||||||
|
}
|
||||||
|
free(storage);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_sntp_sync_wait(TickType_t tout)
|
||||||
|
{
|
||||||
|
if (s_storage == NULL || s_storage->sync_sem == NULL) {
|
||||||
|
return ESP_ERR_INVALID_STATE;
|
||||||
|
}
|
||||||
|
if (xQueueSemaphoreTake(s_storage->sync_sem, tout) != pdTRUE) {
|
||||||
|
return ESP_ERR_TIMEOUT;
|
||||||
|
}
|
||||||
|
if (sntp_get_sync_mode() == SNTP_SYNC_MODE_SMOOTH &&
|
||||||
|
sntp_get_sync_status() == SNTP_SYNC_STATUS_IN_PROGRESS) {
|
||||||
|
return ESP_ERR_NOT_FINISHED;
|
||||||
|
}
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
static esp_err_t sntp_start_api(void* ctx)
|
||||||
|
{
|
||||||
|
sntp_stop();
|
||||||
|
sntp_init();
|
||||||
|
return ESP_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
esp_err_t esp_netif_sntp_start(void)
|
||||||
|
{
|
||||||
|
return esp_netif_tcpip_exec(sntp_start_api, NULL);
|
||||||
|
}
|
@ -1,16 +1,8 @@
|
|||||||
// Copyright 2015-2019 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2015-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// 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_NETIF_PRIVATE_H_
|
#ifndef _ESP_NETIF_PRIVATE_H_
|
||||||
#define _ESP_NETIF_PRIVATE_H_
|
#define _ESP_NETIF_PRIVATE_H_
|
||||||
@ -145,34 +137,6 @@ void esp_netif_list_unlock(void);
|
|||||||
*/
|
*/
|
||||||
bool esp_netif_is_netif_listed(esp_netif_t *esp_netif);
|
bool esp_netif_is_netif_listed(esp_netif_t *esp_netif);
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Cause the TCP/IP stack to join a multicast group
|
|
||||||
*
|
|
||||||
* @param[in] esp_netif Handle to esp-netif instance
|
|
||||||
* @param[in] addr The multicast group to join
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK
|
|
||||||
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
|
||||||
* - ESP_ERR_ESP_NETIF_MLD6_FAILED
|
|
||||||
* - ESP_ERR_NO_MEM
|
|
||||||
*/
|
|
||||||
esp_err_t esp_netif_join_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr);
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @brief Cause the TCP/IP stack to leave a multicast group
|
|
||||||
*
|
|
||||||
* @param[in] esp_netif Handle to esp-netif instance
|
|
||||||
* @param[in] addr The multicast group to leave
|
|
||||||
*
|
|
||||||
* @return
|
|
||||||
* - ESP_OK
|
|
||||||
* - ESP_ERR_ESP_NETIF_INVALID_PARAMS
|
|
||||||
* - ESP_ERR_ESP_NETIF_MLD6_FAILED
|
|
||||||
* - ESP_ERR_NO_MEM
|
|
||||||
*/
|
|
||||||
esp_err_t esp_netif_leave_ip6_multicast_group(esp_netif_t *esp_netif, const esp_ip6_addr_t *addr);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Cause the TCP/IP stack to add an IPv6 address to the interface
|
* @brief Cause the TCP/IP stack to add an IPv6 address to the interface
|
||||||
*
|
*
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
* SPDX-License-Identifier: Unlicense OR CC0-1.0
|
||||||
*/
|
*/
|
||||||
@ -8,21 +8,26 @@
|
|||||||
#include "unity.h"
|
#include "unity.h"
|
||||||
#include "unity_fixture.h"
|
#include "unity_fixture.h"
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_sntp.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "esp_wifi_netif.h"
|
#include "esp_wifi_netif.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "lwip/sockets.h"
|
|
||||||
#include "test_utils.h"
|
#include "test_utils.h"
|
||||||
|
#include "memory_checks.h"
|
||||||
|
|
||||||
TEST_GROUP(esp_netif);
|
TEST_GROUP(esp_netif);
|
||||||
|
|
||||||
TEST_SETUP(esp_netif)
|
TEST_SETUP(esp_netif)
|
||||||
{
|
{
|
||||||
|
test_utils_record_free_mem();
|
||||||
|
TEST_ESP_OK(test_utils_set_leak_level(0, ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_GENERAL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST_TEAR_DOWN(esp_netif)
|
TEST_TEAR_DOWN(esp_netif)
|
||||||
{
|
{
|
||||||
|
test_utils_finish_and_evaluate_leaks(test_utils_get_leak_level(ESP_LEAK_TYPE_WARNING, ESP_COMP_LEAK_ALL),
|
||||||
|
test_utils_get_leak_level(ESP_LEAK_TYPE_CRITICAL, ESP_COMP_LEAK_ALL));
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(esp_netif, init_and_destroy)
|
TEST(esp_netif, init_and_destroy)
|
||||||
@ -37,6 +42,13 @@ TEST(esp_netif, init_and_destroy)
|
|||||||
esp_netif_destroy(esp_netif);
|
esp_netif_destroy(esp_netif);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
TEST(esp_netif, init_and_destroy_sntp)
|
||||||
|
{
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("127.0.0.1");
|
||||||
|
config.start = false;
|
||||||
|
esp_netif_sntp_init(&config);
|
||||||
|
esp_netif_sntp_deinit();
|
||||||
|
}
|
||||||
|
|
||||||
TEST(esp_netif, get_from_if_key)
|
TEST(esp_netif, get_from_if_key)
|
||||||
{
|
{
|
||||||
@ -275,14 +287,22 @@ TEST(esp_netif, get_set_hostname)
|
|||||||
|
|
||||||
TEST_GROUP_RUNNER(esp_netif)
|
TEST_GROUP_RUNNER(esp_netif)
|
||||||
{
|
{
|
||||||
|
/**
|
||||||
|
* Keep the tests that don't need to start TCP/IP stack first, when the leak checker
|
||||||
|
* is more strict with leak level set to 0
|
||||||
|
*/
|
||||||
RUN_TEST_CASE(esp_netif, init_and_destroy)
|
RUN_TEST_CASE(esp_netif, init_and_destroy)
|
||||||
|
RUN_TEST_CASE(esp_netif, init_and_destroy_sntp)
|
||||||
RUN_TEST_CASE(esp_netif, get_from_if_key)
|
RUN_TEST_CASE(esp_netif, get_from_if_key)
|
||||||
RUN_TEST_CASE(esp_netif, create_delete_multiple_netifs)
|
RUN_TEST_CASE(esp_netif, create_delete_multiple_netifs)
|
||||||
|
RUN_TEST_CASE(esp_netif, create_custom_wifi_interfaces)
|
||||||
|
/**
|
||||||
|
* After follow tests which start lwIP and thus expect some mem-leaks by TCP/IP stack
|
||||||
|
*/
|
||||||
|
RUN_TEST_CASE(esp_netif, get_set_hostname)
|
||||||
RUN_TEST_CASE(esp_netif, dhcp_client_state_transitions_wifi_sta)
|
RUN_TEST_CASE(esp_netif, dhcp_client_state_transitions_wifi_sta)
|
||||||
RUN_TEST_CASE(esp_netif, dhcp_server_state_transitions_wifi_ap)
|
RUN_TEST_CASE(esp_netif, dhcp_server_state_transitions_wifi_ap)
|
||||||
RUN_TEST_CASE(esp_netif, dhcp_server_state_transitions_mesh)
|
RUN_TEST_CASE(esp_netif, dhcp_server_state_transitions_mesh)
|
||||||
RUN_TEST_CASE(esp_netif, create_custom_wifi_interfaces)
|
|
||||||
RUN_TEST_CASE(esp_netif, get_set_hostname)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void app_main(void)
|
void app_main(void)
|
||||||
|
@ -2,3 +2,4 @@ CONFIG_UNITY_ENABLE_FIXTURE=y
|
|||||||
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
CONFIG_UNITY_ENABLE_IDF_TEST_RUNNER=y
|
||||||
|
|
||||||
CONFIG_ESP_NETIF_L2_TAP=y
|
CONFIG_ESP_NETIF_L2_TAP=y
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=y
|
||||||
|
@ -153,6 +153,7 @@ idf_component_register(SRCS "${srcs}"
|
|||||||
|
|
||||||
# lots of LWIP source files evaluate macros that check address of stack variables
|
# lots of LWIP source files evaluate macros that check address of stack variables
|
||||||
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-address)
|
target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-address)
|
||||||
|
target_compile_definitions(${COMPONENT_LIB} PRIVATE ESP_LWIP_COMPONENT_BUILD)
|
||||||
|
|
||||||
set_source_files_properties(
|
set_source_files_properties(
|
||||||
lwip/src/netif/ppp/pppos.c
|
lwip/src/netif/ppp/pppos.c
|
||||||
|
@ -19,12 +19,21 @@ menu "LWIP"
|
|||||||
bool "Enable tcpip core locking"
|
bool "Enable tcpip core locking"
|
||||||
default n
|
default n
|
||||||
help
|
help
|
||||||
If Enable tcpip core locking,Creates a global mutex that is held
|
If Enable tcpip core locking,Creates a global mutex that is held
|
||||||
during TCPIP thread operations.Can be locked by client code to perform
|
during TCPIP thread operations.Can be locked by client code to perform
|
||||||
lwIP operations without changing into TCPIP thread using callbacks.
|
lwIP operations without changing into TCPIP thread using callbacks.
|
||||||
See LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE().
|
See LOCK_TCPIP_CORE() and UNLOCK_TCPIP_CORE().
|
||||||
|
|
||||||
If disable tcpip core locking,TCP IP will perform tasks through context switching.
|
If disable tcpip core locking,TCP IP will perform tasks through context switching
|
||||||
|
|
||||||
|
config LWIP_CHECK_THREAD_SAFETY
|
||||||
|
bool "Checks that lwip API runs in expected context"
|
||||||
|
default n
|
||||||
|
help
|
||||||
|
Enable to check that the project does not violate lwip thread safety.
|
||||||
|
If enabled, all lwip functions that require thread awareness run an assertion
|
||||||
|
to verify that the TCP/IP core functionality is either locked or accessed
|
||||||
|
from the correct thread.
|
||||||
|
|
||||||
config LWIP_DNS_SUPPORT_MDNS_QUERIES
|
config LWIP_DNS_SUPPORT_MDNS_QUERIES
|
||||||
bool "Enable mDNS queries in resolving host name"
|
bool "Enable mDNS queries in resolving host name"
|
||||||
|
@ -9,11 +9,18 @@
|
|||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
#include "sntp.h"
|
#include "esp_sntp.h"
|
||||||
|
|
||||||
|
// Remove compat macro and include lwip API
|
||||||
|
#undef SNTP_OPMODE_POLL
|
||||||
#include "lwip/apps/sntp.h"
|
#include "lwip/apps/sntp.h"
|
||||||
|
#include "lwip/tcpip.h"
|
||||||
|
|
||||||
static const char *TAG = "sntp";
|
static const char *TAG = "sntp";
|
||||||
|
|
||||||
|
ESP_STATIC_ASSERT(SNTP_OPMODE_POLL == ESP_SNTP_OPMODE_POLL, "SNTP mode in lwip doesn't match the IDF enum. Please make sure lwIP version is correct");
|
||||||
|
ESP_STATIC_ASSERT(SNTP_OPMODE_LISTENONLY == ESP_SNTP_OPMODE_LISTENONLY, "SNTP mode in lwip doesn't match the IDF enum. Please make sure lwIP version is correct");
|
||||||
|
|
||||||
static volatile sntp_sync_mode_t sntp_sync_mode = SNTP_SYNC_MODE_IMMED;
|
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 volatile sntp_sync_status_t sntp_sync_status = SNTP_SYNC_STATUS_RESET;
|
||||||
static sntp_sync_time_cb_t time_sync_notification_cb = NULL;
|
static sntp_sync_time_cb_t time_sync_notification_cb = NULL;
|
||||||
@ -100,11 +107,17 @@ uint32_t sntp_get_sync_interval(void)
|
|||||||
return s_sync_interval;
|
return s_sync_interval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void sntp_do_restart(void *ctx)
|
||||||
|
{
|
||||||
|
(void)ctx;
|
||||||
|
sntp_stop();
|
||||||
|
sntp_init();
|
||||||
|
}
|
||||||
|
|
||||||
bool sntp_restart(void)
|
bool sntp_restart(void)
|
||||||
{
|
{
|
||||||
if (sntp_enabled()) {
|
if (sntp_enabled()) {
|
||||||
sntp_stop();
|
tcpip_callback(sntp_do_restart, NULL);
|
||||||
sntp_init();
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
@ -138,3 +151,98 @@ void sntp_get_system_time(uint32_t *sec, uint32_t *us)
|
|||||||
*(us) = tv.tv_usec;
|
*(us) = tv.tv_usec;
|
||||||
sntp_set_sync_status(SNTP_SYNC_STATUS_RESET);
|
sntp_set_sync_status(SNTP_SYNC_STATUS_RESET);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void do_setoperatingmode(void *ctx)
|
||||||
|
{
|
||||||
|
esp_sntp_operatingmode_t operating_mode = (esp_sntp_operatingmode_t)ctx;
|
||||||
|
sntp_setoperatingmode(operating_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sntp_setoperatingmode(esp_sntp_operatingmode_t operating_mode)
|
||||||
|
{
|
||||||
|
tcpip_callback(do_setoperatingmode, (void*)operating_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_init(void *ctx)
|
||||||
|
{
|
||||||
|
sntp_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sntp_init(void)
|
||||||
|
{
|
||||||
|
tcpip_callback(do_init, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void do_stop(void *ctx)
|
||||||
|
{
|
||||||
|
sntp_stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sntp_stop(void)
|
||||||
|
{
|
||||||
|
tcpip_callback(do_stop, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct do_setserver {
|
||||||
|
u8_t idx;
|
||||||
|
const ip_addr_t *addr;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void do_setserver(void *ctx)
|
||||||
|
{
|
||||||
|
struct do_setserver *params = ctx;
|
||||||
|
sntp_setserver(params->idx, params->addr);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sntp_setserver(u8_t idx, const ip_addr_t *addr)
|
||||||
|
{
|
||||||
|
struct do_setserver params = {
|
||||||
|
.idx = idx,
|
||||||
|
.addr = addr
|
||||||
|
};
|
||||||
|
tcpip_callback(do_setserver, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
struct do_setservername {
|
||||||
|
u8_t idx;
|
||||||
|
const char *server;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void do_setservername(void *ctx)
|
||||||
|
{
|
||||||
|
struct do_setservername *params = ctx;
|
||||||
|
sntp_setservername(params->idx, params->server);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sntp_setservername(u8_t idx, const char *server)
|
||||||
|
{
|
||||||
|
struct do_setservername params = {
|
||||||
|
.idx = idx,
|
||||||
|
.server = server
|
||||||
|
};
|
||||||
|
tcpip_callback(do_setservername, ¶ms);
|
||||||
|
}
|
||||||
|
|
||||||
|
const char *esp_sntp_getservername(u8_t idx)
|
||||||
|
{
|
||||||
|
return sntp_getservername(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
const ip_addr_t* esp_sntp_getserver(u8_t idx)
|
||||||
|
{
|
||||||
|
return sntp_getserver(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
|
static void do_servermode_dhcp(void* ctx)
|
||||||
|
{
|
||||||
|
u8_t servermode = (bool)ctx ? 1 : 0;
|
||||||
|
sntp_servermode_dhcp(servermode);
|
||||||
|
}
|
||||||
|
|
||||||
|
void esp_sntp_servermode_dhcp(bool enable)
|
||||||
|
{
|
||||||
|
tcpip_callback(do_servermode_dhcp, (void*)enable);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||||
|
@ -8,7 +8,7 @@
|
|||||||
#define __ESP_SNTP_H__
|
#define __ESP_SNTP_H__
|
||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/apps/sntp.h"
|
#include "lwip/ip.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
@ -38,6 +38,23 @@ extern "C" {
|
|||||||
* to wait for the next sync cycle.
|
* to wait for the next sync cycle.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
/// Aliases for esp_sntp prefixed API (inherently thread safe)
|
||||||
|
#define esp_sntp_sync_time sntp_sync_time
|
||||||
|
#define esp_sntp_set_sync_mode sntp_set_sync_mode
|
||||||
|
#define esp_sntp_get_sync_mode sntp_get_sync_mode
|
||||||
|
#define esp_sntp_get_sync_status sntp_get_sync_status
|
||||||
|
#define esp_sntp_set_sync_status sntp_set_sync_status
|
||||||
|
#define esp_sntp_set_time_sync_notification_cb sntp_set_time_sync_notification_cb
|
||||||
|
#define esp_sntp_set_sync_interval sntp_set_sync_interval
|
||||||
|
#define esp_sntp_get_sync_interval sntp_get_sync_interval
|
||||||
|
#define esp_sntp_restart sntp_restart
|
||||||
|
|
||||||
|
#ifndef SNTP_OPMODE_POLL
|
||||||
|
#define SNTP_OPMODE_POLL ESP_SNTP_OPMODE_POLL
|
||||||
|
#else
|
||||||
|
#warning "Defined!"
|
||||||
|
#endif /* SNTP_OPMODE_POLL */
|
||||||
|
|
||||||
/// SNTP time update mode
|
/// SNTP time update mode
|
||||||
typedef enum {
|
typedef enum {
|
||||||
SNTP_SYNC_MODE_IMMED, /*!< Update system time immediately when receiving a response from the SNTP server. */
|
SNTP_SYNC_MODE_IMMED, /*!< Update system time immediately when receiving a response from the SNTP server. */
|
||||||
@ -51,6 +68,12 @@ typedef enum {
|
|||||||
SNTP_SYNC_STATUS_IN_PROGRESS, // Smooth time sync in progress.
|
SNTP_SYNC_STATUS_IN_PROGRESS, // Smooth time sync in progress.
|
||||||
} sntp_sync_status_t;
|
} sntp_sync_status_t;
|
||||||
|
|
||||||
|
/// SNTP operating modes per lwip SNTP module
|
||||||
|
typedef enum {
|
||||||
|
ESP_SNTP_OPMODE_POLL,
|
||||||
|
ESP_SNTP_OPMODE_LISTENONLY,
|
||||||
|
} esp_sntp_operatingmode_t;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief SNTP callback function for notifying about time sync event
|
* @brief SNTP callback function for notifying about time sync event
|
||||||
*
|
*
|
||||||
@ -143,6 +166,106 @@ uint32_t sntp_get_sync_interval(void);
|
|||||||
*/
|
*/
|
||||||
bool sntp_restart(void);
|
bool sntp_restart(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets SNTP operating mode. The mode has to be set before init.
|
||||||
|
*
|
||||||
|
* @param operating_mode Desired operating mode
|
||||||
|
*/
|
||||||
|
void esp_sntp_setoperatingmode(esp_sntp_operatingmode_t operating_mode);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Init and start SNTP service
|
||||||
|
*/
|
||||||
|
void esp_sntp_init(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Stops SNTP service
|
||||||
|
*/
|
||||||
|
void esp_sntp_stop(void);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets SNTP server address
|
||||||
|
*
|
||||||
|
* @param idx Index of the server
|
||||||
|
* @param addr IP address of the server
|
||||||
|
*/
|
||||||
|
void esp_sntp_setserver(u8_t idx, const ip_addr_t *addr);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Sets SNTP hostname
|
||||||
|
* @param idx Index of the server
|
||||||
|
* @param server Name of the server
|
||||||
|
*/
|
||||||
|
void esp_sntp_setservername(u8_t idx, const char *server);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Gets SNTP server name
|
||||||
|
* @param idx Index of the server
|
||||||
|
* @return Name of the server
|
||||||
|
*/
|
||||||
|
const char *esp_sntp_getservername(u8_t idx);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Get SNTP server IP
|
||||||
|
* @param idx Index of the server
|
||||||
|
* @return IP address of the server
|
||||||
|
*/
|
||||||
|
const ip_addr_t* esp_sntp_getserver(u8_t idx);
|
||||||
|
|
||||||
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
|
/**
|
||||||
|
* @brief Enable acquiring SNTP server from DHCP
|
||||||
|
* @param enable True for enabling SNTP from DHCP
|
||||||
|
*/
|
||||||
|
void esp_sntp_servermode_dhcp(bool enable);
|
||||||
|
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||||
|
|
||||||
|
#if !defined(ESP_LWIP_COMPONENT_BUILD) && !defined(ESP_NETIF_COMPONENT_BUILD)
|
||||||
|
/**
|
||||||
|
* @brief if not build within lwip, provide translating inlines,
|
||||||
|
* that will warn about thread safety
|
||||||
|
*/
|
||||||
|
static inline __attribute__((deprecated("use esp_sntp_setoperatingmode() instead")))
|
||||||
|
void sntp_setoperatingmode(u8_t operating_mode)
|
||||||
|
{
|
||||||
|
esp_sntp_setoperatingmode(operating_mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((deprecated("use esp_sntp_servermode_dhcp() instead")))
|
||||||
|
void sntp_servermode_dhcp(int set_servers_from_dhcp)
|
||||||
|
{
|
||||||
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
|
esp_sntp_servermode_dhcp(set_servers_from_dhcp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((deprecated("use esp_sntp_setservername() instead")))
|
||||||
|
void sntp_setservername(u8_t idx, const char *server)
|
||||||
|
{
|
||||||
|
esp_sntp_setservername(idx, server);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((deprecated("use esp_sntp_init() instead")))
|
||||||
|
void sntp_init(void)
|
||||||
|
{
|
||||||
|
esp_sntp_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((deprecated("use esp_sntp_getservername() instead")))
|
||||||
|
const char *sntp_getservername(u8_t idx)
|
||||||
|
{
|
||||||
|
return esp_sntp_getservername(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline __attribute__((deprecated("use esp_sntp_getserver() instead")))
|
||||||
|
const ip_addr_t* sntp_getserver(u8_t idx)
|
||||||
|
{
|
||||||
|
return esp_sntp_getserver(idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif /* ESP_LWIP_COMPONENT_BUILD */
|
||||||
|
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -1,27 +1,16 @@
|
|||||||
// Copyright 2020 Espressif Systems (Shanghai) PTE LTD
|
/*
|
||||||
//
|
* SPDX-FileCopyrightText: 2020-2022 Espressif Systems (Shanghai) CO LTD
|
||||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
*
|
||||||
// you may not use this file except in compliance with the License.
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
// You may obtain a copy of the License at
|
*/
|
||||||
|
|
||||||
// http://www.apache.org/licenses/LICENSE-2.0
|
#pragma once
|
||||||
//
|
|
||||||
// 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__
|
|
||||||
|
|
||||||
|
#warning "sntp.h in IDF's lwip port folder is deprecated. Please include esp_sntp.h"
|
||||||
/*
|
/*
|
||||||
* This header is provided only for compatibility reasons for existing
|
* This header is provided only for compatibility reasons for existing
|
||||||
* applications which directly include "sntp.h" from the IDF default paths.
|
* applications which directly include "sntp.h" from the IDF default paths.
|
||||||
* and will be removed in IDF v5.0.
|
* and will be removed in IDF v6.0.
|
||||||
* It is recommended to use "esp_sntp.h" from IDF's lwip port folder
|
* It is recommended to use "esp_sntp.h" from IDF's lwip port folder
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include "esp_sntp.h"
|
#include "esp_sntp.h"
|
||||||
|
|
||||||
#endif // __SNTP_H__
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 705dd71d46779bf29653f1f1d7b1af5a09fb2aa7
|
Subproject commit 10197b212a95c49c733fb18ffed56cafb0d196d4
|
@ -53,7 +53,6 @@ static sys_mutex_t g_lwip_protect_mutex = NULL;
|
|||||||
|
|
||||||
static pthread_key_t sys_thread_sem_key;
|
static pthread_key_t sys_thread_sem_key;
|
||||||
static void sys_thread_sem_free(void* data);
|
static void sys_thread_sem_free(void* data);
|
||||||
sys_thread_t g_lwip_task;
|
|
||||||
|
|
||||||
#if !LWIP_COMPAT_MUTEX
|
#if !LWIP_COMPAT_MUTEX
|
||||||
|
|
||||||
@ -428,10 +427,8 @@ sys_thread_new(const char *name, lwip_thread_fn thread, void *arg, int stacksize
|
|||||||
ret = xTaskCreatePinnedToCore(thread, name, stacksize, arg, prio, &rtos_task,
|
ret = xTaskCreatePinnedToCore(thread, name, stacksize, arg, prio, &rtos_task,
|
||||||
CONFIG_LWIP_TCPIP_TASK_AFFINITY);
|
CONFIG_LWIP_TCPIP_TASK_AFFINITY);
|
||||||
|
|
||||||
g_lwip_task = rtos_task;
|
LWIP_DEBUGF(TCPIP_DEBUG, ("new lwip task : %x, prio:%d,stack:%d\n",
|
||||||
|
(u32_t)rtos_task, prio, stacksize));
|
||||||
LWIP_DEBUGF(TCPIP_DEBUG, ("tcpip_task_hdlxxx : %x, prio:%d,stack:%d\n",
|
|
||||||
(u32_t)g_lwip_task,TCPIP_THREAD_PRIO,TCPIP_THREAD_STACKSIZE));
|
|
||||||
|
|
||||||
if (ret != pdTRUE) {
|
if (ret != pdTRUE) {
|
||||||
return NULL;
|
return NULL;
|
||||||
@ -577,3 +574,36 @@ sys_delay_ms(uint32_t ms)
|
|||||||
{
|
{
|
||||||
vTaskDelay(ms / portTICK_PERIOD_MS);
|
vTaskDelay(ms / portTICK_PERIOD_MS);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool
|
||||||
|
sys_thread_tcpip(sys_thread_core_lock_t type)
|
||||||
|
{
|
||||||
|
static sys_thread_t lwip_task = NULL;
|
||||||
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
|
static sys_thread_t core_lock_holder = NULL;
|
||||||
|
#endif
|
||||||
|
switch (type) {
|
||||||
|
default:
|
||||||
|
return false;
|
||||||
|
case LWIP_CORE_IS_TCPIP_INITIALIZED:
|
||||||
|
return lwip_task != NULL;
|
||||||
|
case LWIP_CORE_MARK_TCPIP_TASK:
|
||||||
|
LWIP_ASSERT("LWIP_CORE_MARK_TCPIP_TASK: lwip_task == NULL", (lwip_task == NULL));
|
||||||
|
lwip_task = (sys_thread_t) xTaskGetCurrentTaskHandle();
|
||||||
|
return true;
|
||||||
|
#if LWIP_TCPIP_CORE_LOCKING
|
||||||
|
case LWIP_CORE_LOCK_QUERY_HOLDER:
|
||||||
|
return lwip_task ? core_lock_holder == (sys_thread_t) xTaskGetCurrentTaskHandle() : true;
|
||||||
|
case LWIP_CORE_LOCK_MARK_HOLDER:
|
||||||
|
core_lock_holder = (sys_thread_t) xTaskGetCurrentTaskHandle();
|
||||||
|
return true;
|
||||||
|
case LWIP_CORE_LOCK_UNMARK_HOLDER:
|
||||||
|
core_lock_holder = NULL;
|
||||||
|
return true;
|
||||||
|
#else
|
||||||
|
case LWIP_CORE_LOCK_QUERY_HOLDER:
|
||||||
|
return lwip_task == NULL || lwip_task == (sys_thread_t) xTaskGetCurrentTaskHandle();
|
||||||
|
#endif /* LWIP_TCPIP_CORE_LOCKING */
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
@ -100,6 +100,17 @@ sys_sem_t* sys_thread_sem_init(void);
|
|||||||
void sys_thread_sem_deinit(void);
|
void sys_thread_sem_deinit(void);
|
||||||
sys_sem_t* sys_thread_sem_get(void);
|
sys_sem_t* sys_thread_sem_get(void);
|
||||||
|
|
||||||
|
typedef enum {
|
||||||
|
LWIP_CORE_LOCK_QUERY_HOLDER,
|
||||||
|
LWIP_CORE_LOCK_MARK_HOLDER,
|
||||||
|
LWIP_CORE_LOCK_UNMARK_HOLDER,
|
||||||
|
LWIP_CORE_MARK_TCPIP_TASK,
|
||||||
|
LWIP_CORE_IS_TCPIP_INITIALIZED,
|
||||||
|
} sys_thread_core_lock_t;
|
||||||
|
|
||||||
|
bool
|
||||||
|
sys_thread_tcpip(sys_thread_core_lock_t type);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
@ -12,6 +12,7 @@
|
|||||||
#include "lwip/pbuf.h"
|
#include "lwip/pbuf.h"
|
||||||
#include "netif/dhcp_state.h"
|
#include "netif/dhcp_state.h"
|
||||||
|
|
||||||
|
|
||||||
#ifdef ESP_IDF_LWIP_HOOK_FILENAME
|
#ifdef ESP_IDF_LWIP_HOOK_FILENAME
|
||||||
#include ESP_IDF_LWIP_HOOK_FILENAME
|
#include ESP_IDF_LWIP_HOOK_FILENAME
|
||||||
#endif
|
#endif
|
||||||
|
@ -26,6 +26,7 @@
|
|||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
#include "sntp/sntp_get_set_time.h"
|
#include "sntp/sntp_get_set_time.h"
|
||||||
#include "sockets_ext.h"
|
#include "sockets_ext.h"
|
||||||
|
#include "arch/sys_arch.h"
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
extern "C" {
|
extern "C" {
|
||||||
@ -46,9 +47,20 @@ extern "C" {
|
|||||||
*/
|
*/
|
||||||
#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING
|
#ifdef CONFIG_LWIP_TCPIP_CORE_LOCKING
|
||||||
#define LWIP_TCPIP_CORE_LOCKING 1
|
#define LWIP_TCPIP_CORE_LOCKING 1
|
||||||
|
#define LOCK_TCPIP_CORE() do { sys_mutex_lock(&lock_tcpip_core); sys_thread_tcpip(LWIP_CORE_LOCK_MARK_HOLDER); } while(0)
|
||||||
|
#define UNLOCK_TCPIP_CORE() do { sys_thread_tcpip(LWIP_CORE_LOCK_UNMARK_HOLDER); sys_mutex_unlock(&lock_tcpip_core); } while(0)
|
||||||
|
#ifdef CONFIG_LWIP_CHECK_THREAD_SAFETY
|
||||||
|
#define LWIP_ASSERT_CORE_LOCKED() do { LWIP_ASSERT("Required to lock TCPIP core functionality!", sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)); } while(0)
|
||||||
|
#endif /* CONFIG_LWIP_CHECK_THREAD_SAFETY */
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define LWIP_TCPIP_CORE_LOCKING 0
|
#define LWIP_TCPIP_CORE_LOCKING 0
|
||||||
#endif
|
#ifdef CONFIG_LWIP_CHECK_THREAD_SAFETY
|
||||||
|
#define LWIP_ASSERT_CORE_LOCKED() do { LWIP_ASSERT("Required to run in TCPIP context!", sys_thread_tcpip(LWIP_CORE_LOCK_QUERY_HOLDER)); } while(0)
|
||||||
|
#endif /* CONFIG_LWIP_CHECK_THREAD_SAFETY */
|
||||||
|
#endif /* CONFIG_LWIP_TCPIP_CORE_LOCKING */
|
||||||
|
|
||||||
|
#define LWIP_MARK_TCPIP_THREAD() sys_thread_tcpip(LWIP_CORE_MARK_TCPIP_TASK)
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
|
* SYS_LIGHTWEIGHT_PROT==1: if you want inter-task protection for certain
|
||||||
@ -845,11 +857,7 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min)
|
|||||||
* The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup().
|
* The latter 2 can be invoked up by calling netconn_thread_init()/netconn_thread_cleanup().
|
||||||
* Ports may call these for threads created with sys_thread_new().
|
* Ports may call these for threads created with sys_thread_new().
|
||||||
*/
|
*/
|
||||||
#if LWIP_TCPIP_CORE_LOCKING
|
|
||||||
#define LWIP_NETCONN_SEM_PER_THREAD 0
|
|
||||||
#else
|
|
||||||
#define LWIP_NETCONN_SEM_PER_THREAD 1
|
#define LWIP_NETCONN_SEM_PER_THREAD 1
|
||||||
#endif
|
|
||||||
|
|
||||||
/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread,
|
/** LWIP_NETCONN_FULLDUPLEX==1: Enable code that allows reading from one thread,
|
||||||
* writing from a 2nd thread and closing from a 3rd thread at the same time.
|
* writing from a 2nd thread and closing from a 3rd thread at the same time.
|
||||||
@ -1198,11 +1206,17 @@ static inline uint32_t timeout_from_offered(uint32_t lease, uint32_t min)
|
|||||||
#endif
|
#endif
|
||||||
#define LWIP_HOOK_FILENAME "lwip_default_hooks.h"
|
#define LWIP_HOOK_FILENAME "lwip_default_hooks.h"
|
||||||
#define LWIP_HOOK_IP4_ROUTE_SRC ip4_route_src_hook
|
#define LWIP_HOOK_IP4_ROUTE_SRC ip4_route_src_hook
|
||||||
|
#if LWIP_NETCONN_FULLDUPLEX
|
||||||
|
#define LWIP_DONE_SOCK(s) done_socket(sock)
|
||||||
|
#else
|
||||||
|
#define LWIP_DONE_SOCK(s) ((void)1)
|
||||||
|
#endif /* LWIP_NETCONN_FULLDUPLEX */
|
||||||
|
|
||||||
#define LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, err) \
|
#define LWIP_HOOK_SOCKETS_GETSOCKOPT(s, sock, level, optname, optval, optlen, err) \
|
||||||
lwip_getsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(done_socket(sock), true): false
|
lwip_getsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(LWIP_DONE_SOCK(sock), true): false
|
||||||
|
|
||||||
#define LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err) \
|
#define LWIP_HOOK_SOCKETS_SETSOCKOPT(s, sock, level, optname, optval, optlen, err) \
|
||||||
lwip_setsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(done_socket(sock), true): false
|
lwip_setsockopt_impl_ext(sock, level, optname, optval, optlen, err)?(LWIP_DONE_SOCK(sock), true): false
|
||||||
|
|
||||||
/*
|
/*
|
||||||
---------------------------------------
|
---------------------------------------
|
||||||
|
@ -1,2 +1,4 @@
|
|||||||
|
CONFIG_LWIP_TCPIP_CORE_LOCKING=n
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=n
|
||||||
CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=n
|
CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES=n
|
||||||
CONFIG_FREERTOS_SMP=n
|
CONFIG_FREERTOS_SMP=n
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD
|
* SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD
|
||||||
*
|
*
|
||||||
* SPDX-License-Identifier: Apache-2.0
|
* SPDX-License-Identifier: Apache-2.0
|
||||||
*/
|
*/
|
||||||
@ -18,6 +18,8 @@
|
|||||||
#include "lwip/inet.h"
|
#include "lwip/inet.h"
|
||||||
#include "lwip/netdb.h"
|
#include "lwip/netdb.h"
|
||||||
#include "lwip/sockets.h"
|
#include "lwip/sockets.h"
|
||||||
|
#include "lwip/tcpip.h"
|
||||||
|
#include "lwip/prot/iana.h"
|
||||||
#include "ping/ping_sock.h"
|
#include "ping/ping_sock.h"
|
||||||
#include "dhcpserver/dhcpserver.h"
|
#include "dhcpserver/dhcpserver.h"
|
||||||
#include "dhcpserver/dhcpserver_options.h"
|
#include "dhcpserver/dhcpserver_options.h"
|
||||||
@ -142,12 +144,18 @@ TEST(lwip, dhcp_server_init_deinit)
|
|||||||
dhcps_delete(dhcps);
|
dhcps_delete(dhcps);
|
||||||
}
|
}
|
||||||
|
|
||||||
TEST(lwip, dhcp_server_start_stop_localhost)
|
struct dhcps_api {
|
||||||
{
|
EventGroupHandle_t event;
|
||||||
test_case_uses_tcpip();
|
|
||||||
struct netif *netif;
|
|
||||||
dhcps_t *dhcps;
|
|
||||||
ip4_addr_t netmask;
|
ip4_addr_t netmask;
|
||||||
|
ip4_addr_t ip;
|
||||||
|
err_t ret_start;
|
||||||
|
err_t ret_stop;
|
||||||
|
};
|
||||||
|
|
||||||
|
static void dhcps_test_net_classes_api(void* ctx)
|
||||||
|
{
|
||||||
|
struct netif *netif;
|
||||||
|
struct dhcps_api *api = ctx;
|
||||||
|
|
||||||
NETIF_FOREACH(netif) {
|
NETIF_FOREACH(netif) {
|
||||||
if (netif->name[0] == 'l' && netif->name[1] == 'o') {
|
if (netif->name[0] == 'l' && netif->name[1] == 'o') {
|
||||||
@ -156,41 +164,51 @@ TEST(lwip, dhcp_server_start_stop_localhost)
|
|||||||
}
|
}
|
||||||
TEST_ASSERT_NOT_NULL(netif);
|
TEST_ASSERT_NOT_NULL(netif);
|
||||||
|
|
||||||
//Class A
|
dhcps_t *dhcps = dhcps_new();
|
||||||
dhcps = dhcps_new();
|
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&api->netmask, sizeof(api->netmask));
|
||||||
IP4_ADDR(&netmask, 255,0,0,0);
|
api->ret_start = dhcps_start(dhcps, netif, api->ip);
|
||||||
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
|
api->ret_stop = dhcps_stop(dhcps, netif);
|
||||||
ip4_addr_t a_ip = { .addr = 0x7f0001 };
|
|
||||||
IP4_ADDR(&netmask, 255,0,0,0);
|
|
||||||
TEST_ASSERT(dhcps_start(dhcps, netif, a_ip) == ERR_OK);
|
|
||||||
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
|
|
||||||
dhcps_delete(dhcps);
|
dhcps_delete(dhcps);
|
||||||
|
xEventGroupSetBits(api->event, 1);
|
||||||
|
}
|
||||||
|
|
||||||
//Class B
|
static void dhcps_test_net_classes(uint32_t ip, uint32_t mask, bool pass)
|
||||||
dhcps = dhcps_new();
|
{
|
||||||
IP4_ADDR(&netmask, 255,255,0,0);
|
|
||||||
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
|
|
||||||
ip4_addr_t b_ip = { .addr = 0x1000080 };
|
|
||||||
TEST_ASSERT(dhcps_start(dhcps, netif, b_ip) == ERR_OK);
|
|
||||||
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
|
|
||||||
dhcps_delete(dhcps);
|
|
||||||
|
|
||||||
//Class C
|
struct dhcps_api api = {
|
||||||
dhcps = dhcps_new();
|
.ret_start = ERR_IF,
|
||||||
IP4_ADDR(&netmask, 255,255,255,0);
|
.ret_stop = ERR_IF,
|
||||||
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
|
.ip = {.addr = PP_HTONL(ip)},
|
||||||
ip4_addr_t c_ip = { .addr = 0x101A8C0 };
|
.netmask = {.addr = PP_HTONL(mask)},
|
||||||
TEST_ASSERT(dhcps_start(dhcps, netif, c_ip) == ERR_OK);
|
.event = xEventGroupCreate()
|
||||||
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
|
};
|
||||||
dhcps_delete(dhcps);
|
|
||||||
|
tcpip_callback(dhcps_test_net_classes_api, &api);
|
||||||
|
xEventGroupWaitBits(api.event, 1, true, true, pdMS_TO_TICKS(5000));
|
||||||
|
vEventGroupDelete(api.event);
|
||||||
|
err_t ret_start_expected = pass ? ERR_OK : ERR_ARG;
|
||||||
|
TEST_ASSERT(api.ret_start == ret_start_expected);
|
||||||
|
TEST_ASSERT(api.ret_stop == ERR_OK);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
TEST(lwip, dhcp_server_start_stop_localhost)
|
||||||
|
{
|
||||||
|
test_case_uses_tcpip();
|
||||||
|
|
||||||
|
// Class A: IP: 127.0.0.1, Mask: 255.0.0.0
|
||||||
|
dhcps_test_net_classes(0x7f000001, 0xFF000000, true);
|
||||||
|
|
||||||
|
// Class B: IP: 128.1.1.1, Mask: 255.255.0.0
|
||||||
|
dhcps_test_net_classes(0x80010101, 0xFFFF0000, true);
|
||||||
|
|
||||||
|
// Class C: IP: 192.168.1.1, Mask: 255.255.255.0
|
||||||
|
dhcps_test_net_classes(0xC0A80101, 0xFFFFFF00, true);
|
||||||
|
|
||||||
|
// Class A: IP: 127.0.0.1, with Class C Mask: 255.255.255.0
|
||||||
|
// expect dhcps_start() to fail
|
||||||
|
dhcps_test_net_classes(0x7f000001, 0xFFFFFF00, false);
|
||||||
|
|
||||||
//Class A Subnet C
|
|
||||||
dhcps = dhcps_new();
|
|
||||||
IP4_ADDR(&netmask, 255,255,255,0);
|
|
||||||
dhcps_set_option_info(dhcps, SUBNET_MASK, (void*)&netmask, sizeof(netmask));
|
|
||||||
TEST_ASSERT(dhcps_start(dhcps, netif, a_ip) == ERR_ARG);
|
|
||||||
TEST_ASSERT(dhcps_stop(dhcps, netif) == ERR_OK);
|
|
||||||
dhcps_delete(dhcps);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -248,11 +266,10 @@ void test_sntp_timestamps(int year, bool msb_flag)
|
|||||||
{
|
{
|
||||||
int sock = test_sntp_server_create();
|
int sock = test_sntp_server_create();
|
||||||
|
|
||||||
// setup lwip's SNTP in polling mode
|
// init and start the SNTP
|
||||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
esp_sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
||||||
sntp_setservername(0, "127.0.0.1");
|
esp_sntp_setservername(0, "127.0.0.1");
|
||||||
sntp_init();
|
esp_sntp_init();
|
||||||
|
|
||||||
// wait until time sync
|
// wait until time sync
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET) {
|
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET) {
|
||||||
@ -269,7 +286,7 @@ void test_sntp_timestamps(int year, bool msb_flag)
|
|||||||
TEST_ASSERT_EQUAL(year, 1900 + timeinfo.tm_year);
|
TEST_ASSERT_EQUAL(year, 1900 + timeinfo.tm_year);
|
||||||
|
|
||||||
// close the SNTP and the fake server
|
// close the SNTP and the fake server
|
||||||
sntp_stop();
|
esp_sntp_stop();
|
||||||
close(sock);
|
close(sock);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1 +1 @@
|
|||||||
Subproject commit 7d57b18006da6e182ddb87698abdced1566f3b56
|
Subproject commit 2e5a3f236f8cd7c753fd8b8f775e48e8be5f08d6
|
@ -155,6 +155,7 @@ INPUT = \
|
|||||||
$(PROJECT_PATH)/components/esp_netif/include/esp_netif_types.h \
|
$(PROJECT_PATH)/components/esp_netif/include/esp_netif_types.h \
|
||||||
$(PROJECT_PATH)/components/esp_netif/include/esp_netif.h \
|
$(PROJECT_PATH)/components/esp_netif/include/esp_netif.h \
|
||||||
$(PROJECT_PATH)/components/esp_netif/include/esp_vfs_l2tap.h \
|
$(PROJECT_PATH)/components/esp_netif/include/esp_vfs_l2tap.h \
|
||||||
|
$(PROJECT_PATH)/components/esp_netif/include/esp_netif_sntp.h \
|
||||||
$(PROJECT_PATH)/components/esp_partition/include/esp_partition.h \
|
$(PROJECT_PATH)/components/esp_partition/include/esp_partition.h \
|
||||||
$(PROJECT_PATH)/components/esp_phy/include/esp_phy_init.h \
|
$(PROJECT_PATH)/components/esp_phy/include/esp_phy_init.h \
|
||||||
$(PROJECT_PATH)/components/esp_pm/include/$(IDF_TARGET)/pm.h \
|
$(PROJECT_PATH)/components/esp_pm/include/$(IDF_TARGET)/pm.h \
|
||||||
|
@ -14,10 +14,15 @@ ESP-IDF supports the following lwIP TCP/IP stack functions:
|
|||||||
Adapted APIs
|
Adapted APIs
|
||||||
^^^^^^^^^^^^
|
^^^^^^^^^^^^
|
||||||
|
|
||||||
|
.. warning::
|
||||||
|
|
||||||
|
When using any lwIP API (other than `BSD Sockets API`_), please make sure that it is thread safe. To check if a given API call is safe, enable :ref:`CONFIG_LWIP_CHECK_THREAD_SAFETY` and run the application. This way lwIP asserts the TCP/IP core functionality to be correctly accessed; the execution aborts if it is not locked properly or accessed from the correct task (`lwIP FreeRTOS Task`_).
|
||||||
|
The general recommendation is to use :doc:`/api-reference/network/esp_netif` component to interact with lwIP.
|
||||||
|
|
||||||
Some common lwIP "app" APIs are supported indirectly by ESP-IDF:
|
Some common lwIP "app" APIs are supported indirectly by ESP-IDF:
|
||||||
|
|
||||||
- DHCP Server & Client are supported indirectly via the :doc:`/api-reference/network/esp_netif` functionality
|
- DHCP Server & Client are supported indirectly via the :doc:`/api-reference/network/esp_netif` functionality
|
||||||
- Simple Network Time Protocol (SNTP) is supported via the :component_file:`lwip/include/apps/sntp/sntp.h` :component_file:`lwip/lwip/src/include/lwip/apps/sntp.h` functions (see also :ref:`system-time-sntp-sync`)
|
- Simple Network Time Protocol (SNTP) is also supported via the :doc:`/api-reference/network/esp_netif`, or directly via the :component_file:`lwip/include/apps/esp_sntp.h` functions that provide thread-safe API to :component_file:`lwip/lwip/src/include/lwip/apps/sntp.h` functions (see also :ref:`system-time-sntp-sync`)
|
||||||
- ICMP Ping is supported using a variation on the lwIP ping API. See :doc:`/api-reference/protocols/icmp_echo`.
|
- ICMP Ping is supported using a variation on the lwIP ping API. See :doc:`/api-reference/protocols/icmp_echo`.
|
||||||
- NetBIOS lookup is available using the standard lwIP API. :example:`protocols/http_server/restful_server` has an option to demonstrate using NetBIOS to look up a host on the LAN.
|
- NetBIOS lookup is available using the standard lwIP API. :example:`protocols/http_server/restful_server` has an option to demonstrate using NetBIOS to look up a host on the LAN.
|
||||||
- mDNS uses a different implementation to the lwIP default mDNS (see :doc:`/api-reference/protocols/mdns`), but lwIP can look up mDNS hosts using standard APIs such as ``gethostbyname()`` and the convention ``hostname.local``, provided the :ref:`CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES` setting is enabled.
|
- mDNS uses a different implementation to the lwIP default mDNS (see :doc:`/api-reference/protocols/mdns`), but lwIP can look up mDNS hosts using standard APIs such as ``gethostbyname()`` and the convention ``hostname.local``, provided the :ref:`CONFIG_LWIP_DNS_SUPPORT_MDNS_QUERIES` setting is enabled.
|
||||||
|
@ -21,14 +21,14 @@ ESP-NETIF architecture
|
|||||||
|
|
||||||
|
|
||||||
| (A) USER CODE |
|
| (A) USER CODE |
|
||||||
| |
|
| Apps |
|
||||||
.................| init settings events |
|
.................| init settings events |
|
||||||
. +----------------------------------------+
|
. +----------------------------------------+
|
||||||
. . | *
|
. . | *
|
||||||
. . | *
|
. . | *
|
||||||
--------+ +===========================+ * +-----------------------+
|
--------+ +===========================+ * +-----------------------+
|
||||||
| | new/config get/set | * | |
|
| | new/config get/set/apps | * | init |
|
||||||
| | |...*.....| init |
|
| | |...*.....| Apps (DHCP, SNTP) |
|
||||||
| |---------------------------| * | |
|
| |---------------------------| * | |
|
||||||
init | | |**** | |
|
init | | |**** | |
|
||||||
start |************| event handler |*********| DHCP |
|
start |************| event handler |*********| DHCP |
|
||||||
@ -132,6 +132,7 @@ ESP-NETIF is an intermediary between an IO driver and a network stack, connectin
|
|||||||
* Set interface up or down
|
* Set interface up or down
|
||||||
* DHCP server and client API
|
* DHCP server and client API
|
||||||
* DNS API
|
* DNS API
|
||||||
|
* `SNTP API`_
|
||||||
|
|
||||||
6) Driver conversion utilities
|
6) Driver conversion utilities
|
||||||
|
|
||||||
@ -242,6 +243,81 @@ select()
|
|||||||
Select is used in a standard way, just :ref:`CONFIG_VFS_SUPPORT_SELECT` needs to be enabled to be the ``select()`` function available.
|
Select is used in a standard way, just :ref:`CONFIG_VFS_SUPPORT_SELECT` needs to be enabled to be the ``select()`` function available.
|
||||||
|
|
||||||
|
|
||||||
|
.. _esp_netif-sntp-api:
|
||||||
|
|
||||||
|
SNTP API
|
||||||
|
--------
|
||||||
|
|
||||||
|
You can find a brief introduction to SNTP in general, its initialization code and basic modes in :ref:`system-time-sntp-sync` section in the :doc:`System Time Document</api-reference/system/system_time>`.
|
||||||
|
|
||||||
|
This section provides more details about specific use cases of SNTP service, with statically configured servers, or using DHCP provided servers, or both.
|
||||||
|
The workflow is usually very simple:
|
||||||
|
|
||||||
|
1) Initialize and configure the service using :cpp:func:`esp_netif_sntp_init()`.
|
||||||
|
2) Start the service via :cpp:func:`esp_netif_sntp_start()`. This step is not needed if we auto-started the service in the previous step (default). It's useful to start the service explicitly after connecting, if we want to use DHCP obtained NTP servers. (This option needs to be enabled before connecting, but SNTP service should be started after)
|
||||||
|
3) Wait for the system time to synchronize using :cpp:func:`esp_netif_sntp_sync_wait()` (only if needed).
|
||||||
|
4) Stop and destroy the service using :cpp:func:`esp_netif_sntp_deinit()`.
|
||||||
|
|
||||||
|
|
||||||
|
Basic mode with statically defined server(s)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Initialize the module with the default configuration after connecting to network. Note that it's possible to provide multiple NTP servers in the configuration struct:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(2,
|
||||||
|
ESP_SNTP_SERVER_LIST("time.windows.com", "pool.ntp.org" ) );
|
||||||
|
esp_netif_sntp_init(&config);
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
If we want to configure multiple SNTP servers, we have to update lwIP configuration :ref:`CONFIG_LWIP_SNTP_MAX_SERVERS`.
|
||||||
|
|
||||||
|
|
||||||
|
Use DHCP obtained SNTP server(s)
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
First of all, we have to enable lwIP configuration option :ref:`CONFIG_LWIP_DHCP_GET_NTP_SRV`.
|
||||||
|
Then we have to initialize the SNTP module with the DHCP option and no NTP server:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(0, {} );
|
||||||
|
config.start = false; // start SNTP service explicitly
|
||||||
|
config.server_from_dhcp = true; // accept NTP offer from DHCP server
|
||||||
|
esp_netif_sntp_init(&config);
|
||||||
|
|
||||||
|
Then, once we're connected, we could start the service using:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
esp_netif_sntp_start();
|
||||||
|
|
||||||
|
.. note::
|
||||||
|
|
||||||
|
It's also possible to start the service during initialization (default ``config.start=true``). This would likely cause the initial SNTP request to fail (since we are not connected yet) and thus some backoff time for subsequent requests.
|
||||||
|
|
||||||
|
|
||||||
|
Use both static and dynamic servers
|
||||||
|
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
|
||||||
|
|
||||||
|
Very similar to the scenario above (DHCP provided SNTP server), but in this configuration we need to make sure that the static server configuration is refreshed when obtaining NTP servers by DHCP. The underlying lwIP code cleans up the rest of the list of NTP servers when DHCP provided information gets accepted. Thus the ESP-NETIF SNTP module saves the statically configured server(s) and reconfigures them after obtaining DHCP lease.
|
||||||
|
|
||||||
|
The typical configuration now looks as per below, providing the specific ``IP_EVENT`` to update the config and index of the first server to reconfigure (for example setting ``config.index_of_first_server=1`` would keep DHCP provided server at index 0, and the statically configured server at index 1).
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
|
||||||
|
config.start = false; // start SNTP service explicitly (after connecting)
|
||||||
|
config.server_from_dhcp = true; // accept NTP offers from DHCP server
|
||||||
|
config.renew_servers_after_new_IP = true; // let esp-netif update configured SNTP server(s) after receiving DHCP lease
|
||||||
|
config.index_of_first_server = 1; // updates from server num 1, leaving server 0 (from DHCP) intact
|
||||||
|
config.ip_event_to_renew = IP_EVENT_STA_GOT_IP; // IP event on which we refresh the configuration
|
||||||
|
|
||||||
|
Then we start the service normally with :cpp:func:`esp_netif_sntp_start()`.
|
||||||
|
|
||||||
|
|
||||||
ESP-NETIF programmer's manual
|
ESP-NETIF programmer's manual
|
||||||
-----------------------------
|
-----------------------------
|
||||||
|
|
||||||
@ -287,6 +363,7 @@ API Reference
|
|||||||
-------------
|
-------------
|
||||||
|
|
||||||
.. include-build-file:: inc/esp_netif.inc
|
.. include-build-file:: inc/esp_netif.inc
|
||||||
|
.. include-build-file:: inc/esp_netif_sntp.inc
|
||||||
.. include-build-file:: inc/esp_netif_types.inc
|
.. include-build-file:: inc/esp_netif_types.inc
|
||||||
.. include-build-file:: inc/esp_netif_ip_addr.inc
|
.. include-build-file:: inc/esp_netif_ip_addr.inc
|
||||||
.. include-build-file:: inc/esp_vfs_l2tap.inc
|
.. include-build-file:: inc/esp_vfs_l2tap.inc
|
||||||
|
@ -108,28 +108,46 @@ SNTP Time Synchronization
|
|||||||
|
|
||||||
To set the current time, you can use the POSIX functions ``settimeofday()`` and ``adjtime()``. They are used internally in the lwIP SNTP library to set current time when a response from the NTP server is received. These functions can also be used separately from the lwIP SNTP library.
|
To set the current time, you can use the POSIX functions ``settimeofday()`` and ``adjtime()``. They are used internally in the lwIP SNTP library to set current time when a response from the NTP server is received. These functions can also be used separately from the lwIP SNTP library.
|
||||||
|
|
||||||
The function to use inside the lwIP SNTP library depends on the sync mode for system time. Use the function :cpp:func:`sntp_set_sync_mode` to set one of the following sync modes:
|
Some lwIP APIs, including SNTP functions, are not thread safe, so it is recommended to use :doc:`esp_netif component <../network/esp_netif>` when interacting with SNTP module.
|
||||||
|
|
||||||
|
To initialize a particular SNTP server and also start the SNTP service, simply create a default SNTP server configuration with a particular server name, then call :cpp:func:`esp_netif_sntp_init()` to register that server and start the SNTP service.
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("pool.ntp.org");
|
||||||
|
esp_netif_sntp_init(&config);
|
||||||
|
|
||||||
|
This code automatically performs time synchronization once a reply from the SNTP server is received. Sometimes it is useful to wait until the time gets synchronized, :cpp:func:`esp_netif_sntp_sync_wait()` can be used for this purpose:
|
||||||
|
|
||||||
|
.. code-block:: c
|
||||||
|
|
||||||
|
if (esp_netif_sntp_sync_wait(pdMS_TO_TICKS(10000)) != ESP_OK) {
|
||||||
|
printf("Failed to update system time within 10s timeout");
|
||||||
|
}
|
||||||
|
|
||||||
|
To configure multiple NTP servers (or use more advanced settings, such as DHCP provided NTP servers), please refer to the detailed description of :ref:`esp_netif-sntp-api` in :doc:`esp_netif <../network/esp_netif>` documentation.
|
||||||
|
|
||||||
|
The lwIP SNTP library could work in one of the following sync modes:
|
||||||
|
|
||||||
- :cpp:enumerator:`SNTP_SYNC_MODE_IMMED` (default): Updates system time immediately upon receiving a response from the SNTP server after using ``settimeofday()``.
|
- :cpp:enumerator:`SNTP_SYNC_MODE_IMMED` (default): Updates system time immediately upon receiving a response from the SNTP server after using ``settimeofday()``.
|
||||||
- :cpp:enumerator:`SNTP_SYNC_MODE_SMOOTH`: Updates time smoothly by gradually reducing time error using the function ``adjtime()``. If the difference between the SNTP response time and system time is more than 35 minutes, update system time immediately by using ``settimeofday()``.
|
- :cpp:enumerator:`SNTP_SYNC_MODE_SMOOTH`: Updates time smoothly by gradually reducing time error using the function ``adjtime()``. If the difference between the SNTP response time and system time is more than 35 minutes, update system time immediately by using ``settimeofday()``.
|
||||||
|
|
||||||
The lwIP SNTP library has API functions for setting a callback function for a certain event. You might need the following functions:
|
If you want to choose the :cpp:enumerator:`SNTP_SYNC_MODE_SMOOTH` mode, please set the :cpp:member:`esp_sntp_config::smooth` to ``true`` in the SNTP configuration struct. Otherwise (and by default) the :cpp:enumerator:`SNTP_SYNC_MODE_IMMED` mode will be used.
|
||||||
|
|
||||||
- :cpp:func:`sntp_set_time_sync_notification_cb()`: Can be used to set a callback function that will notify of the time synchronization process.
|
For setting a callback function when time gets synchronized, use the :cpp:member:`esp_sntp_config::sync_cb` field in the configuration struct.
|
||||||
- :cpp:func:`sntp_get_sync_status()` and :cpp:func:`sntp_set_sync_status()`: Can be used to get/set time synchronization status.
|
|
||||||
|
|
||||||
To start synchronization via SNTP, just call the following three functions:
|
|
||||||
|
|
||||||
.. code-block:: c
|
|
||||||
|
|
||||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
|
||||||
sntp_setservername(0, "pool.ntp.org");
|
|
||||||
sntp_init();
|
|
||||||
|
|
||||||
An application with this initialization code will periodically synchronize the time. The time synchronization period is determined by :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` (the default value is one hour). To modify the variable, set :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` in project configuration.
|
An application with this initialization code will periodically synchronize the time. The time synchronization period is determined by :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` (the default value is one hour). To modify the variable, set :ref:`CONFIG_LWIP_SNTP_UPDATE_DELAY` in project configuration.
|
||||||
|
|
||||||
A code example that demonstrates the implementation of time synchronization based on the lwIP SNTP library is provided in the :example:`protocols/sntp` directory.
|
A code example that demonstrates the implementation of time synchronization based on the lwIP SNTP library is provided in the :example:`protocols/sntp` directory.
|
||||||
|
|
||||||
|
Note that it's also possible to use lwIP API directly, but care must be taken to thread safety. Here we list the thread-safe APIs:
|
||||||
|
|
||||||
|
- :cpp:func:`sntp_set_time_sync_notification_cb()`: Can be used to set a callback function that will notify of the time synchronization process.
|
||||||
|
- :cpp:func:`sntp_get_sync_status()` and :cpp:func:`sntp_set_sync_status()`: Can be used to get/set time synchronization status.
|
||||||
|
- :cpp:func:`sntp_set_sync_mode` can be used to set the synchronization mode
|
||||||
|
- :cpp:func:`esp_sntp_setoperatingmode` sets the preferred operating mode :cpp:enumerator:`ESP_SNTP_OPMODE_POLL` and :cpp:func:`esp_sntp_init` initializes SNTP modeule
|
||||||
|
- :cpp:func:`esp_sntp_setservername` configures one SNTP server
|
||||||
|
|
||||||
|
|
||||||
Timezones
|
Timezones
|
||||||
---------
|
---------
|
||||||
|
@ -7,3 +7,4 @@ Migration from 5.0 to 5.1
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
peripherals
|
peripherals
|
||||||
|
networking
|
||||||
|
9
docs/en/migration-guides/release-5.x/5.1/networking.rst
Normal file
9
docs/en/migration-guides/release-5.x/5.1/networking.rst
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
Networking
|
||||||
|
===========
|
||||||
|
|
||||||
|
:link_to_translation:`zh_CN:[中文]`
|
||||||
|
|
||||||
|
SNTP
|
||||||
|
----
|
||||||
|
|
||||||
|
SNTP module now provides thread safe APIs to access lwIP functionality. It's recommended to use :doc:`ESP_NETIF </api-reference/network/esp_netif>` API. Please refer to the chapter :ref:`esp_netif-sntp-api` for more details.
|
@ -7,3 +7,4 @@
|
|||||||
:maxdepth: 1
|
:maxdepth: 1
|
||||||
|
|
||||||
peripherals
|
peripherals
|
||||||
|
networking
|
||||||
|
@ -0,0 +1,9 @@
|
|||||||
|
网络
|
||||||
|
===========
|
||||||
|
|
||||||
|
:link_to_translation:`en:[English]`
|
||||||
|
|
||||||
|
SNTP
|
||||||
|
*****
|
||||||
|
|
||||||
|
请参考章节 :ref:`esp_netif-sntp-api` 了解更多详情。
|
@ -1,6 +1,7 @@
|
|||||||
## IDF Component Manager Manifest File
|
## IDF Component Manager Manifest File
|
||||||
dependencies:
|
dependencies:
|
||||||
espressif/esp_ot_cli_extension: "~0.2.0"
|
espressif/esp_ot_cli_extension:
|
||||||
|
version: "~0.3.0"
|
||||||
espressif/mdns: "^1.0.3"
|
espressif/mdns: "^1.0.3"
|
||||||
## Required IDF version
|
## Required IDF version
|
||||||
idf:
|
idf:
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
## IDF Component Manager Manifest File
|
## IDF Component Manager Manifest File
|
||||||
dependencies:
|
dependencies:
|
||||||
espressif/esp_ot_cli_extension: "~0.2.0"
|
espressif/esp_ot_cli_extension:
|
||||||
|
version: "~0.3.0"
|
||||||
idf:
|
idf:
|
||||||
version: ">=4.1.0"
|
version: ">=4.1.0"
|
||||||
|
@ -17,11 +17,11 @@
|
|||||||
#include "freertos/task.h"
|
#include "freertos/task.h"
|
||||||
#include "esp_wifi.h"
|
#include "esp_wifi.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "lwip/apps/sntp.h"
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "protocol_examples_common.h"
|
#include "protocol_examples_common.h"
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_sntp.h"
|
||||||
#include "sdkconfig.h"
|
#include "sdkconfig.h"
|
||||||
|
|
||||||
#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
|
#if CONFIG_MBEDTLS_CERTIFICATE_BUNDLE
|
||||||
@ -90,8 +90,12 @@ static void set_time(void)
|
|||||||
settimeofday(&tv, &tz);
|
settimeofday(&tv, &tz);
|
||||||
|
|
||||||
/* Start SNTP service */
|
/* Start SNTP service */
|
||||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG("time.windows.com");
|
||||||
sntp_init();
|
esp_netif_sntp_init(&config);
|
||||||
|
if (esp_netif_sntp_sync_wait(pdMS_TO_TICKS(10000)) != ESP_OK) {
|
||||||
|
printf("Failed to update system time, continuing");
|
||||||
|
}
|
||||||
|
esp_netif_deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
static void http2_task(void *args)
|
static void http2_task(void *args)
|
||||||
|
@ -16,8 +16,8 @@
|
|||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "nvs.h"
|
#include "nvs.h"
|
||||||
#include "esp_sntp.h"
|
|
||||||
#include "esp_netif.h"
|
#include "esp_netif.h"
|
||||||
|
#include "esp_netif_sntp.h"
|
||||||
|
|
||||||
#include "lwip/err.h"
|
#include "lwip/err.h"
|
||||||
#include "lwip/sockets.h"
|
#include "lwip/sockets.h"
|
||||||
@ -33,31 +33,18 @@ static const char *TAG = "time_sync";
|
|||||||
void initialize_sntp(void)
|
void initialize_sntp(void)
|
||||||
{
|
{
|
||||||
ESP_LOGI(TAG, "Initializing SNTP");
|
ESP_LOGI(TAG, "Initializing SNTP");
|
||||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(2,
|
||||||
sntp_setservername(0, "time.windows.com");
|
ESP_SNTP_SERVER_LIST("time.windows.com", "pool.ntp.org" ) );
|
||||||
sntp_setservername(1, "pool.ntp.org");
|
esp_netif_sntp_init(&config);
|
||||||
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
|
|
||||||
sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
|
|
||||||
#endif
|
|
||||||
sntp_init();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static esp_err_t obtain_time(void)
|
static esp_err_t obtain_time(void)
|
||||||
{
|
{
|
||||||
/**
|
|
||||||
* NTP server address could be aquired via DHCP,
|
|
||||||
* see LWIP_DHCP_GET_NTP_SRV menuconfig option
|
|
||||||
*/
|
|
||||||
#ifdef LWIP_DHCP_GET_NTP_SRV
|
|
||||||
sntp_servermode_dhcp(1);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
// wait for time to be set
|
// wait for time to be set
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
const int retry_count = 10;
|
const int retry_count = 10;
|
||||||
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
|
while (esp_netif_sntp_sync_wait(pdMS_TO_TICKS(2000)) != ESP_OK && ++retry < retry_count) {
|
||||||
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
|
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
|
||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
|
||||||
}
|
}
|
||||||
if (retry == retry_count) {
|
if (retry == retry_count) {
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
@ -96,7 +83,7 @@ esp_err_t fetch_and_store_time_in_nvs(void *args)
|
|||||||
}
|
}
|
||||||
|
|
||||||
nvs_close(my_handle);
|
nvs_close(my_handle);
|
||||||
sntp_stop();
|
esp_netif_deinit();
|
||||||
|
|
||||||
exit:
|
exit:
|
||||||
if (err != ESP_OK) {
|
if (err != ESP_OK) {
|
||||||
|
@ -19,3 +19,4 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
|||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=y
|
||||||
|
@ -9,3 +9,5 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
|||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||||
|
CONFIG_LWIP_TCPIP_CORE_LOCKING=y
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=y
|
||||||
|
@ -8,3 +8,4 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
|||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=y
|
||||||
|
@ -9,3 +9,5 @@ CONFIG_EXAMPLE_ETH_MDIO_GPIO=18
|
|||||||
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
CONFIG_EXAMPLE_ETH_PHY_RST_GPIO=5
|
||||||
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
||||||
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
CONFIG_EXAMPLE_CONNECT_IPV6=y
|
||||||
|
CONFIG_LWIP_TCPIP_CORE_LOCKING=y
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=y
|
||||||
|
@ -9,10 +9,6 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <sys/time.h>
|
#include <sys/time.h>
|
||||||
#include <netdb.h>
|
|
||||||
#include "freertos/FreeRTOS.h"
|
|
||||||
#include "freertos/task.h"
|
|
||||||
#include "freertos/event_groups.h"
|
|
||||||
#include "esp_system.h"
|
#include "esp_system.h"
|
||||||
#include "esp_event.h"
|
#include "esp_event.h"
|
||||||
#include "esp_log.h"
|
#include "esp_log.h"
|
||||||
@ -20,6 +16,8 @@
|
|||||||
#include "esp_sleep.h"
|
#include "esp_sleep.h"
|
||||||
#include "nvs_flash.h"
|
#include "nvs_flash.h"
|
||||||
#include "protocol_examples_common.h"
|
#include "protocol_examples_common.h"
|
||||||
|
#include "esp_netif_sntp.h"
|
||||||
|
#include "lwip/ip_addr.h"
|
||||||
#include "esp_sntp.h"
|
#include "esp_sntp.h"
|
||||||
|
|
||||||
static const char *TAG = "example";
|
static const char *TAG = "example";
|
||||||
@ -35,7 +33,6 @@ static const char *TAG = "example";
|
|||||||
RTC_DATA_ATTR static int boot_count = 0;
|
RTC_DATA_ATTR static int boot_count = 0;
|
||||||
|
|
||||||
static void obtain_time(void);
|
static void obtain_time(void);
|
||||||
static void initialize_sntp(void);
|
|
||||||
|
|
||||||
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_CUSTOM
|
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_CUSTOM
|
||||||
void sntp_sync_time(struct timeval *tv)
|
void sntp_sync_time(struct timeval *tv)
|
||||||
@ -121,24 +118,55 @@ void app_main(void)
|
|||||||
esp_deep_sleep(1000000LL * deep_sleep_sec);
|
esp_deep_sleep(1000000LL * deep_sleep_sec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void print_servers(void)
|
||||||
|
{
|
||||||
|
ESP_LOGI(TAG, "List of configured NTP servers:");
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i){
|
||||||
|
if (esp_sntp_getservername(i)){
|
||||||
|
ESP_LOGI(TAG, "server %d: %s", i, esp_sntp_getservername(i));
|
||||||
|
} else {
|
||||||
|
// we have either IPv4 or IPv6 address, let's print it
|
||||||
|
char buff[INET6_ADDRSTRLEN];
|
||||||
|
ip_addr_t const *ip = esp_sntp_getserver(i);
|
||||||
|
if (ipaddr_ntoa_r(ip, buff, INET6_ADDRSTRLEN) != NULL)
|
||||||
|
ESP_LOGI(TAG, "server %d: %s", i, buff);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static void obtain_time(void)
|
static void obtain_time(void)
|
||||||
{
|
{
|
||||||
ESP_ERROR_CHECK( nvs_flash_init() );
|
ESP_ERROR_CHECK( nvs_flash_init() );
|
||||||
ESP_ERROR_CHECK(esp_netif_init());
|
ESP_ERROR_CHECK(esp_netif_init());
|
||||||
ESP_ERROR_CHECK( esp_event_loop_create_default() );
|
ESP_ERROR_CHECK( esp_event_loop_create_default() );
|
||||||
|
|
||||||
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
/**
|
/**
|
||||||
* NTP server address could be aquired via DHCP,
|
* NTP server address could be acquired via DHCP,
|
||||||
* see following menuconfig options:
|
* see following menuconfig options:
|
||||||
* 'LWIP_DHCP_GET_NTP_SRV' - enable STNP over DHCP
|
* 'LWIP_DHCP_GET_NTP_SRV' - enable STNP over DHCP
|
||||||
* 'LWIP_SNTP_DEBUG' - enable debugging messages
|
* 'LWIP_SNTP_DEBUG' - enable debugging messages
|
||||||
*
|
*
|
||||||
* NOTE: This call should be made BEFORE esp aquires IP address from DHCP,
|
* NOTE: This call should be made BEFORE esp acquires IP address from DHCP,
|
||||||
* otherwise NTP option would be rejected by default.
|
* otherwise NTP option would be rejected by default.
|
||||||
*/
|
*/
|
||||||
#ifdef LWIP_DHCP_GET_NTP_SRV
|
ESP_LOGI(TAG, "Initializing SNTP");
|
||||||
sntp_servermode_dhcp(1); // accept NTP offers from DHCP server, if any
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG(CONFIG_SNTP_TIME_SERVER);
|
||||||
|
config.start = false; // start SNTP service explicitly (after connecting)
|
||||||
|
config.server_from_dhcp = true; // accept NTP offers from DHCP server, if any (need to enable *before* connecting)
|
||||||
|
config.renew_servers_after_new_IP = true; // let esp-netif update configured SNTP server(s) after receiving DHCP lease
|
||||||
|
config.index_of_first_server = 1; // updates from server num 1, leaving server 0 (from DHCP) intact
|
||||||
|
// configure the event on which we renew servers
|
||||||
|
#ifdef CONFIG_EXAMPLE_CONNECT_WIFI
|
||||||
|
config.ip_event_to_renew = IP_EVENT_STA_GOT_IP;
|
||||||
|
#else
|
||||||
|
config.ip_event_to_renew = IP_EVENT_ETH_GOT_IP;
|
||||||
#endif
|
#endif
|
||||||
|
config.sync_cb = time_sync_notification_cb; // only if we need the notification function
|
||||||
|
esp_netif_sntp_init(&config);
|
||||||
|
|
||||||
|
#endif /* LWIP_DHCP_GET_NTP_SRV */
|
||||||
|
|
||||||
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
/* This helper function configures Wi-Fi or Ethernet, as selected in menuconfig.
|
||||||
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
* Read "Establishing Wi-Fi or Ethernet Connection" section in
|
||||||
@ -146,67 +174,53 @@ static void obtain_time(void)
|
|||||||
*/
|
*/
|
||||||
ESP_ERROR_CHECK(example_connect());
|
ESP_ERROR_CHECK(example_connect());
|
||||||
|
|
||||||
initialize_sntp();
|
#if LWIP_DHCP_GET_NTP_SRV
|
||||||
|
ESP_LOGI(TAG, "Starting SNTP");
|
||||||
|
esp_netif_sntp_start();
|
||||||
|
#if LWIP_IPV6 && SNTP_MAX_SERVERS > 2
|
||||||
|
/* This demonstrates using IPv6 address as an additional SNTP server
|
||||||
|
* (statically assigned IPv6 address is also possible)
|
||||||
|
*/
|
||||||
|
ip_addr_t ip6;
|
||||||
|
if (ipaddr_aton("2a01:3f7::1", &ip6)) { // ipv6 ntp source "ntp.netnod.se"
|
||||||
|
esp_sntp_setserver(2, &ip6);
|
||||||
|
}
|
||||||
|
#endif /* LWIP_IPV6 */
|
||||||
|
|
||||||
|
#else
|
||||||
|
ESP_LOGI(TAG, "Initializing and starting SNTP");
|
||||||
|
#if CONFIG_LWIP_SNTP_MAX_SERVERS > 1
|
||||||
|
/* This demonstrates configuring more than one server
|
||||||
|
*/
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG_MULTIPLE(2,
|
||||||
|
ESP_SNTP_SERVER_LIST(CONFIG_SNTP_TIME_SERVER, "pool.ntp.org" ) );
|
||||||
|
#else
|
||||||
|
/*
|
||||||
|
* This is the basic default config with one server and starting the service
|
||||||
|
*/
|
||||||
|
esp_sntp_config_t config = ESP_NETIF_SNTP_DEFAULT_CONFIG(CONFIG_SNTP_TIME_SERVER);
|
||||||
|
#endif
|
||||||
|
config.sync_cb = time_sync_notification_cb; // Note: This is only needed if we want
|
||||||
|
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
|
||||||
|
config.smooth_sync = true;
|
||||||
|
#endif
|
||||||
|
|
||||||
|
esp_netif_sntp_init(&config);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
print_servers();
|
||||||
|
|
||||||
// wait for time to be set
|
// wait for time to be set
|
||||||
time_t now = 0;
|
time_t now = 0;
|
||||||
struct tm timeinfo = { 0 };
|
struct tm timeinfo = { 0 };
|
||||||
int retry = 0;
|
int retry = 0;
|
||||||
const int retry_count = 15;
|
const int retry_count = 15;
|
||||||
while (sntp_get_sync_status() == SNTP_SYNC_STATUS_RESET && ++retry < retry_count) {
|
while (esp_netif_sntp_sync_wait(2000 / portTICK_PERIOD_MS) == ESP_ERR_TIMEOUT && ++retry < retry_count) {
|
||||||
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
|
ESP_LOGI(TAG, "Waiting for system time to be set... (%d/%d)", retry, retry_count);
|
||||||
vTaskDelay(2000 / portTICK_PERIOD_MS);
|
|
||||||
}
|
}
|
||||||
time(&now);
|
time(&now);
|
||||||
localtime_r(&now, &timeinfo);
|
localtime_r(&now, &timeinfo);
|
||||||
|
|
||||||
ESP_ERROR_CHECK( example_disconnect() );
|
ESP_ERROR_CHECK( example_disconnect() );
|
||||||
}
|
esp_netif_sntp_deinit();
|
||||||
|
|
||||||
static void initialize_sntp(void)
|
|
||||||
{
|
|
||||||
ESP_LOGI(TAG, "Initializing SNTP");
|
|
||||||
sntp_setoperatingmode(SNTP_OPMODE_POLL);
|
|
||||||
|
|
||||||
/*
|
|
||||||
* If 'NTP over DHCP' is enabled, we set dynamic pool address
|
|
||||||
* as a 'secondary' server. It will act as a fallback server in case that address
|
|
||||||
* provided via NTP over DHCP is not accessible
|
|
||||||
*/
|
|
||||||
#if LWIP_DHCP_GET_NTP_SRV && SNTP_MAX_SERVERS > 1
|
|
||||||
sntp_setservername(1, "pool.ntp.org");
|
|
||||||
|
|
||||||
#if LWIP_IPV6 && SNTP_MAX_SERVERS > 2 // statically assigned IPv6 address is also possible
|
|
||||||
ip_addr_t ip6;
|
|
||||||
if (ipaddr_aton("2a01:3f7::1", &ip6)) { // ipv6 ntp source "ntp.netnod.se"
|
|
||||||
sntp_setserver(2, &ip6);
|
|
||||||
}
|
|
||||||
#endif /* LWIP_IPV6 */
|
|
||||||
|
|
||||||
#else /* LWIP_DHCP_GET_NTP_SRV && (SNTP_MAX_SERVERS > 1) */
|
|
||||||
// otherwise, use DNS address from a pool
|
|
||||||
sntp_setservername(0, CONFIG_SNTP_TIME_SERVER);
|
|
||||||
|
|
||||||
sntp_setservername(1, "pool.ntp.org"); // set the secondary NTP server (will be used only if SNTP_MAX_SERVERS > 1)
|
|
||||||
#endif
|
|
||||||
|
|
||||||
sntp_set_time_sync_notification_cb(time_sync_notification_cb);
|
|
||||||
#ifdef CONFIG_SNTP_TIME_SYNC_METHOD_SMOOTH
|
|
||||||
sntp_set_sync_mode(SNTP_SYNC_MODE_SMOOTH);
|
|
||||||
#endif
|
|
||||||
sntp_init();
|
|
||||||
|
|
||||||
ESP_LOGI(TAG, "List of configured NTP servers:");
|
|
||||||
|
|
||||||
for (uint8_t i = 0; i < SNTP_MAX_SERVERS; ++i){
|
|
||||||
if (sntp_getservername(i)){
|
|
||||||
ESP_LOGI(TAG, "server %d: %s", i, sntp_getservername(i));
|
|
||||||
} else {
|
|
||||||
// we have either IPv4 or IPv6 address, let's print it
|
|
||||||
char buff[INET6_ADDRSTRLEN];
|
|
||||||
ip_addr_t const *ip = sntp_getserver(i);
|
|
||||||
if (ipaddr_ntoa_r(ip, buff, INET6_ADDRSTRLEN) != NULL)
|
|
||||||
ESP_LOGI(TAG, "server %d: %s", i, buff);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -22,7 +22,7 @@ def test_get_time_from_sntp_server(dut: Dut) -> None:
|
|||||||
dut.write(f'{ap_ssid} {ap_password}')
|
dut.write(f'{ap_ssid} {ap_password}')
|
||||||
dut.expect('IPv4 address:')
|
dut.expect('IPv4 address:')
|
||||||
|
|
||||||
dut.expect('Initializing SNTP')
|
dut.expect('Initializing and starting SNTP')
|
||||||
dut.expect(r'Waiting for system time to be set... \(\d+/\d+\)')
|
dut.expect(r'Waiting for system time to be set... \(\d+/\d+\)')
|
||||||
dut.expect('Notification of a time synchronization event')
|
dut.expect('Notification of a time synchronization event')
|
||||||
|
|
||||||
|
@ -15,3 +15,4 @@ CONFIG_EXAMPLE_ETH_PHY_ADDR=1
|
|||||||
CONFIG_MBEDTLS_TLS_CLIENT_ONLY=y
|
CONFIG_MBEDTLS_TLS_CLIENT_ONLY=y
|
||||||
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
CONFIG_COMPILER_OPTIMIZATION_SIZE=y
|
||||||
CONFIG_EXAMPLE_CONNECT_IPV6=n
|
CONFIG_EXAMPLE_CONNECT_IPV6=n
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=y
|
||||||
|
@ -437,7 +437,6 @@ components/esp_local_ctrl/src/esp_local_ctrl_handler.c
|
|||||||
components/esp_local_ctrl/src/esp_local_ctrl_priv.h
|
components/esp_local_ctrl/src/esp_local_ctrl_priv.h
|
||||||
components/esp_local_ctrl/src/esp_local_ctrl_transport_ble.c
|
components/esp_local_ctrl/src/esp_local_ctrl_transport_ble.c
|
||||||
components/esp_netif/include/esp_netif_ppp.h
|
components/esp_netif/include/esp_netif_ppp.h
|
||||||
components/esp_netif/private_include/esp_netif_private.h
|
|
||||||
components/esp_netif/test/test_esp_netif.c
|
components/esp_netif/test/test_esp_netif.c
|
||||||
components/esp_netif/test_apps/component_ut_test.py
|
components/esp_netif/test_apps/component_ut_test.py
|
||||||
components/esp_netif/test_apps/main/esp_netif_test.c
|
components/esp_netif/test_apps/main/esp_netif_test.c
|
||||||
@ -724,7 +723,6 @@ components/lwip/apps/ping/ping.c
|
|||||||
components/lwip/include/apps/dhcpserver/dhcpserver_options.h
|
components/lwip/include/apps/dhcpserver/dhcpserver_options.h
|
||||||
components/lwip/include/apps/esp_ping.h
|
components/lwip/include/apps/esp_ping.h
|
||||||
components/lwip/include/apps/ping/ping.h
|
components/lwip/include/apps/ping/ping.h
|
||||||
components/lwip/include/apps/sntp/sntp.h
|
|
||||||
components/lwip/port/esp32/debug/lwip_debug.c
|
components/lwip/port/esp32/debug/lwip_debug.c
|
||||||
components/lwip/port/esp32/freertos/sys_arch.c
|
components/lwip/port/esp32/freertos/sys_arch.c
|
||||||
components/lwip/port/esp32/hooks/tcp_isn_default.c
|
components/lwip/port/esp32/hooks/tcp_isn_default.c
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
TEST_COMPONENTS=mqtt
|
TEST_COMPONENTS=mqtt
|
||||||
CONFIG_MQTT_PROTOCOL_5=y
|
CONFIG_MQTT_PROTOCOL_5=y
|
||||||
CONFIG_MQTT5_TEST_BROKER_URI="mqtt://${EXAMPLE_MQTTV5_BROKER_TCP}"
|
CONFIG_MQTT5_TEST_BROKER_URI="mqtt://${EXAMPLE_MQTTV5_BROKER_TCP}"
|
||||||
|
CONFIG_LWIP_TCPIP_CORE_LOCKING=y
|
||||||
|
CONFIG_LWIP_CHECK_THREAD_SAFETY=y
|
||||||
|
Loading…
Reference in New Issue
Block a user