mirror of
https://github.com/meshtastic/firmware.git
synced 2025-10-28 15:22:55 +00:00
Update when and how memory is allocated.
This commit is contained in:
parent
b206a69570
commit
ba72308d0c
@ -53,12 +53,42 @@ extern MemGet memGet;
|
||||
#define LOG_TRACE(...) SEGGER_RTT_printf(0, __VA_ARGS__)
|
||||
#else
|
||||
#if defined(DEBUG_PORT) && !defined(DEBUG_MUTE)
|
||||
#define LOG_DEBUG(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_DEBUG, __VA_ARGS__)
|
||||
#define LOG_INFO(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_INFO, __VA_ARGS__)
|
||||
#define LOG_WARN(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_WARN, __VA_ARGS__)
|
||||
#define LOG_ERROR(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_ERROR, __VA_ARGS__)
|
||||
#define LOG_CRIT(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_CRIT, __VA_ARGS__)
|
||||
#define LOG_TRACE(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_TRACE, __VA_ARGS__)
|
||||
#define LOG_DEBUG(...) \
|
||||
do { \
|
||||
if (console) { \
|
||||
console->log(MESHTASTIC_LOG_LEVEL_DEBUG, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_INFO(...) \
|
||||
do { \
|
||||
if (console) { \
|
||||
console->log(MESHTASTIC_LOG_LEVEL_INFO, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_WARN(...) \
|
||||
do { \
|
||||
if (console) { \
|
||||
console->log(MESHTASTIC_LOG_LEVEL_WARN, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_ERROR(...) \
|
||||
do { \
|
||||
if (console) { \
|
||||
console->log(MESHTASTIC_LOG_LEVEL_ERROR, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_CRIT(...) \
|
||||
do { \
|
||||
if (console) { \
|
||||
console->log(MESHTASTIC_LOG_LEVEL_CRIT, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define LOG_TRACE(...) \
|
||||
do { \
|
||||
if (console) { \
|
||||
console->log(MESHTASTIC_LOG_LEVEL_TRACE, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#else
|
||||
#define LOG_DEBUG(...)
|
||||
#define LOG_INFO(...)
|
||||
@ -70,7 +100,12 @@ extern MemGet memGet;
|
||||
#endif
|
||||
|
||||
#if defined(DEBUG_HEAP)
|
||||
#define LOG_HEAP(...) DEBUG_PORT.log(MESHTASTIC_LOG_LEVEL_HEAP, __VA_ARGS__)
|
||||
#define LOG_HEAP(...) \
|
||||
do { \
|
||||
if (console) { \
|
||||
console->log(MESHTASTIC_LOG_LEVEL_HEAP, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
// Macro-based heap debugging
|
||||
#define DEBUG_HEAP_BEFORE auto heapBefore = memGet.getFreeHeap();
|
||||
@ -195,4 +230,4 @@ class Syslog
|
||||
bool vlogf(uint16_t pri, const char *appName, const char *fmt, va_list args) __attribute__((format(printf, 3, 0)));
|
||||
};
|
||||
|
||||
#endif // HAS_NETWORKING
|
||||
#endif // HAS_NETWORKING
|
||||
|
||||
@ -294,7 +294,7 @@ void printInfo()
|
||||
{
|
||||
LOG_INFO("S:B:%d,%s,%s,%s", HW_VENDOR, optstr(APP_VERSION), optstr(APP_ENV), optstr(APP_REPO));
|
||||
}
|
||||
#ifndef PIO_UNIT_TESTING
|
||||
#if !defined(PIO_UNIT_TESTING) || !(PIO_UNIT_TESTING)
|
||||
void setup()
|
||||
{
|
||||
|
||||
@ -1580,7 +1580,7 @@ void scannerToSensorsMap(const std::unique_ptr<ScanI2CTwoWire> &i2cScanner, Scan
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef PIO_UNIT_TESTING
|
||||
#if !defined(PIO_UNIT_TESTING) || !(PIO_UNIT_TESTING)
|
||||
void loop()
|
||||
{
|
||||
runASAP = false;
|
||||
|
||||
@ -38,6 +38,12 @@
|
||||
#include <Preferences.h>
|
||||
#include <esp_efuse.h>
|
||||
#include <esp_efuse_table.h>
|
||||
#if __has_include(<esp_ptr.h>)
|
||||
#include <esp_ptr.h>
|
||||
#define NODEDB_HAS_ESP_PTR 1
|
||||
#else
|
||||
#define NODEDB_HAS_ESP_PTR 0
|
||||
#endif
|
||||
#include <nvs_flash.h>
|
||||
#include <soc/efuse_reg.h>
|
||||
#include <soc/soc.h>
|
||||
@ -68,19 +74,60 @@ meshtastic_DeviceUIConfig uiconfig{.screen_brightness = 153, .screen_timeout = 3
|
||||
meshtastic_LocalModuleConfig moduleConfig;
|
||||
meshtastic_ChannelFile channelFile;
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
//------------------------------------------------------------------------------
|
||||
// Runtime instrumentation helpers
|
||||
//------------------------------------------------------------------------------
|
||||
|
||||
// Hot/cold storage helpers -------------------------------------------------
|
||||
// ESP32-S3 targets (Station G2 and similar) keep the heavy NodeInfoLite payloads
|
||||
// in PSRAM while mirroring routing/UI critical fields in a compact DRAM cache.
|
||||
// The helpers below keep both views in sync.
|
||||
namespace
|
||||
{
|
||||
|
||||
// Log the pool headroom every 100 inserts (and when we hit MAX) so field logs
|
||||
// capture how close we are to exhausting heap/PSRAM on real hardware.
|
||||
|
||||
void logNodeInsertStats(size_t count, const char *poolLabel)
|
||||
{
|
||||
if (count == 0)
|
||||
return;
|
||||
if ((count % 100) != 0 && count != MAX_NUM_NODES)
|
||||
return;
|
||||
|
||||
LOG_INFO("NodeDB %s pool usage %u/%u nodes, heap free %u, psram free %u", poolLabel, static_cast<unsigned>(count),
|
||||
static_cast<unsigned>(MAX_NUM_NODES), memGet.getFreeHeap(), memGet.getFreePsram());
|
||||
}
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
bool logPsramAllocationOnce(void *ptr, size_t capacity)
|
||||
{
|
||||
static bool logged = false;
|
||||
if (logged || !ptr)
|
||||
return logged;
|
||||
|
||||
#if NODEDB_HAS_ESP_PTR
|
||||
bool inPsram = esp_ptr_external_ram(ptr);
|
||||
#else
|
||||
bool inPsram = false;
|
||||
#endif
|
||||
LOG_INFO("NodeDB PSRAM backing at %p (%s) capacity %u entries (~%u bytes)", ptr, inPsram ? "PSRAM" : "DRAM",
|
||||
static_cast<unsigned>(capacity), static_cast<unsigned>(capacity * sizeof(meshtastic_NodeInfoLite)));
|
||||
logged = true;
|
||||
return logged;
|
||||
}
|
||||
#endif
|
||||
|
||||
} // namespace
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
|
||||
void NodeDB::initHotCache()
|
||||
{
|
||||
// Pre-reserve the full cold store in PSRAM during boot so the high watermark
|
||||
// shows up immediately in PSRAM usage logs and we avoid fragmented
|
||||
// allocations later in the mission.
|
||||
psramMeshNodes.resize(MAX_NUM_NODES);
|
||||
hotNodes.resize(MAX_NUM_NODES);
|
||||
hotDirty.assign(MAX_NUM_NODES, true);
|
||||
meshNodes = &psramMeshNodes;
|
||||
logPsramAllocationOnce(psramMeshNodes.data(), psramMeshNodes.capacity());
|
||||
}
|
||||
|
||||
void NodeDB::refreshHotCache()
|
||||
@ -2263,6 +2310,7 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||
syncHotFromCold(index);
|
||||
lite = &psramMeshNodes[index];
|
||||
LOG_INFO("Adding node to database with %i nodes and %u bytes free!", numMeshNodes, memGet.getFreeHeap());
|
||||
logNodeInsertStats(numMeshNodes, "PSRAM");
|
||||
}
|
||||
|
||||
markHotDirty(lite);
|
||||
@ -2314,6 +2362,7 @@ meshtastic_NodeInfoLite *NodeDB::getOrCreateMeshNode(NodeNum n)
|
||||
memset(lite, 0, sizeof(*lite));
|
||||
lite->num = n;
|
||||
LOG_INFO("Adding node to database with %i nodes and %u bytes free!", numMeshNodes, memGet.getFreeHeap());
|
||||
logNodeInsertStats(numMeshNodes, "Heap");
|
||||
}
|
||||
|
||||
return lite;
|
||||
|
||||
@ -43,7 +43,7 @@ Allocator<meshtastic_MeshPacket> &packetPool = dynamicPool;
|
||||
(MAX_RX_TOPHONE + MAX_RX_FROMRADIO + 2 * MAX_TX_QUEUE + \
|
||||
2) // max number of packets which can be in flight (either queued from reception or queued for sending)
|
||||
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3) && defined(BOARD_HAS_PSRAM)
|
||||
// Try to put the heavy MeshPacket pool into PSRAM. If that fails we fall back to
|
||||
// heap allocation so the radio stays functional (at the cost of fewer packets).
|
||||
static PsramMemoryPool<meshtastic_MeshPacket, MAX_PACKETS_STATIC> psramPool;
|
||||
@ -51,6 +51,9 @@ static MemoryDynamic<meshtastic_MeshPacket> fallbackPool;
|
||||
Allocator<meshtastic_MeshPacket> &packetPool = psramPool.isValid()
|
||||
? static_cast<Allocator<meshtastic_MeshPacket> &>(psramPool)
|
||||
: static_cast<Allocator<meshtastic_MeshPacket> &>(fallbackPool);
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
static MemoryPool<meshtastic_MeshPacket, MAX_PACKETS_STATIC> staticPool;
|
||||
Allocator<meshtastic_MeshPacket> &packetPool = staticPool;
|
||||
#else
|
||||
static MemoryPool<meshtastic_MeshPacket, MAX_PACKETS_STATIC> staticPool;
|
||||
Allocator<meshtastic_MeshPacket> &packetPool = staticPool;
|
||||
@ -66,14 +69,6 @@ static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1] __attribute__((__aligned__));
|
||||
*/
|
||||
Router::Router() : concurrency::OSThread("Router"), fromRadioQueue(MAX_RX_FROMRADIO)
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
if (!psramPool.isValid()) {
|
||||
LOG_WARN("PSRAM packet pool unavailable, falling back to heap allocations");
|
||||
}
|
||||
if (!has_psram() && MAX_RX_TOPHONE > get_rx_tophone_limit()) {
|
||||
LOG_WARN("Detected <2MB PSRAM, limiting phone queue to %d packets", get_rx_tophone_limit());
|
||||
}
|
||||
#endif
|
||||
// This is called pre main(), don't touch anything here, the following code is not safe
|
||||
|
||||
/* LOG_DEBUG("Size of NodeInfo %d", sizeof(NodeInfo));
|
||||
|
||||
@ -32,7 +32,13 @@ inline bool has_psram(size_t minimumBytes = PSRAM_LARGE_THRESHOLD_BYTES)
|
||||
inline int get_rx_tophone_limit()
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
return has_psram() ? 400 : 32;
|
||||
#if defined(BOARD_MAX_RX_TOPHONE)
|
||||
return BOARD_MAX_RX_TOPHONE;
|
||||
#elif defined(BOARD_HAS_PSRAM)
|
||||
return 800;
|
||||
#else
|
||||
return 32;
|
||||
#endif
|
||||
#elif defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
return 8;
|
||||
#else
|
||||
@ -45,8 +51,14 @@ inline int get_rx_tophone_limit()
|
||||
// RAM #define MAX_RX_TOPHONE (member_size(DeviceState, receive_queue) / member_size(DeviceState, receive_queue[0]))
|
||||
#ifndef MAX_RX_TOPHONE
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if defined(BOARD_MAX_RX_TOPHONE)
|
||||
#define MAX_RX_TOPHONE BOARD_MAX_RX_TOPHONE
|
||||
#elif defined(BOARD_HAS_PSRAM)
|
||||
static constexpr int MAX_RX_TOPHONE_WITH_PSRAM = 800;
|
||||
#define MAX_RX_TOPHONE MAX_RX_TOPHONE_WITH_PSRAM
|
||||
#else
|
||||
#define MAX_RX_TOPHONE 32
|
||||
#endif
|
||||
#elif defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define MAX_RX_TOPHONE 8
|
||||
#else
|
||||
@ -80,13 +92,14 @@ static_assert(sizeof(meshtastic_NodeInfoLite) <= 200, "NodeInfoLite size increas
|
||||
#elif defined(ARCH_NRF52)
|
||||
#define MAX_NUM_NODES 80
|
||||
#elif defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
#if defined(BOARD_MAX_NUM_NODES)
|
||||
#define MAX_NUM_NODES BOARD_MAX_NUM_NODES
|
||||
#elif defined(BOARD_HAS_PSRAM)
|
||||
#define MAX_NUM_NODES 3000
|
||||
#else
|
||||
#include "Esp.h"
|
||||
static inline int get_max_num_nodes()
|
||||
{
|
||||
if (has_psram()) {
|
||||
return 5000;
|
||||
}
|
||||
|
||||
uint32_t flash_size = ESP.getFlashChipSize() / (1024 * 1024); // Fallback based on flash size
|
||||
if (flash_size >= 15) {
|
||||
return 250;
|
||||
@ -96,6 +109,7 @@ static inline int get_max_num_nodes()
|
||||
return 100;
|
||||
}
|
||||
#define MAX_NUM_NODES get_max_num_nodes()
|
||||
#endif
|
||||
#else
|
||||
#define MAX_NUM_NODES 100
|
||||
#endif
|
||||
|
||||
Loading…
Reference in New Issue
Block a user