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
|
||||
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;
|
||||
|
@ -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
|
||||
|
||||
|
@ -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
|
||||
|
50
src/main.cpp
50
src/main.cpp
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user