timer irqs refactored
This commit is contained in:
parent
b516cbbbce
commit
51917b79d3
@ -111,7 +111,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble,
|
|||||||
batt_voltage; // display values
|
batt_voltage; // display values
|
||||||
extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC
|
extern bool volatile TimePulseTick; // 1sec pps flag set by GPS or RTC
|
||||||
extern timesource_t timeSource;
|
extern timesource_t timeSource;
|
||||||
extern hw_timer_t *sendCycle, *displaytimer, *clockCycle;
|
extern hw_timer_t *displayIRQ, *ppsIRQ;
|
||||||
extern SemaphoreHandle_t I2Caccess, TimePulse;
|
extern SemaphoreHandle_t I2Caccess, TimePulse;
|
||||||
extern TaskHandle_t irqHandlerTask, ClockTask;
|
extern TaskHandle_t irqHandlerTask, ClockTask;
|
||||||
extern TimerHandle_t WifiChanTimer;
|
extern TimerHandle_t WifiChanTimer;
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
#define DISPLAY_IRQ 0x01
|
#define DISPLAY_IRQ 0x01
|
||||||
#define BUTTON_IRQ 0x02
|
#define BUTTON_IRQ 0x02
|
||||||
#define SENDCOUNTER_IRQ 0x04
|
#define SENDCYCLE_IRQ 0x04
|
||||||
#define CYCLIC_IRQ 0x08
|
#define CYCLIC_IRQ 0x08
|
||||||
#define TIMESYNC_IRQ 0x10
|
#define TIMESYNC_IRQ 0x10
|
||||||
|
|
||||||
|
@ -30,17 +30,17 @@ void irqHandler(void *pvParameters) {
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
// are cyclic tasks due?
|
// are cyclic tasks due?
|
||||||
if (InterruptStatus & CYCLIC_IRQ) {
|
if (InterruptStatus & CYCLIC_IRQ)
|
||||||
doHousekeeping();
|
doHousekeeping();
|
||||||
}
|
|
||||||
|
|
||||||
// time to be synced?
|
#ifdef TIME_SYNC_INTERVAL
|
||||||
if (InterruptStatus & TIMESYNC_IRQ) {
|
// is time to be synced?
|
||||||
|
if (InterruptStatus & TIMESYNC_IRQ)
|
||||||
setTime(timeProvider());
|
setTime(timeProvider());
|
||||||
}
|
#endif
|
||||||
|
|
||||||
// is time to send the payload?
|
// is time to send the payload?
|
||||||
if (InterruptStatus & SENDCOUNTER_IRQ)
|
if (InterruptStatus & SENDCYCLE_IRQ)
|
||||||
sendCounter();
|
sendCounter();
|
||||||
}
|
}
|
||||||
vTaskDelete(NULL); // shoud never be reached
|
vTaskDelete(NULL); // shoud never be reached
|
||||||
@ -51,14 +51,26 @@ void irqHandler(void *pvParameters) {
|
|||||||
|
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
void IRAM_ATTR DisplayIRQ() {
|
void IRAM_ATTR DisplayIRQ() {
|
||||||
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits, NULL);
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
portYIELD_FROM_ISR();
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
xTaskNotifyFromISR(irqHandlerTask, DISPLAY_IRQ, eSetBits,
|
||||||
|
&xHigherPriorityTaskWoken);
|
||||||
|
|
||||||
|
if (xHigherPriorityTaskWoken)
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAS_BUTTON
|
#ifdef HAS_BUTTON
|
||||||
void IRAM_ATTR ButtonIRQ() {
|
void IRAM_ATTR ButtonIRQ() {
|
||||||
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits, NULL);
|
BaseType_t xHigherPriorityTaskWoken;
|
||||||
portYIELD_FROM_ISR();
|
xHigherPriorityTaskWoken = pdFALSE;
|
||||||
|
|
||||||
|
xTaskNotifyFromISR(irqHandlerTask, BUTTON_IRQ, eSetBits,
|
||||||
|
&xHigherPriorityTaskWoken);
|
||||||
|
|
||||||
|
if (xHigherPriorityTaskWoken)
|
||||||
|
portYIELD_FROM_ISR();
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
52
src/main.cpp
52
src/main.cpp
@ -23,17 +23,17 @@ licenses. Refer to LICENSE.txt file in repository for more details.
|
|||||||
|
|
||||||
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
|
//////////////////////// ESP32-Paxcounter \\\\\\\\\\\\\\\\\\\\\\\\\\
|
||||||
|
|
||||||
Uused tasks and timers:
|
// Tasks and timers:
|
||||||
|
|
||||||
Task Core Prio Purpose
|
Task Core Prio Purpose
|
||||||
====================================================================================
|
-------------------------------------------------------------------------------
|
||||||
ledloop 0 3 blinks LEDs
|
ledloop 0 3 blinks LEDs
|
||||||
spiloop 0 2 reads/writes data on spi interface
|
spiloop 0 2 reads/writes data on spi interface
|
||||||
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer
|
||||||
|
|
||||||
clockloop 1 4 generates realtime telegrams for external clock
|
clockloop 1 4 generates realtime telegrams for external clock
|
||||||
looptask 1 1 arduino core -> runs the LMIC LoRa stack
|
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
|
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
|
||||||
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
IDLE 1 0 ESP32 arduino scheduler -> runs wifi channel rotator
|
||||||
@ -43,16 +43,31 @@ Low priority numbers denote low priority tasks.
|
|||||||
Tasks using i2c bus all must have same priority, because using mutex semaphore
|
Tasks using i2c bus all must have same priority, because using mutex semaphore
|
||||||
(irqhandler, bmeloop)
|
(irqhandler, bmeloop)
|
||||||
|
|
||||||
ESP32 hardware irq timers
|
// ESP32 hardware timers
|
||||||
================================
|
-------------------------------------------------------------------------------
|
||||||
0 triggers display refresh
|
0 displayIRQ -> display refresh -> 40ms (DISPLAYREFRESH_MS in paxcounter.conf)
|
||||||
1 triggers DCF77 clock signal
|
1 ppsIRQ -> pps clock irq -> 1sec
|
||||||
2 triggers send payload cycle
|
2 unused
|
||||||
3 triggers housekeeping cycle
|
3 unused
|
||||||
|
|
||||||
RTC hardware timer (if present)
|
|
||||||
================================
|
// Interrupt routines
|
||||||
triggers pps 1 sec impulse
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
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,
|
uint16_t volatile macs_total = 0, macs_wifi = 0, macs_ble = 0,
|
||||||
batt_voltage = 0; // globals for display
|
batt_voltage = 0; // globals for display
|
||||||
|
|
||||||
hw_timer_t *sendCycle = NULL, *homeCycle = NULL, *clockCycle = NULL,
|
hw_timer_t *ppsIRQ = NULL, *displayIRQ = NULL;
|
||||||
*displaytimer = NULL;
|
|
||||||
|
|
||||||
TaskHandle_t irqHandlerTask, ClockTask;
|
TaskHandle_t irqHandlerTask, ClockTask;
|
||||||
SemaphoreHandle_t I2Caccess, TimePulse;
|
SemaphoreHandle_t I2Caccess, TimePulse;
|
||||||
@ -306,11 +320,11 @@ void setup() {
|
|||||||
// setup display refresh trigger IRQ using esp32 hardware timer
|
// setup display refresh trigger IRQ using esp32 hardware timer
|
||||||
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
// https://techtutorialsx.com/2017/10/07/esp32-arduino-timer-interrupts/
|
||||||
// prescaler 80 -> divides 80 MHz CPU freq to 1 MHz, timer 0, count up
|
// 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
|
// interrupt handler DisplayIRQ, triggered by edge
|
||||||
timerAttachInterrupt(displaytimer, &DisplayIRQ, true);
|
timerAttachInterrupt(displayIRQ, &DisplayIRQ, true);
|
||||||
// reload interrupt after each trigger of display refresh cycle
|
// reload interrupt after each trigger of display refresh cycle
|
||||||
timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true);
|
timerAlarmWrite(displayIRQ, DISPLAYREFRESH_MS * 1000, true);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// show payload encoder
|
// show payload encoder
|
||||||
@ -385,9 +399,9 @@ void setup() {
|
|||||||
// start timer triggered interrupts
|
// start timer triggered interrupts
|
||||||
ESP_LOGI(TAG, "Starting Timers...");
|
ESP_LOGI(TAG, "Starting Timers...");
|
||||||
#ifdef HAS_DISPLAY
|
#ifdef HAS_DISPLAY
|
||||||
timerAlarmEnable(displaytimer);
|
timerAlarmEnable(displayIRQ);
|
||||||
#endif
|
#endif
|
||||||
sendcycler.attach(SEND_CYCLE, sendcycle);
|
sendcycler.attach(SEND_CYCLE * 2, sendcycle);
|
||||||
housekeeper.attach(HOMECYCLE, housekeeping);
|
housekeeper.attach(HOMECYCLE, housekeeping);
|
||||||
|
|
||||||
// start button interrupt
|
// start button interrupt
|
||||||
|
@ -10,7 +10,7 @@
|
|||||||
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
#define VERBOSE 1 // comment out to silence the device, for mute use build option
|
||||||
|
|
||||||
// Payload send cycle and encoding
|
// 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
|
#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
|
// Set this to include BLE counting and vendor filter functions
|
||||||
|
@ -290,11 +290,12 @@ void PayloadConvert::writeBitmap(bool a, bool b, bool c, bool d, bool e, bool f,
|
|||||||
}
|
}
|
||||||
|
|
||||||
/* ---------------- Cayenne LPP 2.0 format ---------- */
|
/* ---------------- Cayenne LPP 2.0 format ---------- */
|
||||||
// see specs
|
// see specs
|
||||||
// http://community.mydevices.com/t/cayenne-lpp-2-0/7510 (LPP 2.0)
|
// 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)
|
// https://github.com/myDevicesIoT/cayenne-docs/blob/master/docs/LORA.md
|
||||||
// PAYLOAD_ENCODER == 3 -> Dynamic Sensor Payload, using channels -> FPort 1
|
// (LPP 1.0) PAYLOAD_ENCODER == 3 -> Dynamic Sensor Payload, using channels ->
|
||||||
// PAYLOAD_ENCODER == 4 -> Packed Sensor Payload, not using channels -> FPort 2
|
// FPort 1 PAYLOAD_ENCODER == 4 -> Packed Sensor Payload, not using channels ->
|
||||||
|
// FPort 2
|
||||||
|
|
||||||
#elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4)
|
#elif (PAYLOAD_ENCODER == 3 || PAYLOAD_ENCODER == 4)
|
||||||
|
|
||||||
|
@ -58,9 +58,8 @@ void set_rssi(uint8_t val[]) {
|
|||||||
|
|
||||||
void set_sendcycle(uint8_t val[]) {
|
void set_sendcycle(uint8_t val[]) {
|
||||||
cfg.sendcycle = val[0];
|
cfg.sendcycle = val[0];
|
||||||
// update send cycle interrupt
|
// update send cycle interrupt [seconds
|
||||||
timerAlarmWrite(sendCycle, cfg.sendcycle * 2 * 10000, true);
|
sendcycler.attach(cfg.sendcycle * 2, sendcycle);
|
||||||
// reload interrupt after each trigger of channel switch cycle
|
|
||||||
ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds",
|
ESP_LOGI(TAG, "Remote command: set send cycle to %d seconds",
|
||||||
cfg.sendcycle * 2);
|
cfg.sendcycle * 2);
|
||||||
}
|
}
|
||||||
|
@ -3,7 +3,7 @@
|
|||||||
|
|
||||||
Ticker sendcycler;
|
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
|
// put data to send in RTos Queues used for transmit over channels Lora and SPI
|
||||||
void SendPayload(uint8_t port, sendprio_t prio) {
|
void SendPayload(uint8_t port, sendprio_t prio) {
|
||||||
|
@ -78,8 +78,8 @@ uint8_t timepulse_init() {
|
|||||||
|
|
||||||
#else
|
#else
|
||||||
// use ESP32 hardware timer as time base with adjustable frequency
|
// use ESP32 hardware timer as time base with adjustable frequency
|
||||||
clockCycle = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
|
ppsIRQ = timerBegin(1, 8000, true); // set 80 MHz prescaler to 1/10000 sec
|
||||||
timerAlarmWrite(clockCycle, 10000, true); // 1000ms
|
timerAlarmWrite(ppsIRQ, 10000, true); // 1000ms
|
||||||
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
|
ESP_LOGI(TAG, "Timepulse: internal (ESP32 hardware timer)");
|
||||||
return 1; // success
|
return 1; // success
|
||||||
|
|
||||||
@ -92,8 +92,8 @@ void timepulse_start(void) {
|
|||||||
#elif defined RTC_INT // start external clock rtc
|
#elif defined RTC_INT // start external clock rtc
|
||||||
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
|
attachInterrupt(digitalPinToInterrupt(RTC_INT), CLOCKIRQ, FALLING);
|
||||||
#else // start internal clock esp32 hardware timer
|
#else // start internal clock esp32 hardware timer
|
||||||
timerAttachInterrupt(clockCycle, &CLOCKIRQ, true);
|
timerAttachInterrupt(ppsIRQ, &CLOCKIRQ, true);
|
||||||
timerAlarmEnable(clockCycle);
|
timerAlarmEnable(ppsIRQ);
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user