From 00c727427c0d2e1919261953d9e4213cf2854271 Mon Sep 17 00:00:00 2001 From: Guillaume Souchere Date: Mon, 23 Sep 2024 11:32:22 +0200 Subject: [PATCH] feat(heap): Update heap tests on external memory Create a specific group "psram" to only run meaningful tests on the sdkconfig.ci.psram and sdkconfig.ci.psram_all_ext configuration. Add test testing that external memory is prioritized when using MALLOC_CAP_DEFAULT. --- .../heap_tests/main/test_aligned_alloc_caps.c | 12 ++--- .../test_apps/heap_tests/main/test_malloc.c | 45 ++++++++++++++++--- .../heap/test_apps/heap_tests/pytest_heap.py | 2 +- 3 files changed, 47 insertions(+), 12 deletions(-) diff --git a/components/heap/test_apps/heap_tests/main/test_aligned_alloc_caps.c b/components/heap/test_apps/heap_tests/main/test_aligned_alloc_caps.c index 131363859d..9ff98e5408 100644 --- a/components/heap/test_apps/heap_tests/main/test_aligned_alloc_caps.c +++ b/components/heap/test_apps/heap_tests/main/test_aligned_alloc_caps.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -19,7 +19,7 @@ #include #include -TEST_CASE("Capabilities aligned allocator test", "[heap]") +TEST_CASE("Capabilities aligned allocator test", "[heap][psram]") { uint32_t alignments = 0; @@ -29,7 +29,7 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]") uint8_t *buf = (uint8_t *)memalign(alignments, (alignments + 137)); if(((alignments & (alignments - 1)) != 0) || (!alignments)) { TEST_ASSERT( buf == NULL ); - //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", aligments); + //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", alignments); } else { TEST_ASSERT( buf != NULL ); printf("[ALIGNED_ALLOC] alignment required: %"PRIu32" \n", alignments); @@ -58,7 +58,7 @@ TEST_CASE("Capabilities aligned allocator test", "[heap]") uint8_t *buf = (uint8_t *)heap_caps_aligned_alloc(alignments, 10*1024, MALLOC_CAP_SPIRAM); if(((alignments & (alignments - 1)) != 0) || (!alignments)) { TEST_ASSERT( buf == NULL ); - //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", aligments); + //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", alignments); } else { TEST_ASSERT( buf != NULL ); printf("[ALIGNED_ALLOC] alignment required: %"PRIu32" \n", alignments); @@ -86,7 +86,7 @@ TEST_CASE("Capabilities aligned calloc test", "[heap]") uint8_t *buf = (uint8_t *)heap_caps_aligned_calloc(alignments, 1, (alignments + 137), MALLOC_CAP_DEFAULT); if(((alignments & (alignments - 1)) != 0) || (!alignments)) { TEST_ASSERT( buf == NULL ); - //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", aligments); + //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", alignments); } else { TEST_ASSERT( buf != NULL ); printf("[ALIGNED_ALLOC] alignment required: %"PRIu32" \n", alignments); @@ -126,7 +126,7 @@ TEST_CASE("Capabilities aligned calloc test", "[heap]") uint8_t *buf = (uint8_t *)(uint8_t *)heap_caps_aligned_calloc(alignments, 1, 10*1024, MALLOC_CAP_SPIRAM); if(((alignments & (alignments - 1)) != 0) || (!alignments)) { TEST_ASSERT( buf == NULL ); - //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", aligments); + //printf("[ALIGNED_ALLOC] alignment: %"PRIu32" is not a power of two, don't allow allocation \n", alignments); } else { TEST_ASSERT( buf != NULL ); printf("[ALIGNED_ALLOC] alignment required: %"PRIu32" \n", alignments); diff --git a/components/heap/test_apps/heap_tests/main/test_malloc.c b/components/heap/test_apps/heap_tests/main/test_malloc.c index 8cd4078afd..dbfc5d4a6e 100644 --- a/components/heap/test_apps/heap_tests/main/test_malloc.c +++ b/components/heap/test_apps/heap_tests/main/test_malloc.c @@ -1,5 +1,5 @@ /* - * SPDX-FileCopyrightText: 2022-2023 Espressif Systems (Shanghai) CO LTD + * SPDX-FileCopyrightText: 2022-2024 Espressif Systems (Shanghai) CO LTD * * SPDX-License-Identifier: Unlicense OR CC0-1.0 */ @@ -64,10 +64,9 @@ TEST_CASE("Malloc/overwrite, then free all available DRAM", "[heap]") TEST_ASSERT(m1==m2); } -#if CONFIG_SPIRAM_USE_MALLOC -#if (CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL > 1024) -TEST_CASE("Check if reserved DMA pool still can allocate even when malloc()'ed memory is exhausted", "[heap]") +#if CONFIG_SPIRAM_USE_MALLOC && (CONFIG_SPIRAM_MALLOC_RESERVE_INTERNAL > 1024) +TEST_CASE("Check if reserved DMA pool still can allocate even when malloc()'ed memory is exhausted", "[heap][psram]") { char** dmaMem=malloc(sizeof(char*)*512); assert(dmaMem); @@ -85,8 +84,44 @@ TEST_CASE("Check if reserved DMA pool still can allocate even when malloc()'ed m } #endif -#endif +#if CONFIG_SPIRAM +TEST_CASE("Check if default cap allocates in external memory in priority", "[heap][psram]") +{ + const size_t alloc_size = 256; + const uint32_t internal_cap = MALLOC_CAP_DEFAULT | MALLOC_CAP_INTERNAL; + const uint32_t external_cap = MALLOC_CAP_DEFAULT | MALLOC_CAP_SPIRAM; + // get the free internal memory size + size_t free_internal_memory = heap_caps_get_free_size(internal_cap); + size_t free_external_memory = heap_caps_get_free_size(external_cap); + + // allocate a small amount of memory using MALLOC_CAP_DEFAULT + void * ptr = heap_caps_malloc(alloc_size, MALLOC_CAP_DEFAULT); + TEST_ASSERT_NOT_NULL(ptr); + + // check that external memory is used by making sure the free internal memory size is unchanged + // and the free external memory size has decreased by at least the size of the allocation + TEST_ASSERT(free_internal_memory == heap_caps_get_free_size(internal_cap)); + TEST_ASSERT(free_external_memory >= heap_caps_get_free_size(external_cap) + alloc_size); + + heap_caps_free(ptr); + free_internal_memory = heap_caps_get_free_size(internal_cap); + free_external_memory = heap_caps_get_free_size(external_cap); + + // only test malloc if CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL is equal to 0 since otherwise, allocations + // with size under the limit will be done internally. +#if (CONFIG_SPIRAM_MALLOC_ALWAYSINTERNAL == 0) + // test again using malloc + ptr = malloc(alloc_size); + TEST_ASSERT_NOT_NULL(ptr); + + TEST_ASSERT(free_internal_memory == heap_caps_get_free_size(internal_cap)); + TEST_ASSERT(free_external_memory >= heap_caps_get_free_size(external_cap) + alloc_size); + + heap_caps_free(ptr); +#endif +} +#endif /* As you see, we are desperately trying to outsmart the compiler, so that it * doesn't warn about oversized allocations in the next two unit tests. diff --git a/components/heap/test_apps/heap_tests/pytest_heap.py b/components/heap/test_apps/heap_tests/pytest_heap.py index 01c98844be..6f0c710bc2 100644 --- a/components/heap/test_apps/heap_tests/pytest_heap.py +++ b/components/heap/test_apps/heap_tests/pytest_heap.py @@ -66,7 +66,7 @@ def test_heap_in_flash(dut: Dut) -> None: ] ) def test_heap(dut: Dut) -> None: - dut.run_all_single_board_cases() + dut.run_all_single_board_cases(group='psram') @pytest.mark.generic