tasking + statemachine restructured

This commit is contained in:
Klaus K Wilting 2018-09-21 18:23:34 +02:00
parent 67832da09d
commit 5b9327512b
6 changed files with 93 additions and 75 deletions

View File

@ -10,7 +10,11 @@
static const char TAG[] = "main";
// do all housekeeping
void doHomework() {
void doHousekeeping() {
portENTER_CRITICAL(&timerMux);
HomeCycleIRQ = 0;
portEXIT_CRITICAL(&timerMux);
// update uptime counter
uptime();
@ -49,16 +53,7 @@ void doHomework() {
if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again
esp_restart(); // memory leak, reset device
}
} // doHomework()
void checkHousekeeping() {
if (HomeCycleIRQ) {
portENTER_CRITICAL(&timerMux);
HomeCycleIRQ = 0;
portEXIT_CRITICAL(&timerMux);
doHomework();
}
}
} // doHousekeeping()
void IRAM_ATTR homeCycleIRQ() {
portENTER_CRITICAL(&timerMux);

View File

@ -1,8 +1,7 @@
#ifndef _CYCLIC_H
#define _CYCLIC_H
void doHomework(void);
void checkHousekeeping(void);
void doHousekeeping(void);
void homeCycleIRQ(void);
uint64_t uptime(void);
void reset_counters(void);

View File

@ -33,14 +33,14 @@ uint16_t macs_total = 0, macs_wifi = 0, macs_ble = 0,
batt_voltage = 0; // globals for display
// hardware timer for cyclic tasks
hw_timer_t *channelSwitch = NULL, *displaytimer = NULL, *sendCycle = NULL,
*homeCycle = NULL;
hw_timer_t *channelSwitch, *displaytimer, *sendCycle, *homeCycle;
// this variables will be changed in the ISR, and read in main loop
volatile int ButtonPressedIRQ = 0, ChannelTimerIRQ = 0, SendCycleTimerIRQ = 0,
DisplayTimerIRQ = 0, HomeCycleIRQ = 0;
TaskHandle_t WifiLoopTask = NULL;
TaskHandle_t StateTask = NULL;
// RTos send queues for payload transmit
#ifdef HAS_LORA
@ -68,9 +68,6 @@ PayloadConvert payload(PAYLOAD_BUFFER_SIZE);
// local Tag for logging
static const char TAG[] = "main";
/* begin Aruino SETUP
* ------------------------------------------------------------ */
void setup() {
// disable the default wifi logging
@ -229,6 +226,7 @@ void setup() {
// reload interrupt after each trigger of display refresh cycle
timerAlarmWrite(displaytimer, DISPLAYREFRESH_MS * 1000, true);
// enable display interrupt
yield();
timerAlarmEnable(displaytimer);
#endif
@ -236,7 +234,6 @@ void setup() {
channelSwitch = timerBegin(1, 800, true);
timerAttachInterrupt(channelSwitch, &ChannelSwitchIRQ, 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
sendCycle = timerBegin(2, 8000, true);
@ -248,9 +245,13 @@ void setup() {
timerAttachInterrupt(homeCycle, &homeCycleIRQ, 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);
yield();
timerAlarmEnable(sendCycle);
yield();
timerAlarmEnable(channelSwitch);
// show payload encoder
@ -283,13 +284,35 @@ void setup() {
// join network
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
// (note: arduino main loop runs on core 1, too)
// https://techtutorialsx.com/2017/05/09/esp32-get-task-execution-core/
ESP_LOGI(TAG, "Starting Lora...");
xTaskCreatePinnedToCore(lorawan_loop, "loraloop", 2048, (void *)1,
(5 | portPRIVILEGE_BIT), &LoraTask, 1);
xTaskCreatePinnedToCore(lorawan_loop, "loraloop", 2048, (void *)1, 1,
&LoraTask, 1);
#endif
// if device has GPS and it is enabled, start GPS reader task on core 0 with
@ -317,41 +340,43 @@ void setup() {
reset_salt(); // get new 16bit for salting hashes
xTaskCreatePinnedToCore(wifi_channel_loop, "wifiloop", 2048, (void *)1, 1,
&WifiLoopTask, 0);
// start state machine
ESP_LOGI(TAG, "Starting Statemachine...");
xTaskCreatePinnedToCore(stateMachine, "stateloop", 2048, (void *)1, 3,
&StateTask, 1);
} // setup()
/* end Arduino SETUP
* ------------------------------------------------------------ */
void stateMachine(void *pvParameters) {
/* begin Arduino main loop
* ------------------------------------------------------ */
configASSERT(((uint32_t)pvParameters) == 1); // FreeRTOS check
void loop() {
// state machine for switching display, LED, button, housekeeping,
// senddata
while (1) {
#if (HAS_LED != NOT_A_PIN) || defined(HAS_RGB_LED)
led_loop();
led_loop();
#endif
#ifdef HAS_BUTTON
readButton();
readButton();
#endif
#ifdef HAS_DISPLAY
updateDisplay();
updateDisplay();
#endif
// check housekeeping cycle and if expired do homework
checkHousekeeping();
// check send queue and process it
processSendBuffer();
// check send cycle and enqueue payload if cycle is expired
sendPayload();
// yield to CPU
vTaskDelay(2 / portTICK_PERIOD_MS);
// check housekeeping cycle and if expired do the work
if (HomeCycleIRQ)
doHousekeeping();
// check send queue and process it
processSendBuffer();
// check send cycle and enqueue payload if cycle is expired
if (SendCycleTimerIRQ)
sendPayload();
// yield to CPU
vTaskDelay(2 / portTICK_PERIOD_MS);
}
}
} // loop()
/* end Arduino main loop
* ------------------------------------------------------------ */
void loop() { vTaskDelay(2 / portTICK_PERIOD_MS); }

View File

@ -13,5 +13,8 @@
#include <esp_spi_flash.h> // needed for reading ESP32 chip attributes
#include <esp_event_loop.h> // needed for Wifi event handler
#include <esp32-hal-timer.h> // needed for timers
void stateMachine(void *pvParameters);
#endif

View File

@ -246,7 +246,7 @@ int version_compare(const String v1, const String v2) {
// vnum stores each numeric part of version
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());) {
// storing numeric part of version 1 in vnum1
while (i < v1.length() && v1[i] != '.') {

View File

@ -34,39 +34,36 @@ void SendData(uint8_t port) {
}
} // SendData
// cyclic called function to prepare payload to send
// interrupt triggered function to prepare payload to send
void sendPayload() {
if (SendCycleTimerIRQ) {
portENTER_CRITICAL(&timerMux);
SendCycleTimerIRQ = 0;
portEXIT_CRITICAL(&timerMux);
portENTER_CRITICAL(&timerMux);
SendCycleTimerIRQ = 0;
portEXIT_CRITICAL(&timerMux);
// append counter data to payload
payload.reset();
payload.addCount(macs_wifi, cfg.blescan ? macs_ble : 0);
// append GPS data, if present
// append counter data to payload
payload.reset();
payload.addCount(macs_wifi, cfg.blescan ? macs_ble : 0);
// append GPS data, if present
#ifdef HAS_GPS
// show NMEA data in debug mode, useful for debugging GPS on board
// connection
ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
gps.passedChecksum(), gps.failedChecksum(),
gps.sentencesWithFix());
// log GPS position if we have a fix and gps data mode is enabled
if ((cfg.gpsmode) && (gps.location.isValid())) {
gps_read();
payload.addGPS(gps_status);
ESP_LOGD(TAG, "lat=%.6f | lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%um",
gps_status.latitude / (float)1e6,
gps_status.longitude / (float)1e6, gps_status.satellites,
gps_status.hdop / (float)100, gps_status.altitude);
} else {
ESP_LOGD(TAG, "No valid GPS position or GPS data mode disabled");
}
#endif
SendData(COUNTERPORT);
// show NMEA data in debug mode, useful for debugging GPS on board
// connection
ESP_LOGD(TAG, "GPS NMEA data: passed %d / failed: %d / with fix: %d",
gps.passedChecksum(), gps.failedChecksum(), gps.sentencesWithFix());
// log GPS position if we have a fix and gps data mode is enabled
if ((cfg.gpsmode) && (gps.location.isValid())) {
gps_read();
payload.addGPS(gps_status);
ESP_LOGD(TAG, "lat=%.6f | lon=%.6f | %u Sats | HDOP=%.1f | Altitude=%um",
gps_status.latitude / (float)1e6,
gps_status.longitude / (float)1e6, gps_status.satellites,
gps_status.hdop / (float)100, gps_status.altitude);
} else {
ESP_LOGD(TAG, "No valid GPS position or GPS data mode disabled");
}
#endif
SendData(COUNTERPORT);
} // sendpayload()
// interrupt handler used for payload send cycle timer
@ -76,9 +73,8 @@ void IRAM_ATTR SendCycleIRQ() {
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() {
MessageBuffer_t SendBuffer;
#ifdef HAS_LORA