interrupt timing issues (not fully solved yet)
This commit is contained in:
parent
8de2ee0680
commit
54c6536349
@ -2,13 +2,9 @@
|
|||||||
#define _IF482_H
|
#define _IF482_H
|
||||||
|
|
||||||
#include "globals.h"
|
#include "globals.h"
|
||||||
#include "timekeeper.h"
|
|
||||||
|
|
||||||
#define IF482_FRAME_SIZE (17)
|
#define IF482_FRAME_SIZE (17)
|
||||||
|
|
||||||
extern HardwareSerial IF482;
|
|
||||||
|
|
||||||
void IF482_Pulse(time_t t);
|
|
||||||
String IRAM_ATTR IF482_Frame(time_t tt);
|
String IRAM_ATTR IF482_Frame(time_t tt);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -6,9 +6,10 @@
|
|||||||
#include "TimeLib.h"
|
#include "TimeLib.h"
|
||||||
#include "irqhandler.h"
|
#include "irqhandler.h"
|
||||||
|
|
||||||
#if(HAS_GPS)
|
#ifdef HAS_GPS
|
||||||
#include "gpsread.h"
|
#include "gpsread.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_IF482
|
#ifdef HAS_IF482
|
||||||
#include "if482.h"
|
#include "if482.h"
|
||||||
#elif defined HAS_DCF77
|
#elif defined HAS_DCF77
|
||||||
|
@ -84,18 +84,6 @@ not evaluated by model BU-190, use "F" instead for this model
|
|||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
HardwareSerial IF482(2); // use UART #2 (note: #1 may be in use for serial GPS)
|
|
||||||
|
|
||||||
// triggered by timepulse to send IF482 signal
|
|
||||||
void IF482_Pulse(time_t t) {
|
|
||||||
|
|
||||||
static const TickType_t txDelay =
|
|
||||||
pdMS_TO_TICKS(1000) - tx_Ticks(IF482_FRAME_SIZE, HAS_IF482);
|
|
||||||
|
|
||||||
vTaskDelay(txDelay); // wait until moment to fire
|
|
||||||
IF482.print(IF482_Frame(t + 1)); // note: if482 telegram for *next* second
|
|
||||||
}
|
|
||||||
|
|
||||||
String IRAM_ATTR IF482_Frame(time_t printTime) {
|
String IRAM_ATTR IF482_Frame(time_t printTime) {
|
||||||
|
|
||||||
time_t t = myTZ.toLocal(printTime);
|
time_t t = myTZ.toLocal(printTime);
|
||||||
|
@ -3,6 +3,8 @@
|
|||||||
// Local logging tag
|
// Local logging tag
|
||||||
static const char TAG[] = __FILE__;
|
static const char TAG[] = __FILE__;
|
||||||
|
|
||||||
|
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
// irq handler task, handles all our application level interrupts
|
// irq handler task, handles all our application level interrupts
|
||||||
void irqHandler(void *pvParameters) {
|
void irqHandler(void *pvParameters) {
|
||||||
|
|
||||||
@ -54,12 +56,13 @@ void irqHandler(void *pvParameters) {
|
|||||||
|
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
void IRAM_ATTR DisplayIRQ() {
|
void IRAM_ATTR DisplayIRQ() {
|
||||||
|
portENTER_CRITICAL_ISR(&mux);
|
||||||
BaseType_t xHigherPriorityTaskWoken;
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
xHigherPriorityTaskWoken = pdFALSE;
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits,
|
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits,
|
||||||
&xHigherPriorityTaskWoken);
|
&xHigherPriorityTaskWoken);
|
||||||
|
portEXIT_CRITICAL_ISR(&mux);
|
||||||
if (xHigherPriorityTaskWoken)
|
if (xHigherPriorityTaskWoken)
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
@ -67,11 +70,13 @@ void IRAM_ATTR DisplayIRQ() {
|
|||||||
|
|
||||||
#ifdef HAS_BUTTON
|
#ifdef HAS_BUTTON
|
||||||
void IRAM_ATTR ButtonIRQ() {
|
void IRAM_ATTR ButtonIRQ() {
|
||||||
|
portENTER_CRITICAL_ISR(&mux);
|
||||||
BaseType_t xHigherPriorityTaskWoken;
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
xHigherPriorityTaskWoken = pdFALSE;
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits,
|
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits,
|
||||||
&xHigherPriorityTaskWoken);
|
&xHigherPriorityTaskWoken);
|
||||||
|
portEXIT_CRITICAL_ISR(&mux);
|
||||||
|
|
||||||
if (xHigherPriorityTaskWoken)
|
if (xHigherPriorityTaskWoken)
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
|
@ -36,7 +36,7 @@ looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
|||||||
irqhandler 1 1 executes tasks triggered by timer irq
|
irqhandler 1 1 executes tasks triggered by timer irq
|
||||||
gpsloop 1 2 reads data from GPS via serial or i2c
|
gpsloop 1 2 reads data from GPS via serial or i2c
|
||||||
bmeloop 1 1 reads data from BME sensor via i2c
|
bmeloop 1 1 reads data from BME sensor via i2c
|
||||||
timesync_req 1 4 temporary task for processing time sync requests
|
timesync_req 1 2 temporary task for processing time sync requests
|
||||||
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
||||||
|
|
||||||
Low priority numbers denote low priority tasks.
|
Low priority numbers denote low priority tasks.
|
||||||
|
@ -14,8 +14,14 @@ static const char TAG[] = __FILE__;
|
|||||||
// symbol to display current time source
|
// symbol to display current time source
|
||||||
const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
|
const char timeSetSymbols[] = {'G', 'R', 'L', '?'};
|
||||||
|
|
||||||
|
#ifdef HAS_IF482
|
||||||
|
HardwareSerial IF482(2); // use UART #2 (#1 may be in use for serial GPS)
|
||||||
|
#endif
|
||||||
|
|
||||||
Ticker timesyncer;
|
Ticker timesyncer;
|
||||||
|
|
||||||
|
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
||||||
|
|
||||||
void timeSync() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
|
void timeSync() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
|
||||||
|
|
||||||
time_t timeProvider(void) {
|
time_t timeProvider(void) {
|
||||||
@ -115,18 +121,22 @@ void timepulse_start(void) {
|
|||||||
// interrupt service routine triggered by either pps or esp32 hardware timer
|
// interrupt service routine triggered by either pps or esp32 hardware timer
|
||||||
void IRAM_ATTR CLOCKIRQ(void) {
|
void IRAM_ATTR CLOCKIRQ(void) {
|
||||||
|
|
||||||
|
portENTER_CRITICAL_ISR(&mux);
|
||||||
BaseType_t xHigherPriorityTaskWoken;
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
SyncToPPS(); // calibrates UTC systime, see microTime.h
|
|
||||||
xHigherPriorityTaskWoken = pdFALSE;
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
SyncToPPS(); // calibrates UTC systime, see microTime.h
|
||||||
|
|
||||||
if (ClockTask != NULL)
|
if (ClockTask != NULL)
|
||||||
xTaskNotifyFromISR(ClockTask, uint32_t(now()), eSetBits,
|
xTaskNotifyFromISR(ClockTask, uint32_t(now()), eSetBits,
|
||||||
&xHigherPriorityTaskWoken);
|
&xHigherPriorityTaskWoken);
|
||||||
|
|
||||||
#if defined GPS_INT || defined RTC_INT
|
#if (defined GPS_INT || defined RTC_INT)
|
||||||
TimePulseTick = !TimePulseTick; // flip ticker
|
TimePulseTick = !TimePulseTick; // flip pulse ticker
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
portEXIT_CRITICAL_ISR(&mux);
|
||||||
|
|
||||||
// yield only if we should
|
// yield only if we should
|
||||||
if (xHigherPriorityTaskWoken)
|
if (xHigherPriorityTaskWoken)
|
||||||
portYIELD_FROM_ISR();
|
portYIELD_FROM_ISR();
|
||||||
@ -163,8 +173,8 @@ TickType_t tx_Ticks(uint32_t framesize, unsigned long baud, uint32_t config,
|
|||||||
|
|
||||||
uint32_t databits = ((config & 0x0c) >> 2) + 5;
|
uint32_t databits = ((config & 0x0c) >> 2) + 5;
|
||||||
uint32_t stopbits = ((config & 0x20) >> 5) + 1;
|
uint32_t stopbits = ((config & 0x20) >> 5) + 1;
|
||||||
uint32_t txTime = (databits + stopbits + 2) * framesize * 1000.0 / baud;
|
uint32_t txTime = (databits + stopbits + 1) * framesize * 1000.0 / baud;
|
||||||
// +1 ms margin for the startbit +1 ms for pending processing time
|
// +1 for the startbit
|
||||||
|
|
||||||
return round(txTime);
|
return round(txTime);
|
||||||
}
|
}
|
||||||
@ -207,10 +217,13 @@ void clock_loop(void *taskparameter) { // ClockTask
|
|||||||
uint32_t printtime;
|
uint32_t printtime;
|
||||||
time_t t = *((time_t *)taskparameter); // UTC time seconds
|
time_t t = *((time_t *)taskparameter); // UTC time seconds
|
||||||
|
|
||||||
// preload first DCF frame before start
|
|
||||||
#ifdef HAS_DCF77
|
#ifdef HAS_DCF77
|
||||||
uint8_t *DCFpulse; // pointer on array with DCF pulse bits
|
uint8_t *DCFpulse; // pointer on array with DCF pulse bits
|
||||||
DCFpulse = DCF77_Frame(nextmin(t));
|
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
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// output the next second's pulse after timepulse arrived
|
// output the next second's pulse after timepulse arrived
|
||||||
@ -226,7 +239,8 @@ void clock_loop(void *taskparameter) { // ClockTask
|
|||||||
|
|
||||||
#if defined HAS_IF482
|
#if defined HAS_IF482
|
||||||
|
|
||||||
IF482_Pulse(t);
|
vTaskDelay(txDelay); // wait until moment to fire
|
||||||
|
IF482.print(IF482_Frame(t + 1)); // note: if482 telegram for *next* second
|
||||||
|
|
||||||
#elif defined HAS_DCF77
|
#elif defined HAS_DCF77
|
||||||
|
|
||||||
|
@ -54,7 +54,7 @@ void send_timesync_req() {
|
|||||||
"timesync_req", // name of task
|
"timesync_req", // name of task
|
||||||
2048, // stack size of task
|
2048, // stack size of task
|
||||||
(void *)1, // task parameter
|
(void *)1, // task parameter
|
||||||
4, // priority of the task
|
2, // priority of the task
|
||||||
&timeSyncReqTask, // task handle
|
&timeSyncReqTask, // task handle
|
||||||
1); // CPU core
|
1); // CPU core
|
||||||
}
|
}
|
||||||
@ -129,10 +129,14 @@ void process_timesync_req(void *taskparameter) {
|
|||||||
// calculate absolute time offset with millisecond precision using time base
|
// calculate absolute time offset with millisecond precision using time base
|
||||||
// of LMIC os, since we use LMIC's ostime_t txEnd as tx timestamp
|
// of LMIC os, since we use LMIC's ostime_t txEnd as tx timestamp
|
||||||
time_offset += milliseconds(osticks2ms(os_getTime()));
|
time_offset += milliseconds(osticks2ms(os_getTime()));
|
||||||
|
|
||||||
// apply calibration factor for processing time
|
// apply calibration factor for processing time
|
||||||
time_offset += milliseconds(TIME_SYNC_FIXUP);
|
time_offset += milliseconds(TIME_SYNC_FIXUP);
|
||||||
// convert to seconds
|
// convert to whole seconds
|
||||||
time_to_set = static_cast<time_t>(myClock_secTick(time_offset).count());
|
time_to_set = static_cast<time_t>(myClock_secTick(time_offset).count());
|
||||||
|
// time_to_set =
|
||||||
|
// static_cast<time_t>(duration_cast<seconds>(time_offset).count());
|
||||||
|
|
||||||
// calculate fraction milliseconds
|
// calculate fraction milliseconds
|
||||||
time_to_set_fraction_msec = static_cast<uint16_t>(time_offset.count() % 1000);
|
time_to_set_fraction_msec = static_cast<uint16_t>(time_offset.count() % 1000);
|
||||||
|
|
||||||
@ -145,15 +149,14 @@ void process_timesync_req(void *taskparameter) {
|
|||||||
TIME_SYNC_TRIGGER) { // milliseconds threshold
|
TIME_SYNC_TRIGGER) { // milliseconds threshold
|
||||||
|
|
||||||
// wait until top of second
|
// wait until top of second
|
||||||
uint16_t const wait_ms = 1000 - time_to_set_fraction_msec;
|
vTaskDelay(pdMS_TO_TICKS(1000 - time_to_set_fraction_msec));
|
||||||
ESP_LOGD(TAG, "[%0.3f] waiting %d ms", millis() / 1000.0, wait_ms);
|
|
||||||
vTaskDelay(pdMS_TO_TICKS(wait_ms));
|
|
||||||
|
|
||||||
#if !defined(GPS_INT) && !defined(RTC_INT)
|
time_to_set++; // advance time the one waited second
|
||||||
|
|
||||||
|
#if (!defined GPS_INT && !defined RTC_INT)
|
||||||
// sync esp32 hardware timer based pps to top of second
|
// sync esp32 hardware timer based pps to top of second
|
||||||
timerRestart(ppsIRQ); // reset pps timer
|
timerRestart(ppsIRQ); // reset pps timer
|
||||||
CLOCKIRQ(); // fire clock pps interrupt
|
CLOCKIRQ(); // fire clock pps interrupt
|
||||||
time_to_set++; // advance time 1 second
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
setTime(time_to_set); // set the time on top of second
|
setTime(time_to_set); // set the time on top of second
|
||||||
@ -193,6 +196,21 @@ void store_time_sync_req(uint32_t t_txEnd_ms) {
|
|||||||
t_txEnd_ms % 1000);
|
t_txEnd_ms % 1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
// called from lorawan.cpp after time_sync_req was sent
|
||||||
|
void store_time_sync_req_pwm(void) {
|
||||||
|
|
||||||
|
uint8_t k = time_sync_seqNo % TIME_SYNC_SAMPLES;
|
||||||
|
|
||||||
|
time_sync_tx[k] += milliseconds(t_txEnd_ms);
|
||||||
|
|
||||||
|
ESP_LOGD(TAG, "[%0.3f] Timesync request #%d sent at %d.%03d",
|
||||||
|
millis() / 1000.0, time_sync_seqNo, t_txEnd_ms / 1000,
|
||||||
|
t_txEnd_ms % 1000);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
// process timeserver timestamp answer, called from lorawan.cpp
|
// process timeserver timestamp answer, called from lorawan.cpp
|
||||||
int recv_timesync_ans(uint8_t buf[], uint8_t buf_len) {
|
int recv_timesync_ans(uint8_t buf[], uint8_t buf_len) {
|
||||||
|
|
||||||
@ -229,7 +247,7 @@ int recv_timesync_ans(uint8_t buf[], uint8_t buf_len) {
|
|||||||
// construct the timepoint when message was seen on gateway
|
// construct the timepoint when message was seen on gateway
|
||||||
time_sync_rx[k] += seconds(timestamp_sec) + milliseconds(timestamp_msec);
|
time_sync_rx[k] += seconds(timestamp_sec) + milliseconds(timestamp_msec);
|
||||||
|
|
||||||
// guess if the timepoint is recent by comparing with code compile date
|
// guess timepoint is recent if newer than code compile date
|
||||||
if (timeIsValid(myClock::to_time_t(time_sync_rx[k]))) {
|
if (timeIsValid(myClock::to_time_t(time_sync_rx[k]))) {
|
||||||
ESP_LOGD(TAG, "[%0.3f] Timesync request #%d rcvd at %d.%03d",
|
ESP_LOGD(TAG, "[%0.3f] Timesync request #%d rcvd at %d.%03d",
|
||||||
millis() / 1000.0, seq_no, timestamp_sec, timestamp_msec);
|
millis() / 1000.0, seq_no, timestamp_sec, timestamp_msec);
|
||||||
|
Loading…
Reference in New Issue
Block a user