Skip to content

Instantly share code, notes, and snippets.

@benpeoples
Created March 28, 2018 17:05
Show Gist options
  • Save benpeoples/015823ec94c57c19be74ebe9abf621ac to your computer and use it in GitHub Desktop.
Save benpeoples/015823ec94c57c19be74ebe9abf621ac to your computer and use it in GitHub Desktop.
ESP32 newlib patch for adjtime
100a101,146
> //// CHANGES TO MAKE ADJTIME EXIST
>
> static uint64_t get_time_since_boot(); // FIXME: Is there a better way to do this?
>
> // adjtime_start stores the start time of the slew
> // adjtime_total is how many microseconds total to slew
> // Maximum is 2^31 microseconds, or about 35 minutes.
> // Typically 500,000 microseconds max for NTP
> // Rate is the speed at which we add data.
> // Unix typical rate is 85 seconds per second
> // 6 = 64 seconds per second
> // 7 = 128 seconds per second
> // Caveats:
> // 1. time adjustment progress does not survive deep sleep, but a completed adjustment does.
> // 2. keep time adjustments shortish, 35 minutes would take 74 hours to adjust.
> static uint64_t adjtime_start = 0;
> static int32_t adjtime_total = 0;
> #define ADJTIME_RATE 7
>
> // Adjtime takes two timeval structs
> // delta is the tv to add or subtract from the clock
> // outdelta is a way to find out where we are in the process (currently unsupported)
> // Trivial example:
> //
> // struct timeval delta;
> //
> // delta.tv_sec = -1;
> // delta.tv_usec = 0;
> //
> // adjtime(&delta,NULL);
> // This removes 1 second from the clock.
> //
> int adjtime(const struct timeval *delta, struct timeval *outdelta)
> {
> if(delta == NULL)
> return 0;
>
> if(llabs((delta->tv_sec * 1000000L + delta->tv_usec)) > INT_MAX)
> return -1;
>
> adjtime_start = get_time_since_boot();
> adjtime_total = (delta->tv_sec * 1000000L + delta->tv_usec);
>
> return 0;
> }
>
104a151
> int64_t adjustment;
111a159,190
>
> if(adjtime_start > 0)
> {
> adjustment = (get_time_since_boot() - adjtime_start) >> ADJTIME_RATE;
> if(adjtime_total < 0)
> {
> if(adjustment >= -adjtime_total)
> {
> result = result + adjtime_total;
> set_boot_time(result);
> adjtime_start = 0;
> }
> else
> {
> result -= adjustment;
> }
> }
> else // if adjtime_total = 0 this also fires, but that's an infrequent case.
> {
> if(adjustment >= adjtime_total)
> {
> result = result + adjtime_total;
> set_boot_time(result);
> adjtime_start = 0;
> }
> else
> {
> result += adjustment;
> }
> }
> }
>
114c193,195
< #endif //defined(WITH_RTC) || defined(WITH_FRC)
---
> #endif //defined(WITH_RTC) || defined(WITH_FRC1)
>
> ///// END OF ADJTIME ADDS
268d348
<
@epareja2
Copy link

Hello, I'm trying to use the adjtime() function in an ESP32 using Arduino library, but this function has no real efect on time modification.

I found this repository but could you explain please how is it used and what exactly does?

Thank you.

@benpeoples
Copy link
Author

I have no idea what parts of esp-idf and newlib made it into the Arduino library. However, adjtime has been in the ESP-IDF newlib for at least 3 years now, so this shouldn't be necessary.

What this function does is allows NTP primarily to slowly tweak the real time clock from what it's currently set to to what NTP thinks it should be set to.

For instance, if NTP discovers that the clock is 1 second slow, over the course of 128 seconds it will add a little time continuously until the time is sync'd up. Except when you first connect to NTP, the offsets are usually much lower than 1 second (0.25 seconds is in fact rather large). This allows your system's real time clock to (1) always count forwards without noticeable jumps and (2) stay very close to NTP time all the time. The NTP client is usually written to look at the time delta and if it's larger than some amount, just jump the clock to be correct. For instance, if system time were off by an hour (3600 seconds), adjtime would take 5 days to correct the time, and that's... not great.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment