interrupt timing issues (not fully solved yet)
This commit is contained in:
parent
8de2ee0680
commit
54c6536349
@ -2,13 +2,9 @@
|
||||
#define _IF482_H
|
||||
|
||||
#include "globals.h"
|
||||
#include "timekeeper.h"
|
||||
|
||||
#define IF482_FRAME_SIZE (17)
|
||||
|
||||
extern HardwareSerial IF482;
|
||||
|
||||
void IF482_Pulse(time_t t);
|
||||
String IRAM_ATTR IF482_Frame(time_t tt);
|
||||
|
||||
#endif
|
@ -6,9 +6,10 @@
|
||||
#include "TimeLib.h"
|
||||
#include "irqhandler.h"
|
||||
|
||||
#if(HAS_GPS)
|
||||
#ifdef HAS_GPS
|
||||
#include "gpsread.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAS_IF482
|
||||
#include "if482.h"
|
||||
#elif defined HAS_DCF77
|
||||
|
@ -84,18 +84,6 @@ not evaluated by model BU-190, use "F" instead for this model
|
||||
// Local logging tag
|
||||
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) {
|
||||
|
||||
time_t t = myTZ.toLocal(printTime);
|
||||
|
@ -3,6 +3,8 @@
|
||||
// Local logging tag
|
||||
static const char TAG[] = __FILE__;
|
||||
|
||||
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
// irq handler task, handles all our application level interrupts
|
||||
void irqHandler(void *pvParameters) {
|
||||
|
||||
@ -54,12 +56,13 @@ void irqHandler(void *pvParameters) {
|
||||
|
||||
#ifdef HAS_DISPLAY
|
||||
void IRAM_ATTR DisplayIRQ() {
|
||||
portENTER_CRITICAL_ISR(&mux);
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits,
|
||||
&xHigherPriorityTaskWoken);
|
||||
|
||||
portEXIT_CRITICAL_ISR(&mux);
|
||||
if (xHigherPriorityTaskWoken)
|
||||
portYIELD_FROM_ISR();
|
||||
}
|
||||
@ -67,11 +70,13 @@ void IRAM_ATTR DisplayIRQ() {
|
||||
|
||||
#ifdef HAS_BUTTON
|
||||
void IRAM_ATTR ButtonIRQ() {
|
||||
portENTER_CRITICAL_ISR(&mux);
|
||||
BaseType_t xHigherPriorityTaskWoken;
|
||||
xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits,
|
||||
&xHigherPriorityTaskWoken);
|
||||
portEXIT_CRITICAL_ISR(&mux);
|
||||
|
||||
if (xHigherPriorityTaskWoken)
|
||||
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
|
||||
gpsloop 1 2 reads data from GPS via serial or 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
|
||||
|
||||
Low priority numbers denote low priority tasks.
|
||||
|
@ -14,8 +14,14 @@ static const char TAG[] = __FILE__;
|
||||
// symbol to display current time source
|
||||
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;
|
||||
|
||||
static portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
|
||||
|
||||
void timeSync() { xTaskNotify(irqHandlerTask, TIMESYNC_IRQ, eSetBits); }
|
||||
|
||||
time_t timeProvider(void) {
|
||||
@ -115,18 +121,22 @@ 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;
|
||||
SyncToPPS(); // calibrates UTC systime, see microTime.h
|
||||
xHigherPriorityTaskWoken = pdFALSE;
|
||||
|
||||
SyncToPPS(); // calibrates UTC systime, see microTime.h
|
||||
|
||||
if (ClockTask != NULL)
|
||||
xTaskNotifyFromISR(ClockTask, uint32_t(now()), eSetBits,
|
||||
&xHigherPriorityTaskWoken);
|
||||
|
||||
#if defined GPS_INT || defined RTC_INT
|
||||
TimePulseTick = !TimePulseTick; // flip ticker
|
||||
#if (defined GPS_INT || defined RTC_INT)
|
||||
TimePulseTick = !TimePulseTick; // flip pulse ticker
|
||||
#endif
|
||||
|
||||
portEXIT_CRITICAL_ISR(&mux);
|
||||
|
||||
// yield only if we should
|
||||
if (xHigherPriorityTaskWoken)
|
||||
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 stopbits = ((config & 0x20) >> 5) + 1;
|
||||
uint32_t txTime = (databits + stopbits + 2) * framesize * 1000.0 / baud;
|
||||
// +1 ms margin for the startbit +1 ms for pending processing time
|
||||
uint32_t txTime = (databits + stopbits + 1) * framesize * 1000.0 / baud;
|
||||
// +1 for the startbit
|
||||
|
||||
return round(txTime);
|
||||
}
|
||||
@ -207,10 +217,13 @@ void clock_loop(void *taskparameter) { // ClockTask
|
||||
uint32_t printtime;
|
||||
time_t t = *((time_t *)taskparameter); // UTC time seconds
|
||||
|
||||
// preload first DCF frame before start
|
||||
#ifdef HAS_DCF77
|
||||
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
|
||||
|
||||
// output the next second's pulse after timepulse arrived
|
||||
@ -226,7 +239,8 @@ void clock_loop(void *taskparameter) { // ClockTask
|
||||
|
||||
#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
|
||||
|
||||
|
@ -54,7 +54,7 @@ void send_timesync_req() {
|
||||
"timesync_req", // name of task
|
||||
2048, // stack size of task
|
||||
(void *)1, // task parameter
|
||||
4, // priority of the task
|
||||
2, // priority of the task
|
||||
&timeSyncReqTask, // task handle
|
||||
1); // CPU core
|
||||
}
|
||||
@ -129,10 +129,14 @@ void process_timesync_req(void *taskparameter) {
|
||||
// calculate absolute time offset with millisecond precision using time base
|
||||
// of LMIC os, since we use LMIC's ostime_t txEnd as tx timestamp
|
||||
time_offset += milliseconds(osticks2ms(os_getTime()));
|
||||
|
||||
// apply calibration factor for processing time
|
||||
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>(duration_cast<seconds>(time_offset).count());
|
||||
|
||||
// calculate fraction milliseconds
|
||||
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
|
||||
|
||||
// wait until top of second
|
||||
uint16_t const wait_ms = 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));
|
||||
vTaskDelay(pdMS_TO_TICKS(1000 - time_to_set_fraction_msec));
|
||||
|
||||
#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
|
||||
timerRestart(ppsIRQ); // reset pps timer
|
||||
CLOCKIRQ(); // fire clock pps interrupt
|
||||
time_to_set++; // advance time 1 second
|
||||
#endif
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
/*
|
||||
// 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
|
||||
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
|
||||
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]))) {
|
||||
ESP_LOGD(TAG, "[%0.3f] Timesync request #%d rcvd at %d.%03d",
|
||||
millis() / 1000.0, seq_no, timestamp_sec, timestamp_msec);
|
||||
|
Loading…
Reference in New Issue
Block a user