-
Notifications
You must be signed in to change notification settings - Fork 7.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Memory & Heap issues with 4.3 (FreeRTOS functions, const char * in DRAM .data and TLSF control_t) (IDFGH-6143) #7822
Comments
Looking forward to seeing that commit reviewed and merged! |
@philippe44 regarding 2-: The idea of asserts is to use them only during development. Once the application is stable, you can disable them. Since they only abort the application and reset the device, they're also not very meaningful for a user. That being said, if you put their string into flash and the assert triggers when flash operations are disabled, then the assert will trigger an exception which is also not very pleasant. For the rest of the points my knowledge is too limited, I can't make any judgement but I'll pass this to colleagues who are more familiar. |
@0xjakob: absolutely, I forgot about that but I was surprised because it was a change in 4.3 vs 4.0. I can disable them in general. |
But very useful. It'll pinpoint where the assert failed, so even without a debugger, with gdbstub, you'll see where the assert failed. If it doesn't trigger an exception, it's very likely the assert will go unnoticed (what's a line in a hundred of lines of logs?) and your code will crash later on because the allocated memory is missing or corrupted. |
I've moved to make them simply silent. The issue is that our project is becoming quite big and every piece of ram is needed and now every piece of flash is needed as well... |
I'm afraid not. If the assert does not trigger an exception, then yes, the default is to print out the register stack trace which makes it possible to see where the assert fails. That's what the assert is for. If, however, there's an exception while the assert function is running and printing the stack trace, then you lose all this information. You may see a stack trace but to the assert code itself, not the code the assert is back tracing at that moment. All you'll know is that an assert triggered, but not where. |
You should see this patch and the file
to
There is no change whatsoever in the way the assert is handled. If the assert stop the execution (as it should), you'll get an address somewhere in the stack to this line. You'll use addr2line or gdb or whatever too, you'll get to the code line above and you'll see the message In all case, the patched version is better since it does not require storing useless assert text in the final binary, and you can still have the assert enabled in your build. |
No, this is not ture. |
Well, what I hope really is that my PR will be accepted... |
Does CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_SILENT=y help? |
While investigating and issue with available heap decrease between 4.3 and 4.0 while porting my application, I've opened #7813 and #7818 that I've closed now that I understand the problem and I think it's better to make a summary here. I observed a loss of 10-15kB of the precious internal RAM for any application and I've seen 3 causes:
1- On 4.3, the FREERTOS_PLACE_FUNCTIONS_INTO_FLASH seems to be disabled by default where it is not an option in 4.0. I missed that, my bad, but that was a reduction of ~7kB of available on-chip RAM for heap. That is simple to "solve"
2- The TLSF has a ton of asserts() with a string in heap_tlsf.c. That's nice but unfortunately, as these functions are placed in IRAM for efficiency, it seems that (logically?) the linker also places the strings (which should normaly be in .rodata in Flash) in DRAM .data, so that's another 1.5kB loss. The tlsf_assert can be changed to nothing, but that does not seem wise, maybe there is a way to still move these string to .rodata in Flash.
3- The TLSF itself requires a gigantic header/control block of 1.6kB for each heap zone, and as esp32 seems to have 5, then we end up "wasting" ~9kB. This one seems really awful to me (no offense meant) because it's a lot of scarce memory (for a better algorithm, I understand). Maybe moving SL_INDEX_COUNT_LOG2 to 4 would be a better size/efficiency compromise or it could become a config parameter. Or it could be made a runtime parameter that depends on the memory pool size, that would allow to use minimize overhead as each internal block is small and a larger block when SPIRAM is used but there we don't really care. This is obviously more complicated as the sizeof(control_t) is now irrelevant and must be calculated per heap zone.
[edit]: Also, when using SPIRAM, currently the control_t is above 2kB which becomes ridiculous knowing that some hezap zone of internal RAM are as small as 6kB or 15kB. I feel that a variable control_t is necessary and I'd be happy to work on a patch if you agree with the idea.
The text was updated successfully, but these errors were encountered: