interrupt timing issues (not fully solved yet)

This commit is contained in:
Verkehrsrot 2019-03-23 15:12:11 +01:00
parent 8de2ee0680
commit 54c6536349
7 changed files with 58 additions and 36 deletions

View File

@ -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

View File

@ -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

View File

@ -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);

View File

@ -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();

View File

@ -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.

View File

@ -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));
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
#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

View File

@ -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);