diff --git a/src/timekeeper.cpp b/src/timekeeper.cpp index 80f13a6c..2eb8024d 100644 --- a/src/timekeeper.cpp +++ b/src/timekeeper.cpp @@ -20,8 +20,6 @@ HardwareSerial IF482(2); // use UART #2 (#1 may be in use for serial GPS) Ticker timesyncer; -static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED; - void timeSync() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); } time_t timeProvider(void) { @@ -32,7 +30,7 @@ time_t timeProvider(void) { t = get_gpstime(); // fetch recent time from last NEMA record if (t) { #ifdef HAS_RTC - set_rtctime(t); // calibrate RTC + set_rtctime(t, do_mutex); // calibrate RTC #endif timeSource = _gps; timesyncer.attach(TIME_SYNC_INTERVAL * 60, timeSync); // regular repeat @@ -121,7 +119,6 @@ void timepulse_start(void) { // interrupt service routine triggered by either pps or esp32 hardware timer void IRAM_ATTR CLOCKIRQ(void) { - portENTER_CRITICAL_ISR(&mux); BaseType_t xHigherPriorityTaskWoken = pdFALSE; SyncToPPS(); // calibrates UTC systime and advances it +1, see microTime.h @@ -136,13 +133,12 @@ void IRAM_ATTR CLOCKIRQ(void) { #endif #endif - portEXIT_CRITICAL_ISR(&mux); - // yield only if we should if (xHigherPriorityTaskWoken) portYIELD_FROM_ISR(); } + // helper function to check plausibility of a time time_t timeIsValid(time_t const t) { // is it a time in the past? we use compile date to guess @@ -208,6 +204,7 @@ void clock_init(void) { assert(ClockTask); // has clock task started? } // clock_init + void clock_loop(void *taskparameter) { // ClockTask // caveat: don't use now() in this task, it will cause a race condition @@ -224,9 +221,8 @@ void clock_loop(void *taskparameter) { // ClockTask uint8_t *DCFpulse; // pointer on array with DCF pulse bits DCFpulse = DCF77_Frame(nextmin(t)); // load first DCF frame before start #elif defined HAS_IF482 - static TickType_t txDelay = - pdMS_TO_TICKS(1000 - 2) - tx_Ticks(IF482_FRAME_SIZE, HAS_IF482); - // 2ms margin for processing time + static TickType_t txDelay = pdMS_TO_TICKS(1000 - IF482_SYNC_FIXUP) - + tx_Ticks(IF482_FRAME_SIZE, HAS_IF482); #endif // output the next second's pulse after timepulse arrived @@ -246,7 +242,8 @@ void clock_loop(void *taskparameter) { // ClockTask last_printtime = t; -#ifdef HAS_LED1 +// pps blink on secondary LED if we have one +#ifdef HAS_TWO_LED if (led1_state) switch_LED1(LED_OFF); else diff --git a/src/timesync.cpp b/src/timesync.cpp index e90c2628..a3d9c8e7 100644 --- a/src/timesync.cpp +++ b/src/timesync.cpp @@ -119,10 +119,10 @@ void process_timesync_req(void *taskparameter) { time_offset_ms /= TIME_SYNC_SAMPLES; // calculate time offset with millisecond precision using time base - // of LMIC os, since we use LMIC's ostime_t txEnd as tx timestamp - time_offset_ms += milliseconds(osticks2ms(os_getTime())); + // of LMIC os, since we use LMIC's ostime_t txEnd as tx timestamp. // apply calibration factor for processing time - time_offset_ms += milliseconds(TIME_SYNC_FIXUP); + time_offset_ms += + milliseconds(osticks2ms(os_getTime())) + milliseconds(TIME_SYNC_FIXUP); // calculate absolute time in UTC epoch // convert to whole seconds, floor @@ -136,18 +136,26 @@ void process_timesync_req(void *taskparameter) { // adjust system time if (timeIsValid(time_to_set)) { - // wait until top of second - vTaskDelay(pdMS_TO_TICKS(1000 - time_to_set_fraction_msec)); - time_to_set++; // advance time 1 sec wait time +#ifdef HAS_RTC + // get and lock access to i2c before we start time sync + if (I2C_MUTEX_LOCK()) { +#endif + + // wait until top of second with 4ms precision + time_to_set++; // advance time 1 sec wait time + vTaskDelay(pdMS_TO_TICKS(1000 - time_to_set_fraction_msec)); + +#ifdef HAS_RTC + // set RTC time and, if he have, calibrate RTC_INT pulse on top of second + set_rtctime(time_to_set, no_mutex); + I2C_MUTEX_UNLOCK(); + } // release i2c bus access +#endif #if (!defined GPS_INT && !defined RTC_INT) - // sync esp32 hardware timer based pps to top of second + // sync pps timer to top of second timerRestart(ppsIRQ); // reset pps timer - CLOCKIRQ(); // fire clock pps interrupt - -#elif defined HAS_RTC - // calibrate RTC and RTC_INT pulse on top of second - set_rtctime(time_to_set); + CLOCKIRQ(); // fire clock pps #endif setTime(time_to_set); // set the time on top of second