timing improvements (separate mutexes for IRQ; Loraloop higher prio)
This commit is contained in:
		
							parent
							
								
									bad2331a6b
								
							
						
					
					
						commit
						43b4946252
					
				| @ -26,7 +26,7 @@ description = Paxcounter is a proof-of-concept ESP32 device for metering passeng | ||||
| 
 | ||||
| [common] | ||||
| ; 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! | ||||
| ; 0=None, 1=Error, 2=Warn, 3=Info, 4=Debug, 5=Verbose | ||||
| debug_level = 0 | ||||
|  | ||||
| @ -7,15 +7,15 @@ | ||||
| static const char TAG[] = "main"; | ||||
| 
 | ||||
| void IRAM_ATTR ButtonIRQ() { | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   portENTER_CRITICAL(&mutexButton); | ||||
|   ButtonPressedIRQ++; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
|   portEXIT_CRITICAL(&mutexButton); | ||||
| } | ||||
| 
 | ||||
| void readButton() { | ||||
|     portENTER_CRITICAL(&timerMux); | ||||
|     portENTER_CRITICAL(&mutexButton); | ||||
|     ButtonPressedIRQ = 0; | ||||
|     portEXIT_CRITICAL(&timerMux); | ||||
|     portEXIT_CRITICAL(&mutexButton); | ||||
|     ESP_LOGI(TAG, "Button pressed"); | ||||
|     payload.reset(); | ||||
|     payload.addButton(0x01); | ||||
|  | ||||
| @ -12,9 +12,9 @@ static const char TAG[] = "main"; | ||||
| // do all housekeeping
 | ||||
| void doHousekeeping() { | ||||
| 
 | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   portENTER_CRITICAL(&mutexHomeCycle); | ||||
|   HomeCycleIRQ = 0; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
|   portEXIT_CRITICAL(&mutexHomeCycle); | ||||
| 
 | ||||
|   // update uptime counter
 | ||||
|   uptime(); | ||||
| @ -69,9 +69,9 @@ void doHousekeeping() { | ||||
| } // doHousekeeping()
 | ||||
| 
 | ||||
| void IRAM_ATTR homeCycleIRQ() { | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   portENTER_CRITICAL(&mutexHomeCycle); | ||||
|   HomeCycleIRQ++; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
|   portEXIT_CRITICAL(&mutexHomeCycle); | ||||
| } | ||||
| 
 | ||||
| // uptime counter 64bit to prevent millis() rollover after 49 days
 | ||||
|  | ||||
| @ -2,7 +2,7 @@ | ||||
| #define _CYCLIC_H | ||||
| 
 | ||||
| void doHousekeeping(void); | ||||
| void homeCycleIRQ(void); | ||||
| void IRAM_ATTR homeCycleIRQ(void); | ||||
| uint64_t uptime(void); | ||||
| void reset_counters(void); | ||||
| int redirect_log(const char *fmt, va_list args); | ||||
|  | ||||
| @ -91,9 +91,9 @@ void init_display(const char *Productname, const char *Version) { | ||||
| 
 | ||||
| void refreshtheDisplay() { | ||||
| 
 | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   portENTER_CRITICAL(&mutexDisplay); | ||||
|   DisplayTimerIRQ = 0; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
|   portEXIT_CRITICAL(&mutexDisplay); | ||||
| 
 | ||||
|   // set display on/off according to current device configuration
 | ||||
|   if (DisplayState != cfg.screenon) { | ||||
| @ -191,9 +191,9 @@ void refreshtheDisplay() { | ||||
| } // refreshDisplay()
 | ||||
| 
 | ||||
| void IRAM_ATTR DisplayIRQ() { | ||||
|   portENTER_CRITICAL_ISR(&timerMux); | ||||
|   portENTER_CRITICAL_ISR(&mutexDisplay); | ||||
|   DisplayTimerIRQ++; | ||||
|   portEXIT_CRITICAL_ISR(&timerMux); | ||||
|   portEXIT_CRITICAL_ISR(&mutexDisplay); | ||||
| } | ||||
| 
 | ||||
| #endif // HAS_DISPLAY
 | ||||
| @ -9,6 +9,6 @@ extern HAS_DISPLAY u8x8; | ||||
| void init_display(const char *Productname, const char *Version); | ||||
| void refreshtheDisplay(void); | ||||
| void DisplayKey(const uint8_t *key, uint8_t len, bool lsb); | ||||
| void DisplayIRQ(void); | ||||
| void IRAM_ATTR DisplayIRQ(void); | ||||
| 
 | ||||
| #endif | ||||
| @ -46,7 +46,7 @@ extern uint16_t volatile macs_total, macs_wifi, macs_ble, | ||||
|     batt_voltage;               // display values
 | ||||
| extern std::set<uint16_t> macs; // temp storage for MACs
 | ||||
| extern hw_timer_t *channelSwitch, *sendCycle; | ||||
| extern portMUX_TYPE timerMux; | ||||
| extern portMUX_TYPE mutexButton, mutexDisplay, mutexHomeCycle, mutexSendCycle; | ||||
| extern volatile uint8_t SendCycleTimerIRQ, HomeCycleIRQ, DisplayTimerIRQ, | ||||
|     ChannelTimerIRQ, ButtonPressedIRQ; | ||||
| 
 | ||||
|  | ||||
| @ -34,9 +34,9 @@ | ||||
|  * 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; | ||||
|   int rem; | ||||
| 
 | ||||
|  | ||||
| @ -1,6 +1,9 @@ | ||||
| #ifndef _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 | ||||
							
								
								
									
										22
									
								
								src/main.cpp
									
									
									
									
									
								
							
							
						
						
									
										22
									
								
								src/main.cpp
									
									
									
									
									
								
							| @ -26,12 +26,12 @@ licenses. Refer to LICENSE.txt file in repository for more details. | ||||
| Uused tasks and timers: | ||||
| 
 | ||||
| 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 | ||||
| IDLE          1     0     Arduino loop() -> used for LED switching | ||||
| loraloop      1     1     runs the LMIC stack | ||||
| statemachine  1     3     switches application process logic | ||||
| loraloop      1     3     runs the LMIC stack | ||||
| statemachine  1     1     switches application process logic | ||||
| wifiloop      0     4     rotates wifi channels | ||||
| 
 | ||||
| ESP32 hardware timers | ||||
| @ -77,9 +77,11 @@ QueueHandle_t SPISendQueue; | ||||
| TaskHandle_t GpsTask = NULL; | ||||
| #endif | ||||
| 
 | ||||
| portMUX_TYPE timerMux = | ||||
|     portMUX_INITIALIZER_UNLOCKED; // sync main loop and ISR when modifying IRQ
 | ||||
|                                   // handler shared variables
 | ||||
| // sync main loop and ISR when modifying IRQ handler shared variables
 | ||||
| portMUX_TYPE mutexButton = portMUX_INITIALIZER_UNLOCKED; | ||||
| 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
 | ||||
| 
 | ||||
| @ -312,7 +314,7 @@ void setup() { | ||||
|                           "loraloop",   /* name of task */ | ||||
|                           2560,         /* stack size of task */ | ||||
|                           (void *)1,    /* parameter of the task */ | ||||
|                           1,            /* priority of the task */ | ||||
|                           3,            /* priority of the task */ | ||||
|                           &LoraTask,    /* task handle*/ | ||||
|                           1);           /* CPU core */ | ||||
| #endif | ||||
| @ -350,7 +352,7 @@ void setup() { | ||||
|   // start wifi channel rotation task
 | ||||
|   xTaskCreatePinnedToCore(switchWifiChannel, /* task function */ | ||||
|                           "wifiloop",        /* name of task */ | ||||
|                           1024,              /* stack size of task */ | ||||
|                           1536,              /* stack size of task */ | ||||
|                           NULL,              /* parameter of the task */ | ||||
|                           4,                 /* priority of the task */ | ||||
|                           &wifiSwitchTask,   /* task handle*/ | ||||
| @ -362,7 +364,7 @@ void setup() { | ||||
|                           "stateloop",       /* name of task */ | ||||
|                           2048,              /* stack size of task */ | ||||
|                           (void *)1,         /* parameter of the task */ | ||||
|                           3,                 /* priority of the task */ | ||||
|                           1,                 /* priority of the task */ | ||||
|                           &stateMachineTask, /* task handle */ | ||||
|                           1);                /* CPU core */ | ||||
| 
 | ||||
|  | ||||
| @ -314,7 +314,8 @@ void do_ota_update() { | ||||
|   client.stop(); | ||||
| } // 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 | ||||
|   u8x8.setCursor(14, row); | ||||
|   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.print(msg.substr(0, 16).c_str()); | ||||
|   } | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| #ifdef HAS_DISPLAY | ||||
| // callback function to show download progress while streaming data
 | ||||
| void show_progress(size_t current, size_t size) { | ||||
|   char buf[17]; | ||||
|   snprintf(buf, 17, "%-9lu (%3lu%%)", current, current * 100 / size); | ||||
|   display(4, "**", buf); | ||||
| #endif | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| // helper function to compare two versions. Returns 1 if v2 is
 | ||||
| // smaller, -1 if v1 is smaller, 0 if equal
 | ||||
|  | ||||
| @ -14,8 +14,11 @@ | ||||
| void do_ota_update(); | ||||
| void start_ota_update(); | ||||
| 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 display(const uint8_t row, const std::string status, const std::string msg); | ||||
| #endif | ||||
| 
 | ||||
| #endif // USE_OTA
 | ||||
| 
 | ||||
|  | ||||
| @ -37,9 +37,9 @@ void SendData(uint8_t port) { | ||||
| // interrupt triggered function to prepare payload to send
 | ||||
| void sendPayload() { | ||||
| 
 | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   portENTER_CRITICAL(&mutexSendCycle); | ||||
|   SendCycleTimerIRQ = 0; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
|   portEXIT_CRITICAL(&mutexSendCycle); | ||||
| 
 | ||||
|   // append counter data to payload
 | ||||
|   payload.reset(); | ||||
| @ -68,9 +68,9 @@ void sendPayload() { | ||||
| 
 | ||||
| // interrupt handler used for payload send cycle timer
 | ||||
| void IRAM_ATTR SendCycleIRQ() { | ||||
|   portENTER_CRITICAL(&timerMux); | ||||
|   portENTER_CRITICAL(&mutexSendCycle); | ||||
|   SendCycleTimerIRQ++; | ||||
|   portEXIT_CRITICAL(&timerMux); | ||||
|   portEXIT_CRITICAL(&mutexSendCycle); | ||||
| } | ||||
| 
 | ||||
| // interrupt triggered function to eat data from send queues and transmit it
 | ||||
|  | ||||
| @ -3,7 +3,7 @@ | ||||
| 
 | ||||
| void SendData(uint8_t port); | ||||
| void sendPayload(void); | ||||
| void SendCycleIRQ(void); | ||||
| void IRAM_ATTR SendCycleIRQ(void); | ||||
| void checkSendQueues(void); | ||||
| void flushQueues(); | ||||
| 
 | ||||
|  | ||||
| @ -31,4 +31,5 @@ void stateMachine(void *pvParameters) { | ||||
|     // give yield to CPU
 | ||||
|     vTaskDelay(2 / portTICK_PERIOD_MS); | ||||
|   } | ||||
|   vTaskDelete(NULL); // shoud never be reached
 | ||||
| } | ||||
| @ -28,6 +28,7 @@ IRAM_ATTR void wifi_sniffer_packet_handler(void *buff, | ||||
| void wifi_sniffer_init(void) { | ||||
|   wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); | ||||
|   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 = { | ||||
|       .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_LOGD(TAG, "Wifi set channel %d", channel); | ||||
|   } | ||||
|   vTaskDelete(NULL); | ||||
|   vTaskDelete(NULL); // shoud never be reached
 | ||||
| } | ||||
|  | ||||
| @ -26,7 +26,7 @@ typedef struct { | ||||
| } wifi_ieee80211_packet_t; | ||||
| 
 | ||||
| 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 switchWifiChannel(void * parameter); | ||||
| 
 | ||||
|  | ||||
		Loading…
	
		Reference in New Issue
	
	Block a user