tasking + statemachine restructured
This commit is contained in:
parent
67832da09d
commit
5b9327512b
@ -10,7 +10,11 @@
|
|||||||
static const char TAG[] = "main";
|
static const char TAG[] = "main";
|
||||||
|
|
||||||
// do all housekeeping
|
// do all housekeeping
|
||||||
void doHomework() {
|
void doHousekeeping() {
|
||||||
|
|
||||||
|
portENTER_CRITICAL(&timerMux);
|
||||||
|
HomeCycleIRQ = 0;
|
||||||
|
portEXIT_CRITICAL(&timerMux);
|
||||||
|
|
||||||
// update uptime counter
|
// update uptime counter
|
||||||
uptime();
|
uptime();
|
||||||
@ -49,16 +53,7 @@ void doHomework() {
|
|||||||
if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again
|
if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again
|
||||||
esp_restart(); // memory leak, reset device
|
esp_restart(); // memory leak, reset device
|
||||||
}
|
}
|
||||||
} // doHomework()
|
} // doHousekeeping()
|
||||||
|
|
||||||
void checkHousekeeping() {
|
|
||||||
if (HomeCycleIRQ) {
|
|
||||||
portENTER_CRITICAL(&timerMux);
|
|
||||||
HomeCycleIRQ = 0;
|
|
||||||
portEXIT_CRITICAL(&timerMux);
|
|
||||||
doHomework();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void IRAM_ATTR homeCycleIRQ() {
|
void IRAM_ATTR homeCycleIRQ() {
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&timerMux);
|
||||||
|
@ -1,8 +1,7 @@
|
|||||||
#ifndef _CYCLIC_H
|
#ifndef _CYCLIC_H
|
||||||
#define _CYCLIC_H
|
#define _CYCLIC_H
|
||||||
|
|
||||||
void doHomework(void);
|
void doHousekeeping(void);
|
||||||
void checkHousekeeping(void);
|
|
||||||
void homeCycleIRQ(void);
|
void homeCycleIRQ(void);
|
||||||
uint64_t uptime(void);
|
uint64_t uptime(void);
|
||||||
void reset_counters(void);
|
void reset_counters(void);
|
||||||
|
71
src/main.cpp
71
src/main.cpp
@ -33,14 +33,14 @@ uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0,
|
|||||||
batt_voltage = 0; // globals for display
|
batt_voltage = 0; // globals for display
|
||||||
|
|
||||||
// hardware timer for cyclic tasks
|
// hardware timer for cyclic tasks
|
||||||
hw_timer_t *channelSwitch = NULL, *displaytimer = NULL, *sendCycle = NULL,
|
hw_timer_t *channelSwitch, *displaytimer, *sendCycle, *homeCycle;
|
||||||
*homeCycle = NULL;
|
|
||||||
|
|
||||||
// this variables will be changed in the ISR, and read in main loop
|
// this variables will be changed in the ISR, and read in main loop
|
||||||
volatile int ButtonPressedIRQ = 0, ChannelTimerIRQ = 0, SendCycleTimerIRQ = 0,
|
volatile int ButtonPressedIRQ = 0, ChannelTimerIRQ = 0, SendCycleTimerIRQ = 0,
|
||||||
DisplayTimerIRQ = 0, HomeCycleIRQ = 0;
|
DisplayTimerIRQ = 0, HomeCycleIRQ = 0;
|
||||||
|
|
||||||
TaskHandle_t WifiLoopTask = NULL;
|
TaskHandle_t WifiLoopTask = NULL;
|
||||||
|
TaskHandle_t StateTask = NULL;
|
||||||
|
|
||||||
// RTos send queues for payload transmit
|
// RTos send queues for payload transmit
|
||||||
#ifdef HAS_LORA
|
#ifdef HAS_LORA
|
||||||
@ -68,9 +68,6 @@ PayloadConvert payload(PAYLOAD_BUFFER_SIZE);
|
|||||||
// local Tag for logging
|
// local Tag for logging
|
||||||
static const char TAG[] = "main";
|
static const char TAG[] = "main";
|
||||||
|
|
||||||
/* begin Aruino SETUP
|
|
||||||
* ------------------------------------------------------------ */
|
|
||||||
|
|
||||||
void setup() {
|
void setup() {
|
||||||
|
|
||||||
// disable the default wifi logging
|
// disable the default wifi logging
|
||||||
@ -229,6 +226,7 @@ void setup() {
|
|||||||
// 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(displaytimer, DISPLAYREFRESH_MS * 1000, true);
|
||||||
// enable display interrupt
|
// enable display interrupt
|
||||||
|
yield();
|
||||||
timerAlarmEnable(displaytimer);
|
timerAlarmEnable(displaytimer);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -236,7 +234,6 @@ void setup() {
|
|||||||
channelSwitch = timerBegin(1, 800, true);
|
channelSwitch = timerBegin(1, 800, true);
|
||||||
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
|
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, true);
|
||||||
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 1000, true);
|
timerAlarmWrite(channelSwitch, cfg.wifichancycle * 1000, true);
|
||||||
//ESP_LOGI(TAG, "chanelswitch alarm threshold %d", cfg.wifichancycle * 1000);
|
|
||||||
|
|
||||||
// setup send cycle trigger IRQ using esp32 hardware timer 2
|
// setup send cycle trigger IRQ using esp32 hardware timer 2
|
||||||
sendCycle = timerBegin(2, 8000, true);
|
sendCycle = timerBegin(2, 8000, true);
|
||||||
@ -248,9 +245,13 @@ void setup() {
|
|||||||
timerAttachInterrupt(homeCycle, &homeCycleIRQ, true);
|
timerAttachInterrupt(homeCycle, &homeCycleIRQ, true);
|
||||||
timerAlarmWrite(homeCycle, HOMECYCLE * 10000, true);
|
timerAlarmWrite(homeCycle, HOMECYCLE * 10000, true);
|
||||||
|
|
||||||
//enable timers, caution: order is critical here
|
// enable timers
|
||||||
|
// caution, see: https://github.com/espressif/arduino-esp32/issues/1313
|
||||||
|
yield();
|
||||||
timerAlarmEnable(homeCycle);
|
timerAlarmEnable(homeCycle);
|
||||||
|
yield();
|
||||||
timerAlarmEnable(sendCycle);
|
timerAlarmEnable(sendCycle);
|
||||||
|
yield();
|
||||||
timerAlarmEnable(channelSwitch);
|
timerAlarmEnable(channelSwitch);
|
||||||
|
|
||||||
// show payload encoder
|
// show payload encoder
|
||||||
@ -283,13 +284,35 @@ void setup() {
|
|||||||
// join network
|
// join network
|
||||||
LMIC_startJoining();
|
LMIC_startJoining();
|
||||||
|
|
||||||
|
/*
|
||||||
|
|
||||||
|
Overview Tasks & Timer
|
||||||
|
|
||||||
|
Task Core Prio Purpose
|
||||||
|
====================================================================
|
||||||
|
IDLE 0 0 ESP32 arduino scheduler
|
||||||
|
wifiloop 0 1 switches Wifi channels
|
||||||
|
gpsloop 0 2 reasd data from GPS over serial or i2c
|
||||||
|
IDLE 1 0 Arduino loop() -> unused
|
||||||
|
loraloop 1 1 runs the LMIC stack
|
||||||
|
statemachine 1 3 switches process logic
|
||||||
|
|
||||||
|
Timers
|
||||||
|
======
|
||||||
|
0 Display-Refresh
|
||||||
|
1 Wifi Channel Switch
|
||||||
|
2 Send Cycle
|
||||||
|
3 Housekeeping
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
// start lmic runloop in rtos task on core 1
|
// start lmic runloop in rtos task on core 1
|
||||||
// (note: arduino main loop runs on core 1, too)
|
// (note: arduino main loop runs on core 1, too)
|
||||||
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
|
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
|
||||||
|
|
||||||
ESP_LOGI(TAG, "Starting Lora...");
|
ESP_LOGI(TAG, "Starting Lora...");
|
||||||
xTaskCreatePinnedToCore(lorawan_loop, "loraloop", 2048, (void *)1,
|
xTaskCreatePinnedToCore(lorawan_loop, "loraloop", 2048, (void *)1, 1,
|
||||||
(5 | portPRIVILEGE_BIT), &LoraTask, 1);
|
&LoraTask, 1);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// if device has GPS and it is enabled, start GPS reader task on core 0 with
|
// if device has GPS and it is enabled, start GPS reader task on core 0 with
|
||||||
@ -317,18 +340,19 @@ void setup() {
|
|||||||
reset_salt(); // get new 16bit for salting hashes
|
reset_salt(); // get new 16bit for salting hashes
|
||||||
xTaskCreatePinnedToCore(wifi_channel_loop, "wifiloop", 2048, (void *)1, 1,
|
xTaskCreatePinnedToCore(wifi_channel_loop, "wifiloop", 2048, (void *)1, 1,
|
||||||
&WifiLoopTask, 0);
|
&WifiLoopTask, 0);
|
||||||
|
|
||||||
|
// start state machine
|
||||||
|
ESP_LOGI(TAG, "Starting Statemachine...");
|
||||||
|
xTaskCreatePinnedToCore(stateMachine, "stateloop", 2048, (void *)1, 3,
|
||||||
|
&StateTask, 1);
|
||||||
|
|
||||||
} // setup()
|
} // setup()
|
||||||
|
|
||||||
/* end Arduino SETUP
|
void stateMachine(void *pvParameters) {
|
||||||
* ------------------------------------------------------------ */
|
|
||||||
|
|
||||||
/* begin Arduino main loop
|
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
|
||||||
* ------------------------------------------------------ */
|
|
||||||
|
|
||||||
void loop() {
|
while (1) {
|
||||||
|
|
||||||
// state machine for switching display, LED, button, housekeeping,
|
|
||||||
// senddata
|
|
||||||
|
|
||||||
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
|
||||||
led_loop();
|
led_loop();
|
||||||
@ -342,16 +366,17 @@ void loop() {
|
|||||||
updateDisplay();
|
updateDisplay();
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
// check housekeeping cycle and if expired do homework
|
// check housekeeping cycle and if expired do the work
|
||||||
checkHousekeeping();
|
if (HomeCycleIRQ)
|
||||||
|
doHousekeeping();
|
||||||
// check send queue and process it
|
// check send queue and process it
|
||||||
processSendBuffer();
|
processSendBuffer();
|
||||||
// check send cycle and enqueue payload if cycle is expired
|
// check send cycle and enqueue payload if cycle is expired
|
||||||
|
if (SendCycleTimerIRQ)
|
||||||
sendPayload();
|
sendPayload();
|
||||||
// yield to CPU
|
// yield to CPU
|
||||||
vTaskDelay(2 / portTICK_PERIOD_MS);
|
vTaskDelay(2 / portTICK_PERIOD_MS);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // loop()
|
void loop() { vTaskDelay(2 / portTICK_PERIOD_MS); }
|
||||||
|
|
||||||
/* end Arduino main loop
|
|
||||||
* ------------------------------------------------------------ */
|
|
||||||
|
@ -13,5 +13,8 @@
|
|||||||
|
|
||||||
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
|
||||||
#include <esp_event_loop.h> // needed for Wifi event handler
|
#include <esp_event_loop.h> // needed for Wifi event handler
|
||||||
|
#include <esp32-hal-timer.h> // needed for timers
|
||||||
|
|
||||||
|
void stateMachine(void *pvParameters);
|
||||||
|
|
||||||
#endif
|
#endif
|
@ -246,7 +246,7 @@ int version_compare(const String v1, const String v2) {
|
|||||||
// vnum stores each numeric part of version
|
// vnum stores each numeric part of version
|
||||||
int vnum1 = 0, vnum2 = 0;
|
int vnum1 = 0, vnum2 = 0;
|
||||||
|
|
||||||
// loop untill both string are processed
|
// loop until both string are processed
|
||||||
for (int i = 0, j = 0; (i < v1.length() || j < v2.length());) {
|
for (int i = 0, j = 0; (i < v1.length() || j < v2.length());) {
|
||||||
// storing numeric part of version 1 in vnum1
|
// storing numeric part of version 1 in vnum1
|
||||||
while (i < v1.length() && v1[i] != '.') {
|
while (i < v1.length() && v1[i] != '.') {
|
||||||
|
@ -34,10 +34,9 @@ void SendData(uint8_t port) {
|
|||||||
}
|
}
|
||||||
} // SendData
|
} // SendData
|
||||||
|
|
||||||
// cyclic called function to prepare payload to send
|
// interrupt triggered function to prepare payload to send
|
||||||
void sendPayload() {
|
void sendPayload() {
|
||||||
|
|
||||||
if (SendCycleTimerIRQ) {
|
|
||||||
portENTER_CRITICAL(&timerMux);
|
portENTER_CRITICAL(&timerMux);
|
||||||
SendCycleTimerIRQ = 0;
|
SendCycleTimerIRQ = 0;
|
||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&timerMux);
|
||||||
@ -51,8 +50,7 @@ void sendPayload() {
|
|||||||
// show NMEA data in debug mode, useful for debugging GPS on board
|
// show NMEA data in debug mode, useful for debugging GPS on board
|
||||||
// connection
|
// connection
|
||||||
ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
|
ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
|
||||||
gps.passedChecksum(), gps.failedChecksum(),
|
gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix());
|
||||||
gps.sentencesWithFix());
|
|
||||||
// log GPS position if we have a fix and gps data mode is enabled
|
// log GPS position if we have a fix and gps data mode is enabled
|
||||||
if ((cfg.gpsmode) && (gps.location.isValid())) {
|
if ((cfg.gpsmode) && (gps.location.isValid())) {
|
||||||
gps_read();
|
gps_read();
|
||||||
@ -66,7 +64,6 @@ void sendPayload() {
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
SendData(COUNTERPORT);
|
SendData(COUNTERPORT);
|
||||||
}
|
|
||||||
} // sendpayload()
|
} // sendpayload()
|
||||||
|
|
||||||
// interrupt handler used for payload send cycle timer
|
// interrupt handler used for payload send cycle timer
|
||||||
@ -76,9 +73,8 @@ void IRAM_ATTR SendCycleIRQ() {
|
|||||||
portEXIT_CRITICAL(&timerMux);
|
portEXIT_CRITICAL(&timerMux);
|
||||||
}
|
}
|
||||||
|
|
||||||
// cyclic called function to eat data from RTos send queues and transmit it
|
// interrupt triggered function to eat data from RTos send queues and transmit it
|
||||||
void processSendBuffer() {
|
void processSendBuffer() {
|
||||||
|
|
||||||
MessageBuffer_t SendBuffer;
|
MessageBuffer_t SendBuffer;
|
||||||
|
|
||||||
#ifdef HAS_LORA
|
#ifdef HAS_LORA
|
||||||
|
Loading…
Reference in New Issue
Block a user