From 61414bb9bb0cb275433f7b371ac7cee6fb7e95c5 Mon Sep 17 00:00:00 2001 From: Samuel Sadok Date: Mon, 12 Mar 2018 17:22:25 -0700 Subject: [PATCH] implement _sbrk_r syscall Without implementing _sbrk_r, the weak symbol from newlib-nano is used which calls _sbrk which does not check for RAM end: ``` _sbrk: ldr r2, [pc, #16] ; (8013fa0 <_sbrk+0x14>) ldr r1, [pc, #20] ; (8013fa4 <_sbrk+0x18>) ldr r3, [r2, #0] cmp r3, #0 it eq moveq r3, r1 add r0, r3 str r0, [r2, #0] mov r0, r3 bx lr ``` ``` void** heap_end; void* end; void* _sbrk(size_t size) { void* r3 = *heap_end; if (r3 == NULL) r3 = end; size += r3; *heap_end = size; return r3; } ``` The implementation in this commit returns an error code if the heap would otherwise extend into the reserved stack memory of 0x800 bytes. --- Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld | 1 + Firmware/Board/v3.3/Src/syscalls.c | 41 +++++++++++++++++++++- 2 files changed, 41 insertions(+), 1 deletion(-) diff --git a/Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld b/Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld index 3b96fa83..6a08d185 100644 --- a/Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld +++ b/Firmware/Board/v3.3/STM32F405RGTx_FLASH.ld @@ -37,6 +37,7 @@ _estack = 0x20020000; /* end of RAM */ /* Generate a link error if heap and stack don't fit into RAM */ _Min_Heap_Size = 0x3C00; /* required amount of heap */ _Min_Stack_Size = 0x800; /* required amount of stack */ +_heap_end_max = _estack - _Min_Stack_Size; /* Specify the memory areas */ MEMORY diff --git a/Firmware/Board/v3.3/Src/syscalls.c b/Firmware/Board/v3.3/Src/syscalls.c index 3ddb5701..e55bcd7d 100644 --- a/Firmware/Board/v3.3/Src/syscalls.c +++ b/Firmware/Board/v3.3/Src/syscalls.c @@ -1,7 +1,7 @@ /** ****************************************************************************** * @file : syscalls.c - * @brief : This file implements printf functionality + * @brief : This file implements OS functionality needed by newlib ****************************************************************************** */ @@ -19,6 +19,45 @@ //int _fstat(int file, struct stat *st) {} //int _isatty(int file) {} +extern char _end; // provided by the linker script +extern char _heap_end_max; // provided by the linker script +void* _end_ptr = &_end; +void* _heap_end_max_ptr = &_heap_end_max; +void* heap_end_ptr = 0; + +/* @brief Increments the program break (aka heap end) +* +* This is called internally by malloc once it runs out +* of heap space. Malloc might expect a contiguous heap, +* so we don't call the FreeRTOS pvPortMalloc here. +* If this function returns -1, malloc will return NULL. +* Note that if this function returns NULL, malloc does not +* consider this as an error and will return the pointer 0x8. +* +* You should still be careful with using malloc though, +* as it does not guarantee thread safety. +* +* @return A pointer to the newly allocated block on success +* or -1 otherwise. +*/ +intptr_t _sbrk_r(struct _reent *ignored __attribute__((unused)), size_t size) { + intptr_t ptr; + vTaskSuspendAll(); + { + if (!heap_end_ptr) + heap_end_ptr = _end_ptr; + if (heap_end_ptr + size > _heap_end_max_ptr) { + ptr = -1; + } else { + ptr = (intptr_t)heap_end_ptr; + heap_end_ptr += size; + } + } + (void)xTaskResumeAll(); + return ptr; +} + + #define UART_TX_BUFFER_SIZE 64 static uint8_t uart_tx_buf[UART_TX_BUFFER_SIZE];