timer irqs refactored

This commit is contained in:
Verkehrsrot 2019-03-03 12:57:00 +01:00
parent b516cbbbce
commit 51917b79d3
9 changed files with 70 additions and 44 deletions

View File

@ -111,7 +111,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble,
batt_voltage; // display values
extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC
extern timesource_t timeSource;
extern hw_timer_t *sendCycle, *displaytimer, *clockCycle;
extern hw_timer_t *displayIRQ, *ppsIRQ;
extern SemaphoreHandle_t I2Caccess, TimePulse;
extern TaskHandle_t irqHandlerTask, ClockTask;
extern TimerHandle_t WifiChanTimer;

View File

@ -3,7 +3,7 @@
#define DISPLAY_IRQ 0x01
#define BUTTON_IRQ 0x02
#define SENDCOUNTER_IRQ 0x04
#define SENDCYCLE_IRQ 0x04
#define CYCLIC_IRQ 0x08
#define TIMESYNC_IRQ 0x10

View File

@ -30,17 +30,17 @@ void irqHandler(void *pvParameters) {
#endif
// are cyclic tasks due?
if (InterruptStatus & CYCLIC_IRQ) {
if (InterruptStatus & CYCLIC_IRQ)
doHousekeeping();
}
// time to be synced?
if (InterruptStatus & TIMESYNC_IRQ) {
#ifdef TIME_SYNC_INTERVAL
// is time to be synced?
if (InterruptStatus & TIMESYNC_IRQ)
setTime(timeProvider());
}
#endif
// is time to send the payload?
if (InterruptStatus & SENDCOUNTER_IRQ)
if (InterruptStatus & SENDCYCLE_IRQ)
sendCounter();
}
vTaskDelete(NULL); // shoud never be reached
@ -51,14 +51,26 @@ void irqHandler(void *pvParameters) {
#ifdef HAS_DISPLAY
void IRAM_ATTR DisplayIRQ() {
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits, NULL);
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits,
&xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
}
#endif
#ifdef HAS_BUTTON
void IRAM_ATTR ButtonIRQ() {
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits, NULL);
BaseType_t xHigherPriorityTaskWoken;
xHigherPriorityTaskWoken = pdFALSE;
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits,
&xHigherPriorityTaskWoken);
if (xHigherPriorityTaskWoken)
portYIELD_FROM_ISR();
}
#endif

View File

