Before moving on to HTTPS, a small diversion - SNTP.

It’s possible to use a real-time clock with the Raspberry Pi Pico. There are many options (for example the RV3028 Real-Time Clock Breakout by Pimoroni). But since we have the internet, why not get the time from there?

LwIP comes with an SNTP module. SNTP = Simple NTP. NTP = Network Time Protocol. Sounds promising.

First we add pico_lwip_sntp to the list of libraries. That’s not enough, though. The SNTP client calls a function to set the system time (it can also get the system time in order to maintain and improve the accuracy of the current time). The function is not a callback. Instead, the macro NTP_SET_SYSTEM_TIME is used.

The macro can be set in CMakeLists.txt:

add_definitions(
        -DSNTP_SERVER_DNS=1
        -DSNTP_SERVER_ADDRESS="pool.ntp.org"
        -DSNTP_SET_SYSTEM_TIME=set_system_time
        -DSNTP_STARTUP_DELAY=0
)

This also asks the SNTP client to resolve the host name “pool.ntp.org”, and not to use any startup delay. For some reason, using a delay with pico_cyw43_arch_lwip_poll doesn’t work for me (but I’m probably not going to spend to much time to understand why).

Then

#include "lwip/apps/sntp.h"

And

sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_init();

I’m not sure whether the operation mode is very critical. I also expected sntp_init() to be called first, but looking at the code, it checks the operation mode which means that it should already be set.

This makes the SNTP requests, and then, if successful, it calls the “callback”. I am using something like:

void set_system_time(uint32_t sec)
{
    time_t epoch = sec;
    struct tm *time = gmtime(&epoch);

    datetime_t datetime = {
            .year = (int16_t) (1900 + time->tm_year),
            .month = (int8_t) (time->tm_mon + 1),
            .day = (int8_t) time->tm_mday,
            .hour = (int8_t) time->tm_hour,
            .min = (int8_t) time->tm_min,
            .sec = (int8_t) time->tm_sec,
            .dotw = (int8_t) time->tm_wday,
    };

    rtc_set_datetime(&datetime);
}

Calling rtc_set_datetime requires an initial call to rtc_init(), otherwise weird things happen.

After that, it is possible to fetch the current time using rtc_get_datetime().

The SNTP client supports additional modes where it keeps updating the time according to the difference between the system time and the “real time”, but I’m not interested at the moment. Check SNTP_COMP_ROUNDTRIP and sntp_opts.h in general for more details.

That’s pretty much all I care about SNTP at this point, but for a project that’s going to run for a while (days or weeks), I will probably get back to the roundtrip settings.