mirror of
https://github.com/meshtastic/firmware.git
synced 2025-10-27 15:02:41 +00:00
Add moar stored messages when oflfine as well. Also using psram.
This commit is contained in:
parent
344263de86
commit
2e4f1a0216
@ -8,6 +8,10 @@
|
||||
#include "PointerQueue.h"
|
||||
#include "configuration.h" // For LOG_WARN, LOG_DEBUG, LOG_HEAP
|
||||
|
||||
#if defined(ARCH_ESP32)
|
||||
#include <esp_heap_caps.h>
|
||||
#endif
|
||||
|
||||
template <class T> class Allocator
|
||||
{
|
||||
|
||||
@ -159,3 +163,69 @@ template <class T, int MaxSize> class MemoryPool : public Allocator<T>
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
|
||||
#if defined(ARCH_ESP32)
|
||||
// Simple fixed-size allocator that uses PSRAM. Used on ESP32-S3 builds so the
|
||||
// large MeshPacket pool can live off-chip and free internal RAM.
|
||||
template <class T, int MaxSize> class PsramMemoryPool : public Allocator<T>
|
||||
{
|
||||
private:
|
||||
T *pool;
|
||||
bool used[MaxSize];
|
||||
|
||||
public:
|
||||
PsramMemoryPool() : pool(nullptr), used{}
|
||||
{
|
||||
pool = static_cast<T *>(heap_caps_malloc(sizeof(T) * MaxSize, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT));
|
||||
if (pool) {
|
||||
memset(pool, 0, sizeof(T) * MaxSize);
|
||||
} else {
|
||||
LOG_WARN("Failed to allocate PSRAM pool of %d elements", MaxSize);
|
||||
}
|
||||
}
|
||||
|
||||
~PsramMemoryPool() override
|
||||
{
|
||||
if (pool) {
|
||||
heap_caps_free(pool);
|
||||
}
|
||||
}
|
||||
|
||||
bool isValid() const { return pool != nullptr; }
|
||||
|
||||
void release(T *p) override
|
||||
{
|
||||
if (!pool || !p) {
|
||||
LOG_DEBUG("Failed to release PSRAM memory, pointer is null or pool unavailable");
|
||||
return;
|
||||
}
|
||||
|
||||
int index = static_cast<int>(p - pool);
|
||||
if (index >= 0 && index < MaxSize) {
|
||||
assert(used[index]);
|
||||
used[index] = false;
|
||||
LOG_HEAP("Released PSRAM pool item %d at 0x%x", index, p);
|
||||
} else {
|
||||
LOG_WARN("Pointer 0x%x not from PSRAM pool!", p);
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
T *alloc(TickType_t maxWait) override
|
||||
{
|
||||
if (!pool)
|
||||
return nullptr;
|
||||
|
||||
for (int i = 0; i < MaxSize; i++) {
|
||||
if (!used[i]) {
|
||||
used[i] = true;
|
||||
LOG_HEAP("Allocated PSRAM pool item %d at 0x%x", i, &pool[i]);
|
||||
return &pool[i];
|
||||
}
|
||||
}
|
||||
|
||||
LOG_WARN("No free slots available in PSRAM memory pool!");
|
||||
return nullptr;
|
||||
}
|
||||
};
|
||||
#endif
|
||||
|
||||
@ -305,15 +305,21 @@ void MeshService::sendToPhone(meshtastic_MeshPacket *p)
|
||||
#endif
|
||||
#endif
|
||||
|
||||
if (toPhoneQueue.numFree() == 0) {
|
||||
// MAX_RX_TOPHONE is sized for PSRAM-backed builds. Fall back to a smaller
|
||||
// runtime limit if the helper detects <2MB of PSRAM at boot.
|
||||
const int queueLimit = get_rx_tophone_limit();
|
||||
const bool runtimeLimitReached = queueLimit > 0 && toPhoneQueue.numUsed() >= queueLimit;
|
||||
|
||||
if (toPhoneQueue.numFree() == 0 || runtimeLimitReached) {
|
||||
const bool runtimeControlled = runtimeLimitReached && queueLimit < MAX_RX_TOPHONE;
|
||||
if (p->decoded.portnum == meshtastic_PortNum_TEXT_MESSAGE_APP ||
|
||||
p->decoded.portnum == meshtastic_PortNum_RANGE_TEST_APP) {
|
||||
LOG_WARN("ToPhone queue is full, discard oldest");
|
||||
LOG_WARN("ToPhone queue %s, discard oldest", runtimeControlled ? "reached runtime limit" : "is full");
|
||||
meshtastic_MeshPacket *d = toPhoneQueue.dequeuePtr(0);
|
||||
if (d)
|
||||
releaseToPool(d);
|
||||
} else {
|
||||
LOG_WARN("ToPhone queue is full, drop packet");
|
||||
LOG_WARN("ToPhone queue %s, drop packet", runtimeControlled ? "reached runtime limit" : "is full");
|
||||
releaseToPool(p);
|
||||
fromNum++; // Make sure to notify observers in case they are reconnected so they can get the packets
|
||||
return;
|
||||
|
||||
@ -43,9 +43,19 @@ 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)
|
||||
// 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;
|
||||
static MemoryDynamic<meshtastic_MeshPacket> fallbackPool;
|
||||
Allocator<meshtastic_MeshPacket> &packetPool = psramPool.isValid()
|
||||
? static_cast<Allocator<meshtastic_MeshPacket> &>(psramPool)
|
||||
: static_cast<Allocator<meshtastic_MeshPacket> &>(fallbackPool);
|
||||
#else
|
||||
static MemoryPool<meshtastic_MeshPacket, MAX_PACKETS_STATIC> staticPool;
|
||||
Allocator<meshtastic_MeshPacket> &packetPool = staticPool;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
static uint8_t bytes[MAX_LORA_PAYLOAD_LEN + 1] __attribute__((__aligned__));
|
||||
|
||||
@ -56,6 +66,14 @@ 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));
|
||||
|
||||
@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
#include <vector>
|
||||
|
||||
#include "memGet.h"
|
||||
#include "mesh/generated/meshtastic/admin.pb.h"
|
||||
#include "mesh/generated/meshtastic/deviceonly.pb.h"
|
||||
#include "mesh/generated/meshtastic/localonly.pb.h"
|
||||
@ -11,11 +12,42 @@
|
||||
// Tricky macro to let you find the sizeof a type member
|
||||
#define member_size(type, member) sizeof(((type *)0)->member)
|
||||
|
||||
// Minimum PSRAM the firmware expects before enabling the "expanded" queues that
|
||||
// rely on off-chip RAM instead of internal DRAM. Currently set to 2MB to
|
||||
// accommodate Heltec WiFi LoRa 32 V4 boards (and others)
|
||||
static constexpr size_t PSRAM_LARGE_THRESHOLD_BYTES = 2 * 1024 * 1024;
|
||||
|
||||
inline bool has_psram(size_t minimumBytes = PSRAM_LARGE_THRESHOLD_BYTES)
|
||||
{
|
||||
#if defined(ARCH_ESP32) || defined(ARCH_PORTDUINO)
|
||||
return memGet.getPsramSize() >= minimumBytes;
|
||||
#else
|
||||
(void)minimumBytes;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
// Runtime cap used to keep the BLE message queue from overflowing low-memory
|
||||
// S3 variants if PSRAM is smaller than expected or temporarily unavailable.
|
||||
inline int get_rx_tophone_limit()
|
||||
{
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
return has_psram() ? 200 : 32;
|
||||
#elif defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
return 8;
|
||||
#else
|
||||
return 32;
|
||||
#endif
|
||||
}
|
||||
|
||||
/// max number of packets which can be waiting for delivery to android - note, this value comes from mesh.options protobuf
|
||||
// FIXME - max_count is actually 32 but we save/load this as one long string of preencoded MeshPacket bytes - not a big array in
|
||||
// RAM #define MAX_RX_TOPHONE (member_size(DeviceState, receive_queue) / member_size(DeviceState, receive_queue[0]))
|
||||
#ifndef MAX_RX_TOPHONE
|
||||
#if defined(ARCH_ESP32) && !(defined(CONFIG_IDF_TARGET_ESP32C3) || defined(CONFIG_IDF_TARGET_ESP32S3))
|
||||
#if defined(CONFIG_IDF_TARGET_ESP32S3)
|
||||
static constexpr int MAX_RX_TOPHONE_WITH_PSRAM = 200;
|
||||
#define MAX_RX_TOPHONE MAX_RX_TOPHONE_WITH_PSRAM
|
||||
#elif defined(ARCH_ESP32) && !defined(CONFIG_IDF_TARGET_ESP32C3)
|
||||
#define MAX_RX_TOPHONE 8
|
||||
#else
|
||||
#define MAX_RX_TOPHONE 32
|
||||
@ -51,9 +83,8 @@ static_assert(sizeof(meshtastic_NodeInfoLite) <= 200, "NodeInfoLite size increas
|
||||
#include "Esp.h"
|
||||
static inline int get_max_num_nodes()
|
||||
{
|
||||
uint32_t psram_size = ESP.getPsramSize() / (1024 * 1024); // Convert Bytes to MB
|
||||
if (psram_size >= 2) {
|
||||
return 800;
|
||||
if (has_psram()) {
|
||||
return 5000;
|
||||
}
|
||||
|
||||
uint32_t flash_size = ESP.getFlashChipSize() / (1024 * 1024); // Fallback based on flash size
|
||||
|
||||
Loading…
Reference in New Issue
Block a user