diff --git a/include/cyclic.h b/include/cyclic.h index e263a678..1c4da4dd 100644 --- a/include/cyclic.h +++ b/include/cyclic.h @@ -12,5 +12,6 @@ void do_timesync(void); uint64_t uptime(void); void reset_counters(void); int redirect_log(const char *fmt, va_list args); +uint32_t getFreeRAM(); #endif \ No newline at end of file diff --git a/include/display.h b/include/display.h index 492af565..99379b58 100644 --- a/include/display.h +++ b/include/display.h @@ -2,6 +2,7 @@ #define _DISPLAY_H #include +#include "cyclic.h" extern uint8_t volatile DisplayState; extern HAS_DISPLAY u8x8; diff --git a/include/globals.h b/include/globals.h index da547af3..8c429048 100644 --- a/include/globals.h +++ b/include/globals.h @@ -8,6 +8,7 @@ #include #include #include +#include "Mallocator.h" // sniffing types #define MAC_SNIFF_WIFI 0 @@ -87,9 +88,9 @@ extern char display_line6[], display_line7[]; // screen buffers extern uint8_t volatile channel; // wifi channel rotation counter extern uint16_t volatile macs_total, macs_wifi, macs_ble, batt_voltage; // display values -extern std::set macs; // temp storage for MACs extern hw_timer_t *channelSwitch, *sendCycle, *displaytimer; +extern std::set, Mallocator> macs; extern std::array::iterator it; extern std::array beacons; diff --git a/include/macsniff.h b/include/macsniff.h index 81e5a2ed..d41fc787 100644 --- a/include/macsniff.h +++ b/include/macsniff.h @@ -6,8 +6,8 @@ // Hash function for scrambling MAC addresses #include "hash.h" - #include "senddata.h" +#include "cyclic.h" #define MAC_SNIFF_WIFI 0 #define MAC_SNIFF_BLE 1 diff --git a/include/mallocator.h b/include/mallocator.h new file mode 100644 index 00000000..7d32d409 --- /dev/null +++ b/include/mallocator.h @@ -0,0 +1,54 @@ +/* + +This Mallocator code was taken from: + +CppCon2014 Presentations +STL Features And Implementation Techniques +Stephan T. Lavavej + +https://github.com/CppCon/CppCon2014 + +*/ + + +#ifndef _MALLOCATOR_H +#define _MALLOCATOR_H + +#include // size_t, malloc, free +#include // bad_alloc, bad_array_new_length +#include "esp32-hal-psram.h" // ps_malloc + +template struct Mallocator { + typedef T value_type; + Mallocator() noexcept {} // default ctor not required + template Mallocator(const Mallocator &) noexcept {} + template bool operator==(const Mallocator &) const noexcept { + return true; + } + template bool operator!=(const Mallocator &) const noexcept { + return false; + } + + T *allocate(const size_t n) const { + if (n == 0) { + return nullptr; + } + if (n > static_cast(-1) / sizeof(T)) { + throw std::bad_array_new_length(); + } + +#ifndef BOARD_HAS_PSRAM + void *const pv = malloc(n * sizeof(T)); +#else + void *const pv = ps_malloc(n * sizeof(T)); +#endif + + if (!pv) { + throw std::bad_alloc(); + } + return static_cast(pv); + } + void deallocate(T *const p, size_t) const noexcept { free(p); } +}; + +#endif \ No newline at end of file diff --git a/include/rcommand.h b/include/rcommand.h index 806f911a..269caf91 100644 --- a/include/rcommand.h +++ b/include/rcommand.h @@ -7,6 +7,7 @@ #include "lorawan.h" #include "macsniff.h" #include +#include "cyclic.h" // table of remote commands and assigned functions typedef struct { diff --git a/platformio.ini b/platformio.ini index e3423f2e..461cc403 100644 --- a/platformio.ini +++ b/platformio.ini @@ -30,13 +30,13 @@ 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.6.996 +release_version = 1.7.01 ; 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 ; UPLOAD MODE: select esptool to flash via USB/UART, select custom to upload to cloud for OTA -;upload_protocol = esptool -upload_protocol = custom +upload_protocol = esptool +;upload_protocol = custom extra_scripts = pre:build.py keyfile = ota.conf ;platform_espressif32 = espressif32@1.5.0 @@ -207,7 +207,7 @@ monitor_speed = ${common.monitor_speed} platform = ${common.platform_espressif32} framework = arduino board = esp32dev -;board = t-beam +;board = ttgo-t-beam board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = @@ -217,6 +217,7 @@ lib_deps = build_flags = ${common.build_flags_all} -mfix-esp32-psram-cache-issue + -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} @@ -225,7 +226,7 @@ monitor_speed = ${common.monitor_speed} platform = ${common.platform_espressif32} framework = arduino board = esp32dev -;board = t-beam +;board = ttgo-t-beam board_build.partitions = ${common.board_build.partitions} upload_speed = 921600 lib_deps = @@ -235,6 +236,7 @@ lib_deps = build_flags = ${common.build_flags_all} -mfix-esp32-psram-cache-issue + -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} @@ -287,6 +289,7 @@ lib_deps = build_flags = ${common.build_flags_basic} -mfix-esp32-psram-cache-issue + -DBOARD_HAS_PSRAM upload_protocol = ${common.upload_protocol} extra_scripts = ${common.extra_scripts} monitor_speed = ${common.monitor_speed} diff --git a/src/cyclic.cpp b/src/cyclic.cpp index 137ea7f6..80e16f1f 100644 --- a/src/cyclic.cpp +++ b/src/cyclic.cpp @@ -55,19 +55,33 @@ void doHousekeeping() { ESP_LOGI(TAG, "Measured Voltage: %dmV", batt_voltage); #endif - // check free memory - if (esp_get_minimum_free_heap_size() <= MEM_LOW) { + // check free heap memory + if (ESP.getMinFreeHeap() <= MEM_LOW) { ESP_LOGI(TAG, "Memory full, counter cleared (heap low water mark = %d Bytes / " "free heap = %d bytes)", - esp_get_minimum_free_heap_size(), ESP.getFreeHeap()); + ESP.getMinFreeHeap() , ESP.getFreeHeap()); SendPayload(COUNTERPORT); // send data before clearing counters reset_counters(); // clear macs container and reset all counters get_salt(); // get new salt for salting hashes - if (esp_get_minimum_free_heap_size() <= MEM_LOW) // check again + if (ESP.getMinFreeHeap() <= MEM_LOW) // check again do_reset(); // memory leak, reset device } + +// check free PSRAM memory +#ifdef BOARD_HAS_PSRAM + if (ESP.getMinFreePsram() <= MEM_LOW) { + ESP_LOGI(TAG, "PSRAM full, counter cleared"); + SendPayload(COUNTERPORT); // send data before clearing counters + reset_counters(); // clear macs container and reset all counters + get_salt(); // get new salt for salting hashes + + if (ESP.getMinFreePsram() <= MEM_LOW) // check again + do_reset(); // memory leak, reset device + } +#endif + } // doHousekeeping() // uptime counter 64bit to prevent millis() rollover after 49 days @@ -80,6 +94,14 @@ uint64_t uptime() { return (uint64_t)high32 << 32 | low32; } +uint32_t getFreeRAM() { +#ifndef BOARD_HAS_PSRAM + return ESP.getFreeHeap(); +#else + return ESP.getFreePsram(); +#endif +} + void reset_counters() { macs.clear(); // clear all macs container macs_total = 0; // reset all counters diff --git a/src/display.cpp b/src/display.cpp index 63f56831..ff78ec2b 100644 --- a/src/display.cpp +++ b/src/display.cpp @@ -166,7 +166,7 @@ void refreshtheDisplay() { u8x8.setCursor(0, 5); u8x8.printf(!cfg.rssilimit ? "RLIM:off " : "RLIM:%-4d", cfg.rssilimit); u8x8.setCursor(10, 5); - u8x8.printf("%4dKB", ESP.getFreeHeap() / 1024); + u8x8.printf("%4dKB", getFreeRAM() / 1024); #ifdef HAS_LORA // update LoRa status display (line 6) diff --git a/src/hal/ttgobeam_new.h b/src/hal/ttgobeam_new.h index 45f77d3c..1a4552a9 100644 --- a/src/hal/ttgobeam_new.h +++ b/src/hal/ttgobeam_new.h @@ -13,18 +13,17 @@ // BME680 sensor on I2C bus // don't forget to connect SDIO of BME680 to GND for selecting i2c addr 0x76 // -#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL +//#define HAS_BME GPIO_NUM_21, GPIO_NUM_22 // SDA, SCL #define HAS_LED GPIO_NUM_14 // on board green LED // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors -#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C -// Pins for I2C interface of OLED Display -#define MY_OLED_SDA (21) -#define MY_OLED_SCL (22) -#define MY_OLED_RST (NOT_A_PIN) +//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +//#define MY_OLED_SDA (21) +//#define MY_OLED_SCL (22) +//#define MY_OLED_RST (NOT_A_PIN) //#define DISPLAY_FLIP 1 // use if display is rotated #define HAS_LORA 1 // comment out if device shall not send data via LoRa diff --git a/src/hal/ttgobeam_old.h b/src/hal/ttgobeam_old.h index e7d39287..f8e530fc 100644 --- a/src/hal/ttgobeam_old.h +++ b/src/hal/ttgobeam_old.h @@ -19,6 +19,12 @@ // user defined sensors //#define HAS_SENSORS 1 // comment out if device has user defined sensors +//#define HAS_DISPLAY U8X8_SSD1306_128X64_NONAME_HW_I2C +//#define MY_OLED_SDA (21) +//#define MY_OLED_SCL (22) +//#define MY_OLED_RST (NOT_A_PIN) +//#define DISPLAY_FLIP 1 // use if display is rotated + #define HAS_LORA 1 // comment out if device shall not send data via LoRa #define CFG_sx1276_radio 1 // HPD13A LoRa SoC #define BOARD_HAS_PSRAM // use extra 4MB external RAM diff --git a/src/macsniff.cpp b/src/macsniff.cpp index 920ec091..b1e5ffcc 100644 --- a/src/macsniff.cpp +++ b/src/macsniff.cpp @@ -119,7 +119,8 @@ bool mac_add(uint8_t *paddr, int8_t rssi, bool sniff_type) { "%d Bytes left", added ? "new " : "known", sniff_type == MAC_SNIFF_WIFI ? "WiFi" : "BLTH", rssi, buff, - hashedmac, macs_wifi, macs_ble, ESP.getFreeHeap()); + hashedmac, macs_wifi, macs_ble, getFreeRAM()); + #ifdef VENDORFILTER } else { // Very noisy diff --git a/src/main.cpp b/src/main.cpp index 50eed5a8..2ba2268e 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -54,13 +54,14 @@ configData_t cfg; // struct holds current device configuration char display_line6[16], display_line7[16]; // display buffers 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 - + batt_voltage = 0; // globals for display hw_timer_t *channelSwitch = NULL, *sendCycle = NULL, *homeCycle = NULL, *displaytimer = NULL; // irq tasks TaskHandle_t irqHandlerTask, wifiSwitchTask; -std::set macs; // container holding unique MAC adress hashes +// container holding unique MAC address hashes with Memory Alloctor using PSRAM, +// if present +std::set, Mallocator> macs; // initialize payload encoder PayloadConvert payload(PAYLOAD_BUFFER_SIZE); @@ -107,8 +108,10 @@ void setup() { : "external"); ESP_LOGI(TAG, "Internal Total heap %d, internal Free Heap %d", ESP.getHeapSize(), ESP.getFreeHeap()); +#ifdef BOARD_HAS_PSRAM ESP_LOGI(TAG, "SPIRam Total heap %d, SPIRam Free Heap %d", ESP.getPsramSize(), ESP.getFreePsram()); +#endif ESP_LOGI(TAG, "ChipRevision %d, Cpu Freq %d, SDK Version %s", ESP.getChipRevision(), ESP.getCpuFreqMHz(), ESP.getSdkVersion()); ESP_LOGI(TAG, "Flash Size %d, Flash Speed %d", ESP.getFlashChipSize(), @@ -124,7 +127,16 @@ void setup() { // read (and initialize on first run) runtime settings from NVRAM loadConfig(); // includes initialize if necessary - // initialize leds +#ifdef BOARD_HAS_PSRAM + if (psramFound()) { + ESP_LOGI(TAG, "PSRAM found and initialized"); + strcat_P(features, " PSRAM"); + } else + ESP_LOGI(TAG, "No PSRAM found"); +#else +#endif + + // initialize leds #if (HAS_LED != NOT_A_PIN) pinMode(HAS_LED, OUTPUT); strcat_P(features, " LED"); diff --git a/src/paxcounter.conf b/src/paxcounter.conf index 94cdfd1d..370a5ce3 100644 --- a/src/paxcounter.conf +++ b/src/paxcounter.conf @@ -81,7 +81,7 @@ #define RESPONSE_TIMEOUT_MS 60000 // firmware binary server connection timeout [milliseconds] // setting for syncing time of node -#define TIME_SYNC_INTERVAL 60 // sync time each ... minutes [default = 60], comment out means off +//#define TIME_SYNC_INTERVAL 60 // sync time each ... minutes [default = 60], comment out means off // LMIC settings // moved to src/lmic_config.h \ No newline at end of file diff --git a/src/rcommand.cpp b/src/rcommand.cpp index eebd7f30..3b6bccc6 100644 --- a/src/rcommand.cpp +++ b/src/rcommand.cpp @@ -245,7 +245,7 @@ void get_status(uint8_t val[]) { #endif payload.reset(); payload.addStatus(voltage, uptime() / 1000, temperatureRead(), - ESP.getFreeHeap(), rtc_get_reset_reason(0), + getFreeRAM(), rtc_get_reset_reason(0), rtc_get_reset_reason(1)); SendPayload(STATUSPORT); };