timing improvements (separate mutexes for IRQ; Loraloop higher prio)

This commit is contained in:
Klaus K Wilting 2018-09-30 15:08:00 +02:00
parent bad2331a6b
commit 43b4946252
17 changed files with 53 additions and 40 deletions

View File

@ -26,7 +26,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng
[common] [common]
; for release_version use max. 10 chars total, use any decimal format like "a.b.c" ; for release_version use max. 10 chars total, use any decimal format like "a.b.c"
release_version = 1.5.8 release_version = 1.5.9
; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running! ; DEBUG LEVEL: For production run set to 0, otherwise device will leak RAM while running!
; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose
debug_level = 0 debug_level = 0

View File

@ -7,15 +7,15 @@
static const char TAG[] = "main"; static const char TAG[] = "main";
void IRAM_ATTR ButtonIRQ() { void IRAM_ATTR ButtonIRQ() {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&mutexButton);
ButtonPressedIRQ++; ButtonPressedIRQ++;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&mutexButton);
} }
void readButton() { void readButton() {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&mutexButton);
ButtonPressedIRQ = 0; ButtonPressedIRQ = 0;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&mutexButton);
ESP_LOGI(TAG, "Button pressed"); ESP_LOGI(TAG, "Button pressed");
payload.reset(); payload.reset();
payload.addButton(0x01); payload.addButton(0x01);

View File

@ -12,9 +12,9 @@ static const char TAG[] = "main";
// do all housekeeping // do all housekeeping
void doHousekeeping() { void doHousekeeping() {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&mutexHomeCycle);
HomeCycleIRQ = 0; HomeCycleIRQ = 0;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&mutexHomeCycle);
// update uptime counter // update uptime counter
uptime(); uptime();
@ -69,9 +69,9 @@ void doHousekeeping() {
} // doHousekeeping() } // doHousekeeping()
void IRAM_ATTR homeCycleIRQ() { void IRAM_ATTR homeCycleIRQ() {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&mutexHomeCycle);
HomeCycleIRQ++; HomeCycleIRQ++;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&mutexHomeCycle);
} }
// uptime counter 64bit to prevent millis() rollover after 49 days // uptime counter 64bit to prevent millis() rollover after 49 days

View File

@ -2,7 +2,7 @@
#define _CYCLIC_H #define _CYCLIC_H
void doHousekeeping(void); void doHousekeeping(void);
void homeCycleIRQ(void); void IRAM_ATTR homeCycleIRQ(void);
uint64_t uptime(void); uint64_t uptime(void);
void reset_counters(void); void reset_counters(void);
int redirect_log(const char *fmt, va_list args); int redirect_log(const char *fmt, va_list args);

View File

