diff --git a/src/MyMesh.cpp b/src/MyMesh.cpp index 58ab5d6..de358a1 100644 --- a/src/MyMesh.cpp +++ b/src/MyMesh.cpp @@ -3257,15 +3257,8 @@ void MyMesh::popChannelScope() { _chan_scope_pushed = false; } -#define MESHMEM(tag) do { \ - multi_heap_info_t _h{}; heap_caps_get_info(&_h, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); \ - Serial.printf("[MESHMEM] %-12s free=%6u psram=%7u\n", tag, \ - (unsigned)_h.total_free_bytes, (unsigned)ESP.getFreePsram()); Serial.flush(); } while (0) - void MyMesh::begin(bool has_display) { - MESHMEM("enter"); BaseChatMesh::begin(); - MESHMEM("post-base"); if (!_store->loadMainIdentity(self_id)) { self_id = radio_new_identity(); // create new random identity @@ -3288,9 +3281,7 @@ void MyMesh::begin(bool has_display) { #endif // load persisted prefs - MESHMEM("pre-prefs"); _store->loadPrefs(_prefs, sensors.node_lat, sensors.node_lon); - MESHMEM("post-prefs"); // sanitise bad pref values _prefs.rx_delay_base = constrain(_prefs.rx_delay_base, 0, 20.0f); @@ -3332,13 +3323,10 @@ void MyMesh::begin(bool has_display) { #endif resetContacts(); - MESHMEM("pre-contacts"); _store->loadContacts(this); - MESHMEM("post-contacts"); bootstrapRTCfromContacts(); addChannel("Public", PUBLIC_GROUP_PSK); // pre-configure Andy's public channel _store->loadChannels(this); - MESHMEM("post-channels"); applyRadioFromPrefs(); // freq/bw/sf/cr + TX power + RX-boost (shared with the live UI apply) #if defined(DISPLAY_CLASS) diff --git a/src/main.cpp b/src/main.cpp index 1a71e76..ada7dd1 100644 --- a/src/main.cpp +++ b/src/main.cpp @@ -276,15 +276,6 @@ void meshcomodClearSdMigLatch() { #endif -// Boot memory trace: 175 KB of internal RAM is gone before the UI starts, and -// nothing said where. Print free/largest at each init step so the consumer -// names itself instead of being guessed at. -#define BOOTMEM(tag) do { \ - multi_heap_info_t _h{}; heap_caps_get_info(&_h, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); \ - Serial.printf("[BOOTMEM] %-12s free=%6u largest=%6u psram=%7u\n", tag, \ - (unsigned)_h.total_free_bytes, (unsigned)_h.largest_free_block, \ - (unsigned)ESP.getFreePsram()); Serial.flush(); } while (0) - void setup() { Serial.begin(115200); #if defined(HAS_RAK_TAP_V2) @@ -293,7 +284,6 @@ void setup() { delay(200); #endif Serial.println("[BOOT] setup start"); - BOOTMEM("setup-start"); // The SDK ships CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL=4096: every allocation // under 4 KB is forced into internal DRAM even when PSRAM is free. On the V4 // that is why internal sat at ~99% while 800+ KB of PSRAM went unused. Lower @@ -301,7 +291,6 @@ void setup() { // genuinely needs internal/DMA memory asks for it by capability and is // unaffected. Tunable — raise it if something misbehaves. heap_caps_malloc_extmem_enable(256); - BOOTMEM("post-extmem"); // Widen the task-watchdog grace period. The ~5 s default trips during a legitimate-but-slow flash // burst — a SPIFFS garbage-collect, or a bulk save (DataStore issues ~12 flash ops per contact, @@ -344,7 +333,6 @@ void setup() { board.begin(); Serial.println("[BOOT] board ok"); - BOOTMEM("post-board"); #if defined(HAS_RAK_TAP_V2) // Quick PSRAM sanity check — silent crash before SPIFFS could be bad PSRAM config @@ -392,9 +380,7 @@ void setup() { } #endif - BOOTMEM("pre-radio"); if (!radio_init()) { halt(); } - BOOTMEM("post-radio"); Serial.println("[BOOT] radio ok"); fast_rng.begin(radio_driver.getRngSeed()); @@ -440,10 +426,7 @@ void setup() { ExtraFS.begin(); #endif #endif - BOOTMEM("pre-store"); store.begin(); - BOOTMEM("post-store"); - BOOTMEM("pre-mesh"); the_mesh.begin( #ifdef DISPLAY_CLASS disp != NULL @@ -457,15 +440,10 @@ void setup() { #else serial_interface.begin(Serial); #endif - BOOTMEM("pre-iface"); the_mesh.startInterface(serial_interface); - BOOTMEM("post-iface"); #elif defined(RP2040_PLATFORM) LittleFS.begin(); - BOOTMEM("pre-store"); store.begin(); - BOOTMEM("post-store"); - BOOTMEM("pre-mesh"); the_mesh.begin( #ifdef DISPLAY_CLASS disp != NULL @@ -488,18 +466,14 @@ void setup() { #else serial_interface.begin(Serial); #endif - BOOTMEM("pre-iface"); the_mesh.startInterface(serial_interface); - BOOTMEM("post-iface"); #elif defined(ESP32) // Storage selection. SPIFFS by default; use the SD card under /meshcomod when // SPIFFS is unavailable (e.g. installed under Launcher) OR the user opted in // ("Store data on SD"). The SD shares the LoRa SPI bus, already brought up by // radio_init() above, so SD.begin's spi.begin is a no-op. Graceful: any SD // failure falls back to SPIFFS so the device always boots. - BOOTMEM("pre-spiffs"); bool spiffs_ok = SPIFFS.begin(false); // try first WITHOUT auto-format - BOOTMEM("post-spiffs"); bool sd_storage = false; #if defined(HAS_TDECK_GT911) || defined(HELTEC_LORA_V4_R8) || defined(TLORA_PAGER) { @@ -668,14 +642,11 @@ void setup() { Serial.println("[BOOT] touchPrefsReload ok"); Serial.flush(); #endif #endif - BOOTMEM("pre-store"); store.begin(); - BOOTMEM("post-store"); #if defined(HAS_RAK_TAP_V2) Serial.println("[BOOT] store ok"); Serial.flush(); Serial.println("[BOOT] calling mesh.begin..."); Serial.flush(); #endif - BOOTMEM("pre-mesh"); the_mesh.begin( #ifdef DISPLAY_CLASS disp != NULL @@ -697,17 +668,13 @@ void setup() { #endif #if defined(WIFI_SSID) || defined(MULTI_TRANSPORT_COMPANION) - BOOTMEM("pre-wifi-cfg"); wifiConfigBegin(); - BOOTMEM("post-wifi-cfg"); Serial.println("[BOOT] wifiConfig ok"); #endif #ifdef MULTI_TRANSPORT_COMPANION board.setInhibitSleep(true); - BOOTMEM("pre-iface-srv"); serial_interface.begin(Serial, TCP_PORT, WS_PORT); - BOOTMEM("post-iface-srv"); Serial.println("[BOOT] serial_interface ok"); serial_interface.setBroadcastResponses(true); // RX log, channel messages, etc. go to all clients (USB + TCP + WS [+ BLE]), not only last sender /* Pick BLE vs WiFi at boot. The ESP32-S3 doesn't have enough internal heap @@ -794,9 +761,7 @@ void setup() { #else serial_interface.begin(Serial); #endif - BOOTMEM("pre-iface"); the_mesh.startInterface(serial_interface); - BOOTMEM("post-iface"); #else #error "need to define filesystem" #endif diff --git a/src/ui-touch/UITask.cpp b/src/ui-touch/UITask.cpp index 635a593..9db62f3 100644 --- a/src/ui-touch/UITask.cpp +++ b/src/ui-touch/UITask.cpp @@ -1330,12 +1330,6 @@ static void statusBarSetTall(bool tall) { void reserveTileFetchStack(); // fwd: claim the worker stack before Wi-Fi eats the heap -#define MEMPROBE(tag) do { \ - multi_heap_info_t _hi{}; heap_caps_get_info(&_hi, MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); \ - Serial.printf("[MEM] %-14s free=%6u largest=%6u psram=%7u\n", tag, \ - (unsigned)_hi.total_free_bytes, (unsigned)_hi.largest_free_block, \ - (unsigned)ESP.getFreePsram()); } while (0) - // ---- AppPage: the shared full-screen app-page chrome (see AppPage.h) -------------- // Thin wrappers over the machinery just above, exported so the self-contained app // modules (SnakeGame) build the same page as the in-file tool @@ -24361,9 +24355,8 @@ static void luaStoreFetchCatalogWorker(WiFiClient& client, HTTPClient& http) { s_luacat_buf = (char*)heap_caps_malloc(kLuaCatBufMax, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); if (!s_luacat_buf) { return; } s_luacat_buf[0] = 0; - int cn = luaStoreHttpGet(client, http, "http://firmware.wadamesh.com/apps/apps.json", - s_luacat_buf, kLuaCatBufMax); - Serial.printf("[APPCAT] n=%d wifi=%d\n", cn, (int)WiFi.status()); + luaStoreHttpGet(client, http, "http://firmware.wadamesh.com/apps/apps.json", + s_luacat_buf, kLuaCatBufMax); } // Download .lua + .json (immutable per-version path) into /apps/. @@ -24483,7 +24476,6 @@ static bool luaStoreLangDownloadWorker(WiFiClient& client, HTTPClient& http, snprintf(url, sizeof url, "http://firmware.wadamesh.com/apps/lang/%s.lang", code); int n = luaStoreHttpGet(client, http, url, buf, kCap); bool ok = false; - size_t wr = 0; bool opened = false; if (n > 16) { // Write to a TEMP file, verify every byte landed, then rename over the real @@ -24499,7 +24491,7 @@ static bool luaStoreLangDownloadWorker(WiFiClient& client, HTTPClient& http, File f = fs->open(tmp, "w"); opened = (bool)f; if (f) { - wr = langWriteAll(f, (const uint8_t*)buf, (size_t)n); + langWriteAll(f, (const uint8_t*)buf, (size_t)n); f.close(); ok = langVerifyInstall(fs, tmp, path, (size_t)n); } @@ -24515,7 +24507,6 @@ static bool luaStoreLangDownloadWorker(WiFiClient& client, HTTPClient& http, File cf = fs->open(ctl, "w"); if (cf) { wr2 = langWriteAll(cf, (const uint8_t*)buf, (size_t)n); cf.close(); } fs->remove(ctl); - size_t wr3 = 0; if (wr2 == (size_t)n) { // Healthy elsewhere -> nuke and recreate the /lang directory. char ldir[48]; @@ -24536,17 +24527,12 @@ static bool luaStoreLangDownloadWorker(WiFiClient& client, HTTPClient& http, fs->rmdir(ldir); fs->mkdir(ldir); File rf = fs->open(tmp, "w"); - if (rf) { wr3 = langWriteAll(rf, (const uint8_t*)buf, (size_t)n); rf.close(); } + if (rf) { langWriteAll(rf, (const uint8_t*)buf, (size_t)n); rf.close(); } ok = langVerifyInstall(fs, tmp, path, (size_t)n); if (!ok) fs->remove(tmp); } - Serial.printf("[LANGDL] repair ctl=%u relang=%u ok=%d\n", (unsigned)wr2, (unsigned)wr3, (int)ok); } } - char root[16]; - luaHostAppPath(root, sizeof root, ""); // "" = internal flash, "/meshcomod" = SD - Serial.printf("[LANGDL] %s n=%d root=%s open=%d wr=%u ok=%d\n", - url, n, root[0] ? root : "(internal)", (int)opened, (unsigned)wr, (int)ok); heap_caps_free(buf); return ok; } @@ -24910,7 +24896,6 @@ static void tileFetchTaskFn(void* arg) { // Lua app store: catalog fetch + app install (LUA_APPS.md Phase 2). if (s_luacat_request) { s_luacat_request = false; - Serial.println("[APPCAT] worker picked up the request"); luaStoreFetchCatalogWorker(client, http); s_luacat_done = true; continue; @@ -26904,7 +26889,9 @@ static void mapOptInfoCb(lv_event_t* e) { if (!credits) return; // OOM only: skip the credits text snprintf(credits, CREDITS_SZ, "%s%s", attrib, "How tiles work:\n" - "The map is built from 256\xC3\x97256 \"slippy\" tiles. Only the tiles for the " + // NOTE: the literal break after \x97 is REQUIRED — "\xC3\x97256" would parse the + // trailing 256 as part of the hex escape (all hex digits) and emit one garbage byte. + "The map is built from 256\xC3\x97" "256 \"slippy\" tiles. Only the tiles for the " "area you're viewing are fetched \xE2\x80\x94 there is no bulk pre-download.\n\n" "Because this device can't do HTTPS (not enough heap after Wi-Fi starts) " "and decodes JPEG far more cheaply than PNG, tiles come from the wadamesh " @@ -37907,13 +37894,7 @@ static void openLuaStorePage() { s_luacat_done = false; s_luacat_request = true; } - MEMPROBE("store-open"); const bool worker_up = ensureTileFetchTaskRunning(); - Serial.printf("[STORE] open: worker=%d spawn_ok=%d wifi=%d free_int=%u largest=%u free_psram=%u\n", - (int)worker_up, (int)s_tile_fetch_spawn_ok, (int)WiFi.status(), - (unsigned)ESP.getFreeHeap(), - (unsigned)heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT), - (unsigned)ESP.getFreePsram()); // The net worker needs an 8 KB contiguous internal block. When memory is too // tight to start it, nothing will ever service the request — so fail visibly // instead of spinning on "Loading catalog..." forever. @@ -42059,18 +42040,13 @@ static void buildUiTree() { } // ---- Build tab contents ---- - MEMPROBE("pre-home"); makeHome(tab_home); - MEMPROBE("tab-home"); g_lv.dm.channel_mode = false; g_lv.ch.channel_mode = true; makeChatList(tab_chats, g_lv.dm, false, true); - MEMPROBE("tab-chats"); makeContactsTab(tab_contacts); - MEMPROBE("tab-contacts"); makeMapTab(tab_map); - MEMPROBE("tab-map"); #if defined(HAS_EXPANSION_KIT) if (tab_sensors) makeSensorsTab(tab_sensors); #endif @@ -42136,13 +42112,8 @@ static void buildUiTree() { // Create full-screen detail overlays (hidden until a thread is tapped) makeChatDetail(g_lv.dm); makeChatDetail(g_lv.ch); - MEMPROBE("tab-chatdetail"); - MEMPROBE("pre-settings"); - MEMPROBE("pre-settings"); makeSettings(tab_settings); - MEMPROBE("tab-settings"); - MEMPROBE("post-UI-build"); #if defined(HAS_TANMATSU) navBuildTabKeyHints(); // coloured △□○♣◇ shapes on the tab bar = the physical F-keys @@ -45997,8 +45968,6 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no // largest block, so the worker could never start and tiles, the update // check and the app catalog were all silently dead. reserveTileFetchStack(); - MEMPROBE("post-reserve"); - MEMPROBE("pre-lv_init"); lv_init(); initTouchFontFallbacks(); #if CAP_ROUND_CORNERS @@ -46236,9 +46205,7 @@ void UITask::begin(DisplayDriver* display, SensorManager* sensors, NodePrefs* no // when the base orientation is portrait. In hardware landscape the LVGL // rotation is left at NONE so it never software-rotates on top of the panel. g_lv.disp_drv.sw_rotate = 1; - MEMPROBE("pre-disp_reg"); lv_disp_drv_register(&g_lv.disp_drv); - MEMPROBE("post-disp_reg"); #if defined(HAS_TANMATSU) // Apply the 270° software rotation now that the driver is registered: logical surface // becomes 800x480 and lv_disp_get_hor/ver_res report landscape for every layout query.