Skip to content
Draft
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 6 additions & 2 deletions include/lv_conf.h
Original file line number Diff line number Diff line change
Expand Up @@ -69,8 +69,12 @@
/*Instead of an address give a memory allocator that will be called to get a memory pool for LVGL. E.g. my_malloc*/
#if LV_MEM_ADR == 0
#if defined BOARD_HAS_PSRAM
#define LV_MEM_POOL_INCLUDE <esp_heap_caps.h>
#define LV_MEM_POOL_ALLOC(size) heap_caps_aligned_alloc(32, size, MALLOC_CAP_SPIRAM)
/* CONFIG_SPIRAM_USE_MALLOC=y integrates PSRAM into the regular heap so
* MALLOC_CAP_SPIRAM capability is not set; heap_caps_aligned_alloc with
* that cap returns NULL. Use plain malloc() — large allocations route to
* PSRAM automatically. */
#define LV_MEM_POOL_INCLUDE <stdlib.h>
#define LV_MEM_POOL_ALLOC(size) malloc(size)
Comment on lines 71 to +77

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🎯 Functional Correctness | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "Repo files matching lv_conf.h:"
fd -a 'lv_conf\.h$' . || true

echo
echo "Relevant includes and config files:"
for f in $(fd -a 'lv_conf\.h$' .); do
  echo "--- $f ($(wc -l < "$f") lines) ---"
  sed -n '1,130p' "$f"
done

echo
echo "Search for MALLOC_CAP_SPIRAM / LV_MEM_POOL_ALLOC / CONFIG_SPIRAM_USE_MALLOC:"
rg -n "MALLOC_CAP_SPIRAM|LV_MEM_POOL_ALLOC|LV_MEM_POOL_INCLUDE|CONFIG_SPIRAM_USE_MALLOC|BOARD_HAS_PSRAM|heap_caps_aligned_alloc" .

Repository: meshtastic/device-ui

Length of output: 6289


🏁 Script executed:

#!/bin/bash
set -euo pipefail

echo "LGFXDriver relevant lines:"
sed -n '230,295p' include/graphics/driver/LGFXDriver.h

echo
echo "Files mentioning CONFIG_SPIRAM_USE_MALLOC:"
rg -n "CONFIG_SPIRAM_USE_MALLOC|CONFIG_SPIRAM_USE_MALLOC" .

echo
echo "ESP-IDF config/platform indicators for default PSRAM allocator behavior:"
rg -n "CONFIG_SPIRAM_ALLOC_CAP|CONFIG_SPIRAM_USE_MALLOC|SPIRAM_USE_MALLOC|MALLOC_CAP_SPIRAM" -g '*.conf' -g '*.h' -g '*.c' -g '*.md' -g '*.txt' .

Repository: meshtastic/device-ui

Length of output: 4548


🌐 Web query:

ESP-IDF CONFIG_SPIRAM_USE_MALLOC heap_caps_aligned_alloc MALLOC_CAP_SPIRAM returns NULL

💡 Result:

In ESP-IDF, when CONFIG_SPIRAM_USE_MALLOC is enabled, the heap allocator adds PSRAM to the pool of memory capable of satisfying malloc() and heap_caps_malloc() requests [1][2]. If heap_caps_aligned_alloc(alignment, size, MALLOC_CAP_SPIRAM) returns NULL, it indicates that the allocator was unable to find a contiguous block in the external PSRAM that meets both the size and alignment requirements [3][4][5]. Common reasons and troubleshooting steps include: 1. PSRAM Initialization Failure: Ensure that the PSRAM is successfully initialized during boot. Check your serial logs for messages like "PSRAM initialized" or "Adding pool of... of external SPI memory to heap allocator" [6][7]. If the PSRAM is not initialized, MALLOC_CAP_SPIRAM allocations will fail [7]. 2. Alignment and Size Constraints: The heap_caps_aligned_alloc function requires a contiguous block of memory [4][5]. Even if the total free PSRAM appears sufficient, heap fragmentation may prevent the allocation of a single block of the requested size and alignment [8]. You can check the largest free block in PSRAM using heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM) to verify if the requested size can actually be satisfied [6]. 3. Misunderstanding MALLOC_CAP_SPIRAM vs. MALLOC_CAP_DEFAULT: While CONFIG_SPIRAM_USE_MALLOC allows malloc() to use PSRAM, explicitly requesting MALLOC_CAP_SPIRAM tells the allocator to only look in PSRAM [1][2]. If PSRAM is full or fragmented, this call will return NULL even if internal memory is available [3][5]. 4. Configuration Conflicts: Ensure your sdkconfig settings are correct for your specific module. Check CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL, which defines a threshold below which allocations prefer internal memory [1][9]. Also, verify that other components (like WiFi/LWIP) are not exhausting the PSRAM pool if you have enabled options like CONFIG_SPIRAM_TRY_ALLOCATE_WIFI_LWIP [10]. To diagnose, try the following: - Use heap_caps_get_free_size(MALLOC_CAP_SPIRAM) and heap_caps_get_largest_free_block(MALLOC_CAP_SPIRAM) to see the current state of the PSRAM heap [9][6]. - If you suspect fragmentation, consider if you can use EXT_RAM_BSS_ATTR for static buffers instead of dynamic allocation [8][2]. - Verify that your alignment value is a power of two, as required by the API [4].

Citations:


Gate the malloc() allocator on CONFIG_SPIRAM_USE_MALLOC.

BOARD_HAS_PSRAM also covers builds where CONFIG_SPIRAM_USE_MALLOC is disabled, in which ESP-IDF does not automatically integrate PSRAM into the default heap. In those builds, LV_MEM_POOL_ALLOC currently routes PSRAM-backed LVGL draw buffers through malloc() instead of the existing heap_caps_aligned_alloc(..., MALLOC_CAP_SPIRAM) path, so allocations can consume internal RAM or fail.

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@include/lv_conf.h` around lines 71 - 77, Update the BOARD_HAS_PSRAM allocator
conditional in include/lv_conf.h so the plain malloc() definition is used only
when CONFIG_SPIRAM_USE_MALLOC is enabled. Preserve the existing
heap_caps_aligned_alloc(..., MALLOC_CAP_SPIRAM) path for BOARD_HAS_PSRAM builds
without that configuration, while keeping the non-PSRAM allocator behavior
unchanged.

Comment on lines +72 to +77
#else
#undef LV_MEM_POOL_INCLUDE
#undef LV_MEM_POOL_ALLOC
Expand Down
Loading