@ -23,17 +23,17 @@ licenses. Refer to LICENSE.txt file in repository for more details.
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
Uused tasks and timers:
// Tasks and timers:
Task Core Prio Purpose
====================================================================================
-------------------------------------------------------------------------------
ledloop 0 3 blinks LEDs
spiloop 0 2 reads/writes data on spi interface
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
clockloop 1 4 generates realtime telegrams for external clock
looptask 1 1 arduino core -> runs the LMIC LoRa stack
irqhandler 1 1 executes tasks triggered by hw irq, see table below
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
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
@ -43,15 +43,30 @@ Low priority numbers denote low priority tasks.
Tasks using i2c bus all must have same priority, because using mutex semaphore
(irqhandler, bmeloop)
ESP32 hardware irq timers
================================
0 triggers display refresh
1 triggers DCF77 clock signal
2 triggers send payload cycle
3 triggers housekeeping cycle
// ESP32 hardware timers
-------------------------------------------------------------------------------
0 displayIRQ -> display refresh -> 40ms (DISPLAYREFRESH_MS in paxcounter.conf)
1 ppsIRQ -> pps clock irq -> 1sec
2 unused
3 unused
RTC hardware timer (if present)
================================
// Interrupt routines
-------------------------------------------------------------------------------
fired by hardware
DisplayIRQ -> esp32 timer 0 -> irqhandler.cpp
CLOCKIRQ -> esp32 timer 1 -> timekeeper.cpp
ButtonIRQ -> external gpio -> irqhandler.cpp
fired by software (Ticker.h)
TIMESYNC_IRQ -> timeSync() -> timerkeeper.cpp
CYLCIC_IRQ -> housekeeping() -> cyclic.cpp
SENDCYCLE_IRQ -> sendcycle() -> senddata.cpp
// External RTC timer (if present)
-------------------------------------------------------------------------------
triggers pps 1 sec impulse
*/
@ -65,8 +80,7 @@ uint8_t volatile channel = 0; // channel rotation counter
uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
batt_voltage = 0; // globals for display
hw_timer_t *sendCycle = NULL, *homeCycle = NULL, *clockCycle = NULL,
*displaytimer = NULL;
hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL;
TaskHandle_t irqHandlerTask, ClockTask;
SemaphoreHandle_t I2Caccess, TimePulse;
@ -306,11 +320,11 @@ void setup() {
// setup display refresh trigger IRQ using esp32 hardware timer
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
// prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
displaytimer = timerBegin(0, 80, true);
displayIRQ = timerBegin(0, 80, true);
// interrupt handler DisplayIRQ, triggered by edge
timerAttachInterrupt(displaytimer, &DisplayIRQ, true);
timerAttachInterrupt(displayIRQ, &DisplayIRQ, true);
// reload interrupt after each trigger of display refresh cycle
timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true);
timerAlarmWrite(displayIRQ, DISPLAYREFRESH_MS * 1000, true);
#endif
// show payload encoder
@ -385,9 +399,9 @@ void setup() {
// start timer triggered interrupts
ESP_LOGI(TAG, "Starting Timers...");
#ifdef HAS_DISPLAY
timerAlarmEnable(displaytimer);
timerAlarmEnable(displayIRQ);
#endif
sendcycler.attach(SEND_CYCLE, sendcycle);
sendcycler.attach(SEND_CYCLE * 2, sendcycle);
housekeeper.attach(HOMECYCLE, housekeeping);
// start button interrupt

View File

@ -10,7 +10,7 @@
#define VERBOSE 1 // comment out to silence the device, for mute use build option
// Payload send cycle and encoding
#define SEND_CYCLE 30 // payload send cycle [seconds/2] -> 60 sec.
#define SEND_CYCLE 30 // payload send cycle [seconds/2], 0 .. 255
#define PAYLOAD_ENCODER 2 // payload encoder: 1=Plain, 2=Packed, 3=Cayenne LPP dynamic, 4=Cayenne LPP packed
// Set this to include BLE counting and vendor filter functions

View File

@ -292,9 +292,10 @@ void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f,
/* ---------------- Cayenne LPP 2.0 format ---------- */
// see specs
// http://community.mydevices.com/t/cayenne-lpp-2-0/7510 (LPP 2.0)
// https://github.com/myDevicesIoT/cayenne-docs/blob/master/docs/LORA.md (LPP 1.0)
// PAYLOAD_ENCODER == 3 -> Dynamic Sensor Payload, using channels -> FPort 1
// PAYLOAD_ENCODER == 4 -> Packed Sensor Payload, not using channels -> FPort 2
// https://github.com/myDevicesIoT/cayenne-docs/blob/master/docs/LORA.md
// (LPP 1.0) PAYLOAD_ENCODER == 3 -> Dynamic Sensor Payload, using channels ->
// FPort 1 PAYLOAD_ENCODER == 4 -> Packed Sensor Payload, not using channels ->
// FPort 2
#elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4)

View File

@ -58,9 +58,8 @@ void set_rssi(uint8_t val[]) {
void set_sendcycle(uint8_t val[]) {
cfg.sendcycle = val[0];
// update send cycle interrupt
timerAlarmWrite(sendCycle, cfg.sendcycle * 2 * 10000, true);
// reload interrupt after each trigger of channel switch cycle
// update send cycle interrupt [seconds
sendcycler.attach(cfg.sendcycle * 2, sendcycle);
ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds",
cfg.sendcycle * 2);
}

View File

@ -3,7 +3,7 @@
Ticker sendcycler;
void sendcycle() { xTaskNotify(irqHandlerTask, SENDCOUNTER_IRQ, eSetBits); }
void sendcycle() { xTaskNotify(irqHandlerTask, SENDCYCLE_IRQ, eSetBits); }
// put data to send in RTos Queues used for transmit over channels Lora and SPI
void SendPayload(uint8_t port, sendprio_t prio) {

View File

@ -78,8 +78,8 @@ uint8_t timepulse_init() {
#else
// use ESP32 hardware timer as time base with adjustable frequency
clockCycle = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
timerAlarmWrite(clockCycle, 10000, true); // 1000ms
ppsIRQ = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
timerAlarmWrite(ppsIRQ, 10000, true); // 1000ms
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
return 1; // success
@ -92,8 +92,8 @@ void timepulse_start(void) {
#elif defined RTC_INT // start external clock rtc
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
#else // start internal clock esp32 hardware timer
timerAttachInterrupt(clockCycle, &CLOCKIRQ, true);
timerAlarmEnable(clockCycle);
timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, true);
timerAlarmEnable(ppsIRQ);
#endif
}