@ -91,9 +91,9 @@ void init_display(const char *Productname, const char *Version) {
void refreshtheDisplay() { void refreshtheDisplay() {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&mutexDisplay);
DisplayTimerIRQ = 0; DisplayTimerIRQ = 0;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&mutexDisplay);
// set display on/off according to current device configuration // set display on/off according to current device configuration
if (DisplayState != cfg.screenon) { if (DisplayState != cfg.screenon) {
@ -191,9 +191,9 @@ void refreshtheDisplay() {
} // refreshDisplay() } // refreshDisplay()
void IRAM_ATTR DisplayIRQ() { void IRAM_ATTR DisplayIRQ() {
portENTER_CRITICAL_ISR(&timerMux); portENTER_CRITICAL_ISR(&mutexDisplay);
DisplayTimerIRQ++; DisplayTimerIRQ++;
portEXIT_CRITICAL_ISR(&timerMux); portEXIT_CRITICAL_ISR(&mutexDisplay);
} }
#endif // HAS_DISPLAY #endif // HAS_DISPLAY

View File

@ -9,6 +9,6 @@ extern HAS_DISPLAY u8x8;
void init_display(const char *Productname, const char *Version); void init_display(const char *Productname, const char *Version);
void refreshtheDisplay(void); void refreshtheDisplay(void);
void DisplayKey(const uint8_t *key, uint8_t len, bool lsb); void DisplayKey(const uint8_t *key, uint8_t len, bool lsb);
void DisplayIRQ(void); void IRAM_ATTR DisplayIRQ(void);
#endif #endif

View File

@ -46,7 +46,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble,
batt_voltage; // display values batt_voltage; // display values
extern std::set<uint16_t> macs; // temp storage for MACs extern std::set<uint16_t> macs; // temp storage for MACs
extern hw_timer_t *channelSwitch, *sendCycle; extern hw_timer_t *channelSwitch, *sendCycle;
extern portMUX_TYPE timerMux; extern portMUX_TYPE mutexButton, mutexDisplay, mutexHomeCycle, mutexSendCycle;
extern volatile uint8_t SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ, extern volatile uint8_t SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ,
ChannelTimerIRQ, ButtonPressedIRQ; ChannelTimerIRQ, ButtonPressedIRQ;

View File

@ -34,9 +34,9 @@
* SOFTWARE. * SOFTWARE.
*/ */
#include <inttypes.h> #include "hash.h"
uint32_t rokkit(const char *data, int len) { uint32_t IRAM_ATTR rokkit(const char *data, int len) {
uint32_t hash, tmp; uint32_t hash, tmp;
int rem; int rem;

View File

@ -1,6 +1,9 @@
#ifndef _HASH_H #ifndef _HASH_H
#define _HASH_H #define _HASH_H
uint32_t rokkit(const char *data, int len); #include <Arduino.h>
#include <inttypes.h>
#endif uint32_t IRAM_ATTR rokkit(const char *data, int len);
#endif

View File

@ -26,12 +26,12 @@ licenses. Refer to LICENSE.txt file in repository for more details.
Uused tasks and timers: Uused tasks and timers:
Task Core Prio Purpose Task Core Prio Purpose
==================================================================== ====================================================================================
IDLE 0 0 ESP32 arduino scheduler IDLE 0 0 ESP32 arduino scheduler -> runs wifi sniffer task
gpsloop 0 2 read data from GPS over serial or i2c gpsloop 0 2 read data from GPS over serial or i2c
IDLE 1 0 Arduino loop() -> used for LED switching IDLE 1 0 Arduino loop() -> used for LED switching
loraloop 1 1 runs the LMIC stack loraloop 1 3 runs the LMIC stack
statemachine 1 3 switches application process logic statemachine 1 1 switches application process logic
wifiloop 0 4 rotates wifi channels wifiloop 0 4 rotates wifi channels
ESP32 hardware timers ESP32 hardware timers
@ -77,9 +77,11 @@ QueueHandle_t SPISendQueue;
TaskHandle_t GpsTask = NULL; TaskHandle_t GpsTask = NULL;
#endif #endif
portMUX_TYPE timerMux = // sync main loop and ISR when modifying IRQ handler shared variables
portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ portMUX_TYPE mutexButton = portMUX_INITIALIZER_UNLOCKED;
// handler shared variables portMUX_TYPE mutexDisplay = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE mutexHomeCycle = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE mutexSendCycle = portMUX_INITIALIZER_UNLOCKED;
std::set<uint16_t> macs; // container holding unique MAC adress hashes std::set<uint16_t> macs; // container holding unique MAC adress hashes
@ -312,7 +314,7 @@ void setup() {
"loraloop", /* name of task */ "loraloop", /* name of task */
2560, /* stack size of task */ 2560, /* stack size of task */
(void *)1, /* parameter of the task */ (void *)1, /* parameter of the task */
1, /* priority of the task */ 3, /* priority of the task */
&LoraTask, /* task handle*/ &LoraTask, /* task handle*/
1); /* CPU core */ 1); /* CPU core */
#endif #endif
@ -350,7 +352,7 @@ void setup() {
// start wifi channel rotation task // start wifi channel rotation task
xTaskCreatePinnedToCore(switchWifiChannel, /* task function */ xTaskCreatePinnedToCore(switchWifiChannel, /* task function */
"wifiloop", /* name of task */ "wifiloop", /* name of task */
1024, /* stack size of task */ 1536, /* stack size of task */
NULL, /* parameter of the task */ NULL, /* parameter of the task */
4, /* priority of the task */ 4, /* priority of the task */
&wifiSwitchTask, /* task handle*/ &wifiSwitchTask, /* task handle*/
@ -362,7 +364,7 @@ void setup() {
"stateloop", /* name of task */ "stateloop", /* name of task */
2048, /* stack size of task */ 2048, /* stack size of task */
(void *)1, /* parameter of the task */ (void *)1, /* parameter of the task */
3, /* priority of the task */ 1, /* priority of the task */
&stateMachineTask, /* task handle */ &stateMachineTask, /* task handle */
1); /* CPU core */ 1); /* CPU core */

View File

@ -314,7 +314,8 @@ void do_ota_update() {
client.stop(); client.stop();
} // do_ota_update } // do_ota_update
void display(const uint8_t row, const std::string status, const std::string msg) { void display(const uint8_t row, const std::string status,
const std::string msg) {
#ifdef HAS_DISPLAY #ifdef HAS_DISPLAY
u8x8.setCursor(14, row); u8x8.setCursor(14, row);
u8x8.print((status.substr(0, 2)).c_str()); u8x8.print((status.substr(0, 2)).c_str());
@ -323,15 +324,17 @@ void display(const uint8_t row, const std::string status, const std::string msg)
u8x8.setCursor(0, 7); u8x8.setCursor(0, 7);
u8x8.print(msg.substr(0, 16).c_str()); u8x8.print(msg.substr(0, 16).c_str());
} }
#endif
} }
#ifdef HAS_DISPLAY
// callback function to show download progress while streaming data // callback function to show download progress while streaming data
void show_progress(size_t current, size_t size) { void show_progress(size_t current, size_t size) {
char buf[17]; char buf[17];
snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size); snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size);
display(4, "**", buf); display(4, "**", buf);
#endif
} }
#endif
// helper function to compare two versions. Returns 1 if v2 is // helper function to compare two versions. Returns 1 if v2 is
// smaller, -1 if v1 is smaller, 0 if equal // smaller, -1 if v1 is smaller, 0 if equal

View File

@ -14,8 +14,11 @@
void do_ota_update(); void do_ota_update();
void start_ota_update(); void start_ota_update();
int version_compare(const String v1, const String v2); int version_compare(const String v1, const String v2);
void display(const uint8_t row, const std::string status,
const std::string msg);
#ifdef HAS_DISPLAY
void show_progress(size_t current, size_t size); void show_progress(size_t current, size_t size);
void display(const uint8_t row, const std::string status, const std::string msg); #endif
#endif // USE_OTA #endif // USE_OTA

View File

@ -37,9 +37,9 @@ void SendData(uint8_t port) {
// interrupt triggered function to prepare payload to send // interrupt triggered function to prepare payload to send
void sendPayload() { void sendPayload() {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&mutexSendCycle);
SendCycleTimerIRQ = 0; SendCycleTimerIRQ = 0;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&mutexSendCycle);
// append counter data to payload // append counter data to payload
payload.reset(); payload.reset();
@ -68,9 +68,9 @@ void sendPayload() {
// interrupt handler used for payload send cycle timer // interrupt handler used for payload send cycle timer
void IRAM_ATTR SendCycleIRQ() { void IRAM_ATTR SendCycleIRQ() {
portENTER_CRITICAL(&timerMux); portENTER_CRITICAL(&mutexSendCycle);
SendCycleTimerIRQ++; SendCycleTimerIRQ++;
portEXIT_CRITICAL(&timerMux); portEXIT_CRITICAL(&mutexSendCycle);
} }
// interrupt triggered function to eat data from send queues and transmit it // interrupt triggered function to eat data from send queues and transmit it

View File

@ -3,7 +3,7 @@
void SendData(uint8_t port); void SendData(uint8_t port);
void sendPayload(void); void sendPayload(void);
void SendCycleIRQ(void); void IRAM_ATTR SendCycleIRQ(void);
void checkSendQueues(void); void checkSendQueues(void);
void flushQueues(); void flushQueues();

View File

@ -31,4 +31,5 @@ void stateMachine(void *pvParameters) {
// give yield to CPU // give yield to CPU
vTaskDelay(2 / portTICK_PERIOD_MS); vTaskDelay(2 / portTICK_PERIOD_MS);
} }
vTaskDelete(NULL); // shoud never be reached
} }

View File

@ -28,6 +28,7 @@ IRAM_ATTR void wifi_sniffer_packet_handler(void *buff,
void wifi_sniffer_init(void) { void wifi_sniffer_init(void) {
wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM cfg.nvs_enable = 0; // we don't need any wifi settings from NVRAM
cfg.wifi_task_core_id = 0; // we want wifi task running on core 0
wifi_promiscuous_filter_t filter = { wifi_promiscuous_filter_t filter = {
.filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames .filter_mask = WIFI_PROMIS_FILTER_MASK_MGMT}; // we need only MGMT frames
@ -64,5 +65,5 @@ void switchWifiChannel(void * parameter) {
esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE); esp_wifi_set_channel(channel, WIFI_SECOND_CHAN_NONE);
ESP_LOGD(TAG, "Wifi set channel %d", channel); ESP_LOGD(TAG, "Wifi set channel %d", channel);
} }
vTaskDelete(NULL); vTaskDelete(NULL); // shoud never be reached
} }

View File

@ -26,7 +26,7 @@ typedef struct {
} wifi_ieee80211_packet_t; } wifi_ieee80211_packet_t;
void wifi_sniffer_init(void); void wifi_sniffer_init(void);
void wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type); void IRAM_ATTR wifi_sniffer_packet_handler(void *buff, wifi_promiscuous_pkt_type_t type);
void ChannelSwitchIRQ(void); void ChannelSwitchIRQ(void);
void switchWifiChannel(void * parameter); void switchWifiChannel(void * parameter);