eclipse-threadx / samples

A collection of complete sample workspaces and projects for popular development boards from ST, NXP, Renesas, Microchip and Microsoft using popular IDEs and toolchains, including IAR, ARM, STM32CubeIDE, MCUXpresso, MPLAB, Visual Studio, and Visual Studio Code.
131 stars 51 forks source link

STM32L4+ CubeIDE: Incorrect malloc behavior in OOM case #23

Closed nik-markovic closed 3 years ago

nik-markovic commented 3 years ago

This issue is observed with Azure_RTOS_6.1_STM32L4+-DISCO_STM32CubeIDE_Samples_2020_10_10.zip

I either have some bug in my example or newlib-nano malloc implementation seems to be experiencing some unexpected malloc behavior.

I expect malloc to return null if it runs our of ram. In the code below:

This is the injected code from sample_azure_iot_embedded_sdk main.c:

#define MEMORY_TEST
#ifdef MEMORY_TEST
#define TEST_BLOCK_SIZE  (100 * 1024)
#define TEST_BLOCK_COUNT 100
static void *blocks[TEST_BLOCK_COUNT];
void memory_test() {
    int i = 0;
    for (; i < TEST_BLOCK_COUNT; i++) {
        void *ptr = malloc(TEST_BLOCK_SIZE);
        if (NULL == ptr) {
            break;
        }
        blocks[i] = ptr;
    }
    printf("====Allocated %d blocks of size %d (of max %d)===\r\n", i, TEST_BLOCK_SIZE, TEST_BLOCK_COUNT);
    for (int j = 0; j < i; j++) {
        free(blocks[j]);
    }
}
#endif /* MEMORY_TEST */

/* Define main entry point.  */
int main(void)
{
    /* Setup platform. */
    board_setup();

    if (NULL == malloc(1UL * TEST_BLOCK_SIZE * TEST_BLOCK_SIZE)) return 1;

    memory_test();

    /* Enter the ThreadX kernel.  */
    tx_kernel_enter();
}
bo-ms commented 3 years ago

@nik-markovic first using malloc for embedded software is not encouraged. If you do want to use malloc, you can increase the heap size in iar\common_hardware_code\stm32l4s5xx_flash.icf.

define symbol ICFEDIT_size_heap = 0x200;

nik-markovic commented 3 years ago

@bo-ms The decision use or not to use malloc should be differed to the developers. Malloc has its uses in embedded development. You are using it in the Azure C SDK which is being used across many embedded products. I also want to use the cJSON library (I don't want to use the alternatives) and I am willing ignore fragmentation because there's plenty of heap available.

I an using the Cube IDE project. I don't see how "increasing" heap size would help with malloc behavior that does not behave per C standard. The default project is already using all available ram for heap. I never said that I needed more heap. I would just hope that you can fix the issue in your SDK.

goldscott commented 3 years ago

Hi @nik-markovic - we don't provide/maintain the malloc implementation. Have you talked to the folks who wrote it?

ryanwinter commented 3 years ago

hi @nik-markovic , the C0SDK was designed to not use the heap in any way, if you are seeing heap allocation in the C-SDK, then this is a bug.

Are you able to point and where the heap allocation is?

nik-markovic commented 3 years ago

@goldscott I think that I understand what you are saying now. You are not providing a malloc implementation in the SDK, but I was expecting that the customer projects (deriving form your sample) would be able to use malloc.

For the STM32L4+ CubeIDE flaveor, the malloc implementation coming from the CubeIDE's toolchain. For example, found in sample_azure_iot_embedded_sdk/Debug/sample_azure_iot_embedded_sdk.map if malloc is linked in:

/opt/st/stm32cubeide_1.6.0/plugins/com.st.stm32cube.ide.mcu.externaltools.gnu-tools-for-stm32.9-2020-q2-update.linux64_1.5.0.202011040924/tools/bin/../lib/gcc/arm-none-eabi/9.3.1/../../../../arm-none-eabi/lib/thumb/v7e-m+fp/hard/libc_nano.a(lib_a-findfp.o) (_malloc_r)

Since you are providing the reference project and STM32L4 configuration, I probably incorrectly assumed that you would configure newlib (that comes with he toolchain that comes with the IDE) and provide malloc functionality... I'm no embedded expert, but I'm under the impression that _sbrk may need to be implanted to limit heap to the boundaries set by the linker configuration file.

I ok with assuming that am on my own here, and that I should figure this out, as it falls out of scope and supported features of AzureRTOS. Though... it would probably be the first development environment for a device that I've encountered that doesn't support it. Even though you do not use malloc in your implementation or provide an actual implementation for it, it would be nice if malloc was at least supported in the sample reference project configuration.

@ryanwinter I wasn't referring to the AzureRTOS Azure C SDK port. I was referring to azure-iot-sdk-c on github

Thanks!

ryanwinter commented 3 years ago

Hi @nik-markovic,

Thanks for pointing out the azure-iot-sdk-c implementation.

That SDK is not meant for embedded devices, although it is still used in that way. Please use the Azure SDK for C for embedded devices which doesn't use heap allocation. The Azure RTOS middleware is built on top of this SDK. (I know, the names are confusingly similar).

nik-markovic commented 3 years ago

@ryanwinter Oh I see...

Though comment "Please use the Azure SDK for C for embedded devices" does not apply to me. I never used the Azure C SDK nor do I have intention to use it currently. I need to use the AzureRTOS and cJSON library in my application (which needs malloc). I was just trying to point out (with a bad example) that comment "don't use malloc in embedded" is a bit harsh and that malloc is sometimes used in embedded devices nowadays, so that memory can be more efficiently shared - compared to overhead of fixed buffers or implementing a sharing mechanism for those buffers. More often than not the underlying (RT)OS provides efficient mechanisms to deal with fragmentation... FreeRTOS and Zephyr comes to mind.

Anyways, thanks for pointing out my Azure C SDK confusion.

goldscott commented 3 years ago

I don't think anybody harshly said "don't use malloc." Bo stated "using malloc for embedded software is not encouraged." Obviously, there are cases when malloc is needed, but we encourage people to avoid it if possible.

Malloc is typically provided in the libraries included with the compiler.

bo-ms commented 3 years ago

@goldscott thanks for clarifying it.