Page 9 of 11
Article Index
Page 176 SNTP RTC main program
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "lwip/pbuf.h"
#include "lwip/udp.h"
#include "setupWifi.h"
#include "hardware/rtc.h"
#include "time.h"
#include "lwip/dns.h"
bool getDateNow(struct tm *t)
{
datetime_t rtc;
bool state = rtc_get_datetime(&rtc);
if (state)
{
t->tm_sec = rtc.sec;
t->tm_min = rtc.min;
t->tm_hour = rtc.hour;
t->tm_mday = rtc.day;
t->tm_mon = rtc.month - 1;
t->tm_year = rtc.year - 1900;
t->tm_wday = rtc.dotw;
t->tm_yday = 0;
t->tm_isdst = -1;
}
return state;
}
void setRTC(struct tm *datetime)
{
datetime_t t;
t.year = datetime->tm_year + 1900;
t.month = datetime->tm_mon + 1;
t.day = datetime->tm_mday;
t.dotw = datetime->tm_wday;
t.hour = datetime->tm_hour;
t.min = datetime->tm_min;
t.sec = datetime->tm_sec;
rtc_init();
rtc_set_datetime(&t);
}
struct timeStatus
{
bool ready;
struct udp_pcb *pcb;
};
void recv(void *arg, struct udp_pcb *pcb, struct pbuf *p, const ip_addr_t *addr, u16_t port)
{
struct timeStatus *tstatus = (struct timeStatus *)arg;
printf("SNTP responded\n");
if (p != NULL)
{
uint8_t seconds_buf[4];
pbuf_copy_partial(p, seconds_buf, sizeof(seconds_buf), 40);
uint32_t seconds_since_1900 = seconds_buf[0] << 24 | seconds_buf[1] << 16 | seconds_buf[2] << 8 | seconds_buf[3];
time_t seconds_since_1970 = seconds_since_1900 - 2208988800;
struct tm *datetime = gmtime(&seconds_since_1970);
setRTC(datetime);
pbuf_free(p);
udp_remove(pcb);
tstatus->pcb=NULL;
tstatus->ready = true;
}
}
bool pollSNTP(struct timeStatus *tstatus)
{
if (tstatus == NULL)
return true;
if (tstatus->ready)
{
free(tstatus);
tstatus = NULL;
return true;
}
return false;
}
void dns_found(const char *name, const ip_addr_t *ip, void *arg)
{
struct timeStatus *tstatus = (struct timeStatus *)arg;
printf("DNS %s\n", ipaddr_ntoa(ip));
struct udp_pcb *pcb = udp_new();
tstatus->pcb = pcb;
udp_recv(pcb, recv, arg);
udp_bind(pcb, IP_ADDR_ANY, 123);
udp_connect(pcb, ip, 123);
struct pbuf *p = pbuf_alloc(PBUF_TRANSPORT, 48, PBUF_RAM);
uint8_t *payload = (uint8_t *)p->payload;
memset(payload, 0, 48);
*payload = 0x1b;
err_t er = udp_send(pcb, p);
pbuf_free(p);
}
struct timeStatus *getSNTP()
{
struct timeStatus *tstatus = malloc(sizeof(struct timeStatus));
tstatus->ready = false;
tstatus->pcb=NULL;
ip_addr_t ip;
cyw43_arch_lwip_begin();
err_t err = dns_gethostbyname("time.nist.gov", &ip, dns_found, tstatus);
cyw43_arch_lwip_end();
if (err == ERR_OK)
{
printf("DNS cache %s\n", ipaddr_ntoa(&ip));
dns_found("", &ip, tstatus);
}
return tstatus;
}
void cancelSNTP(struct timeStatus *tstatus)
{
if (tstatus != NULL)
{
udp_remove(tstatus->pcb);
free(tstatus);
tstatus = NULL;
printf("canceled\n");
}
}
int main()
{
stdio_init_all();
connect();
while (true)
{
struct timeStatus *tstatus = getSNTP();
sleep_ms(500);
if (pollSNTP(tstatus))
break;
cancelSNTP(tstatus);
}
while (true)
{
struct tm t;
getDateNow(&t);
char Date[100];
strftime(Date, sizeof(Date), "Date: %a, %d %b %Y %k:%M:%S %Z\r\n", &t);
printf("%s\n", Date);
sleep_ms(5000);
}
}
Page 182 SNTP RTC App main program
#include <stdio.h>
#include "pico/stdlib.h"
#include "pico/cyw43_arch.h"
#include "setupWifi.h"
#include "hardware/rtc.h"
#include <time.h>
#include "lwip/apps/sntp.h"
void SNTPSetRTC(u32_t t, u32_t us)
{
printf("updating RTC\n");
time_t seconds_since_1970 = t - 2208988800;
struct tm *datetime = gmtime(&seconds_since_1970);
datetime_t dt;
dt.year = datetime->tm_year + 1900;
dt.month = datetime->tm_mon + 1;
dt.day = datetime->tm_mday;
dt.dotw = datetime->tm_wday;
dt.hour = datetime->tm_hour;
dt.min = datetime->tm_min;
dt.sec = datetime->tm_sec;
rtc_init();
rtc_set_datetime(&dt);
}
bool getDateNow(struct tm *t)
{
datetime_t rtc;
bool state = rtc_get_datetime(&rtc);
if (state)
{
t->tm_sec = rtc.sec;
t->tm_min = rtc.min;
t->tm_hour = rtc.hour;
t->tm_mday = rtc.day;
t->tm_mon = rtc.month - 1;
t->tm_year = rtc.year - 1900;
t->tm_wday = rtc.dotw;
t->tm_yday = 0;
t->tm_isdst = -1;
}
return state;
}
int main()
{
stdio_init_all();
connect();
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, "pool.ntp.org");
sntp_init();
while (true)
{
struct tm t;
if (getDateNow(&t)) {
char Date[100];
strftime(Date, sizeof(Date), "Date: %a, %d %b %Y %k:%M:%S %Z\r\n", &t);
printf("%s\n", Date);
}
sleep_ms(5000);
}
}
Page 183 Full listing not in book
SNTP RTC app lwipopts.h
#ifndef _LWIPOPTS_EXAMPLE_COMMONH_H
#define _LWIPOPTS_EXAMPLE_COMMONH_H
// Common settings used in most of the pico_w examples
// (see https://www.nongnu.org/lwip/2_1_x/group__lwip__opts.html for details)
// allow override in some examples
#ifndef NO_SYS
#define NO_SYS 1
#endif
// allow override in some examples
#ifndef LWIP_SOCKET
#define LWIP_SOCKET 0
#endif
#if PICO_CYW43_ARCH_POLL
#define MEM_LIBC_MALLOC 1
#else
// MEM_LIBC_MALLOC is incompatible with non polling versions
#define MEM_LIBC_MALLOC 0
#endif
#define MEM_ALIGNMENT 4
#define MEM_SIZE 4000
#define MEMP_NUM_TCP_SEG 32
#define MEMP_NUM_ARP_QUEUE 10
#define PBUF_POOL_SIZE 24
#define LWIP_ARP 1
#define LWIP_ETHERNET 1
#define LWIP_ICMP 1
#define LWIP_RAW 1
#define TCP_WND (8 * TCP_MSS)
#define TCP_MSS 1460
#define TCP_SND_BUF (8 * TCP_MSS)
#define TCP_SND_QUEUELEN ((4 * (TCP_SND_BUF) + (TCP_MSS - 1)) / (TCP_MSS))
#define LWIP_NETIF_STATUS_CALLBACK 1
#define LWIP_NETIF_LINK_CALLBACK 1
#define LWIP_NETIF_HOSTNAME 1
#define LWIP_NETCONN 0
#define MEM_STATS 0
#define SYS_STATS 0
#define MEMP_STATS 0
#define LINK_STATS 0
// #define ETH_PAD_SIZE 2
#define LWIP_CHKSUM_ALGORITHM 3
#define LWIP_DHCP 1
#define LWIP_IPV4 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DNS 1
#define LWIP_TCP_KEEPALIVE 1
#define LWIP_NETIF_TX_SINGLE_PBUF 1
#define DHCP_DOES_ARP_CHECK 0
#define LWIP_DHCP_DOES_ACD_CHECK 0
#ifndef NDEBUG
#define LWIP_DEBUG 1
#define LWIP_STATS 1
#define LWIP_STATS_DISPLAY 1
#endif
#define ETHARP_DEBUG LWIP_DBG_OFF
#define NETIF_DEBUG LWIP_DBG_OFF
#define PBUF_DEBUG LWIP_DBG_OFF
#define API_LIB_DEBUG LWIP_DBG_OFF
#define API_MSG_DEBUG LWIP_DBG_OFF
#define SOCKETS_DEBUG LWIP_DBG_OFF
#define ICMP_DEBUG LWIP_DBG_OFF
#define INET_DEBUG LWIP_DBG_OFF
#define IP_DEBUG LWIP_DBG_OFF
#define IP_REASS_DEBUG LWIP_DBG_OFF
#define RAW_DEBUG LWIP_DBG_OFF
#define MEM_DEBUG LWIP_DBG_OFF
#define MEMP_DEBUG LWIP_DBG_OFF
#define SYS_DEBUG LWIP_DBG_OFF
#define TCP_DEBUG LWIP_DBG_OFF
#define TCP_INPUT_DEBUG LWIP_DBG_OFF
#define TCP_OUTPUT_DEBUG LWIP_DBG_OFF
#define TCP_RTO_DEBUG LWIP_DBG_OFF
#define TCP_CWND_DEBUG LWIP_DBG_OFF
#define TCP_WND_DEBUG LWIP_DBG_OFF
#define TCP_FR_DEBUG LWIP_DBG_OFF
#define TCP_QLEN_DEBUG LWIP_DBG_OFF
#define TCP_RST_DEBUG LWIP_DBG_OFF
#define UDP_DEBUG LWIP_DBG_OFF
#define TCPIP_DEBUG LWIP_DBG_OFF
#define PPP_DEBUG LWIP_DBG_OFF
#define SLIP_DEBUG LWIP_DBG_OFF
#define DHCP_DEBUG LWIP_DBG_OFF
#undef TCP_WND
#define TCP_WND 16384
#define SNTP_SERVER_DNS 1
#define SNTP_SUPPORT 1
#define SNTP_UPDATE_DELAY 60*1000
#define SNTP_SET_SYSTEM_TIME_NTP(sec, us) \
void SNTPSetRTC(u32_t, u32_t); \
SNTPSetRTC(sec, us)
#define LWIP_DEBUG 1
#endif /* __LWIPOPTS_H__ */
Page 184 Full listing not in book
SNTP RTC app CMakeLists.txt
cmake_minimum_required(VERSION 3.13)
set(PICO_BOARD pico_w)
set(CMAKE_C_STANDARD 11)
set(CMAKE_CXX_STANDARD 17)
include(pico_sdk_import.cmake)
project(PicoW C CXX ASM)
pico_sdk_init()
add_executable(main
main.c
)
target_include_directories(main PRIVATE ${CMAKE_CURRENT_LIST_DIR})
target_link_libraries(main pico_stdlib pico_cyw43_arch_lwip_threadsafe_background pico_lwip_sntp hardware_rtc)
pico_add_extra_outputs(main)