Assert failed: insert_free_block

Description

Since LVGL was “crashing” due to the fact that my LV_MEM_SIZE was too small I tried increasing this size by moving the memory buffer for LVGL.
But now all I get is the following.
[Error] (0.310, +310) insert_free_block: Asserted at expression: current && “free list cannot have a null entry” (in lv_tlsf.c line #614)

My original memory map looked like this

+------------ 0x20003900 ------------+
|      eventrecorder (1280 bytes)    |
+------------ 0x20003E00 ------------+
|                                    |
+------------ 0x20004100 ------------+
|      LVGL memory (16128 bytes)     |
+============ 0x20008000 ============+
|         Controller internal        |
+============ 0xA0000000 ============+

And, by removing the eventrecorder (part of the keil uVision) my new memory map should look like this.

+------------ 0x20003900 ------------+
|      LVGL memory (18176 bytes)     |
+============ 0x20008000 ============+
|         Controller internal        |
+============ 0xA0000000 ============+

And lv_conf (original)

/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
#define LV_MEM_CUSTOM 0
#if LV_MEM_CUSTOM == 0
    /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
    #define LV_MEM_SIZE 0x3F00 //(64U * 1024U)          /*[bytes]*/

    /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
    #define LV_MEM_ADR 0x20004100     /*0: unused*/
    /*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
        #undef LV_MEM_POOL_INCLUDE
        #undef LV_MEM_POOL_ALLOC
    #endif

#else       /*LV_MEM_CUSTOM*/
    #define LV_MEM_CUSTOM_INCLUDE <stdlib.h>   /*Header for the dynamic memory function*/
    #define LV_MEM_CUSTOM_ALLOC   malloc
    #define LV_MEM_CUSTOM_FREE    free
    #define LV_MEM_CUSTOM_REALLOC realloc
#endif     /*LV_MEM_CUSTOM*/

And the new version

/*1: use custom malloc/free, 0: use the built-in `lv_mem_alloc()` and `lv_mem_free()`*/
#define LV_MEM_CUSTOM 0
#if LV_MEM_CUSTOM == 0
    /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
    #define LV_MEM_SIZE 0x4700 //(64U * 1024U)          /*[bytes]*/

    /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
    #define LV_MEM_ADR 0x20003900     /*0: unused*/
    /*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
        #undef LV_MEM_POOL_INCLUDE
        #undef LV_MEM_POOL_ALLOC
    #endif

#else       /*LV_MEM_CUSTOM*/
    #define LV_MEM_CUSTOM_INCLUDE <stdlib.h>   /*Header for the dynamic memory function*/
    #define LV_MEM_CUSTOM_ALLOC   malloc
    #define LV_MEM_CUSTOM_FREE    free
    #define LV_MEM_CUSTOM_REALLOC realloc
#endif     /*LV_MEM_CUSTOM*/

What MCU/Processor/Board and compiler are you using?

An LPC1788 with keil uVision and LVGL 8.4.0 (was 8.3.11)

What do you want to achieve?

A bigger LV_MEM_SIZE

What have you tried so far?

Nothing really, I just changed my LV_MEM_SIZE and LV_MEM_ADR, next I know 2 of the asserts where failing.
The 1st was

tlsf_assert(block_to_ptr(block) == align_ptr(block_to_ptr(block), ALIGN_SIZE)
            && "block not aligned properly");

Next the current assert is also failing

tlsf_assert(current && "free list cannot have a null entry");

Code to reproduce

No real steps required. I have the LV_USE_MEM_MONITOR enabled so I can keep tabs on the memory usage. But when I now start the LVGL thread the memory monitor only displays a ? followed by a assert crash at the above mentioned locations.

So I am testing some stuff.

I updated lv_conf_cmsis.h so I use a little less memory.

    /*Size of the memory available for `lv_mem_alloc()` in bytes (>= 2kB)*/
    #define LV_MEM_SIZE 0x4000 //(64U * 1024U)          /*[bytes]*/

    /*Set an address for the memory pool instead of allocating it as a normal array. Can be in external SRAM too.*/
    #define LV_MEM_ADR 0x20004000     /*0: unused*/

This seems to run fine.

Next test: what happens if I fill 0x20003900 to 0x20004000 with some data (0xAA) is this overwritten or not?

The filling of that block doesn’t seem to make a real difference. What I write in that block remains as static data. (So it’s not that other code is messing with this memory.)

As a 2nd test I enabled all the logging that made sense to me So: LV_LOG_TRACE_MEM and LV_LOG_TRACE_OBJ_CREATE as well as LV_USE_ASSERT_MEM_INTEGRITY and LV_USE_ASSERT_OBJ.

The result of this can be found in this file (it’s a bit long). Next, I moved the full block from 0x20004000 to 0x20003900 (didn’t change the size). This however resulted in a “crash”
[Error] (0.479, +30) lv_tlsf_check: Asserted at expression: block == &control->block_null && "block list must be null" (in lv_tlsf.c line #859). Full log can be found here.

If I open them in a diff viewer everything looks about the same, including the timestamps. The only diff seems to be the line above.

I’m going to re-visit my assumption that the block 0x20003900 to 0x20004000 remains unwritten.

Well, it took a while. But I was wrong. The region from 0x20003000 to about 0x200039A0 is set to 0 by another task. (I guess my USB stack). (just tested and it’s indeed my USB stack)

Anyway, this issue seems to be solved at the moment.

Conclusion if lv_tlsf_check starts screaming at you: There is most likely some process overriding it’s memory.