From e2dec698b17a7b02976e6f9b12977768032c2833 Mon Sep 17 00:00:00 2001 From: justinschoeman <37309347+justinschoeman@users.noreply.github.com> Date: Mon, 20 Aug 2018 21:03:15 +0200 Subject: [PATCH 1/4] Limit dynamic memory allocation to stack + reserve The current _sbrk allows the entire RAM (including space already used by the stack) to be allocated by malloc/new calls. This change limits it to the bottom of the stack + an application modifiable reserve (to make sure there is a minimum amount of space reserved for future stack growth). --- .../variants/generic_stm32f103c/syscalls.c | 183 ++++++++++++++++++ 1 file changed, 183 insertions(+) create mode 100644 STM32F1/variants/generic_stm32f103c/syscalls.c diff --git a/STM32F1/variants/generic_stm32f103c/syscalls.c b/STM32F1/variants/generic_stm32f103c/syscalls.c new file mode 100644 index 000000000..d8b751cf3 --- /dev/null +++ b/STM32F1/variants/generic_stm32f103c/syscalls.c @@ -0,0 +1,183 @@ +/****************************************************************************** + * The MIT License + * + * Copyright (c) 2010 Perry Hung. + * Copyright (c) 2011, 2012 LeafLabs, LLC. + * + * Permission is hereby granted, free of charge, to any person + * obtaining a copy of this software and associated documentation + * files (the "Software"), to deal in the Software without + * restriction, including without limitation the rights to use, copy, + * modify, merge, publish, distribute, sublicense, and/or sell copies + * of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be + * included in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, + * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND + * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS + * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN + * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE + * SOFTWARE. + *****************************************************************************/ + +/** + * @file wirish/syscalls.c + * @brief newlib stubs + * + * Low level system routines used by newlib for basic I/O and memory + * allocation. You can override most of these. + */ + +#include + +#include +#include +#include + +/* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then + * assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by + * the linker */ +#ifndef CONFIG_HEAP_START +extern char _lm_heap_start; +#define CONFIG_HEAP_START ((void *)&_lm_heap_start) +#endif +#ifndef CONFIG_HEAP_END +extern char _lm_heap_end; +#define CONFIG_HEAP_END ((void *)&_lm_heap_end) +#endif + +/* + * _sbrk -- Increment the program break. + * + * Get incr bytes more RAM (for use by the heap). malloc() and + * friends call this function behind the scenes. + * + * The following can be included in application code to reserve + * a minimum amount of space for future stack growth: + * extern int __sbrk_stack_reserve; + * __sbrk_stack_reserve=10240; + * + */ +volatile int __sbrk_stack_reserve = 256; +void *_sbrk(int incr) { + static void * pbreak = NULL; /* current program break */ + void * ret; + + if (pbreak == NULL) { + pbreak = CONFIG_HEAP_START; + } + + if (((void*)&ret - pbreak < incr + __sbrk_stack_reserve) || + (pbreak - CONFIG_HEAP_START < -incr)) { + errno = ENOMEM; + return (void *)-1; + } + + ret = pbreak; + pbreak += incr; + return ret; +} + +__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { + return 1; +} + +__weak int _close(int fd __attribute__((unused))) { + return 0; +} + +__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { + st->st_mode = S_IFCHR; + return 0; +} + +__weak int _isatty(int fd __attribute__((unused))) { + return 1; +} + +__weak int isatty(int fd __attribute__((unused))) { + return 1; +} + +__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { + return -1; +} + +__weak unsigned char getch(void) { + return 0; +} + + +__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { + *buf = getch(); + + return 1; +} + +__weak void putch(unsigned char c __attribute__((unused))) { +} + +__weak void cgets(char *s, int bufsize) { + char *p; + int c; + int i; + + for (i = 0; i < bufsize; i++) { + *(s+i) = 0; + } +// memset(s, 0, bufsize); + + p = s; + + for (p = s; p < s + bufsize-1;) { + c = getch(); + switch (c) { + case '\r' : + case '\n' : + putch('\r'); + putch('\n'); + *p = '\n'; + return; + + case '\b' : + if (p > s) { + *p-- = 0; + putch('\b'); + putch(' '); + putch('\b'); + } + break; + + default : + putch(c); + *p++ = c; + break; + } + } + return; +} + +__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { + int i; + + for (i = 0; i < cnt; i++) + putch(buf[i]); + + return cnt; +} + +/* Override fgets() in newlib with a version that does line editing */ +__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { + cgets(s, bufsize); + return s; +} + +__weak void _exit(int exitcode __attribute__((unused))) { + while (1) + ; +} From 707ebdf021dbe57d1fc29cc5424155092159d40c Mon Sep 17 00:00:00 2001 From: justinschoeman <37309347+justinschoeman@users.noreply.github.com> Date: Mon, 20 Aug 2018 21:08:12 +0200 Subject: [PATCH 2/4] Limit dynamic memory allocation to stack + reserve The current _sbrk allows the entire RAM (including space already used by the stack) to be allocated by malloc/new calls. This change limits it to the bottom of the stack + an application modifiable reserve (to make sure there is a minimum amount of space reserved for future stack growth). --- STM32F1/variants/generic_stm32f103c/wirish/syscalls.c | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c b/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c index 91ed5a104..d8b751cf3 100644 --- a/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c +++ b/STM32F1/variants/generic_stm32f103c/wirish/syscalls.c @@ -56,7 +56,14 @@ extern char _lm_heap_end; * * Get incr bytes more RAM (for use by the heap). malloc() and * friends call this function behind the scenes. + * + * The following can be included in application code to reserve + * a minimum amount of space for future stack growth: + * extern int __sbrk_stack_reserve; + * __sbrk_stack_reserve=10240; + * */ +volatile int __sbrk_stack_reserve = 256; void *_sbrk(int incr) { static void * pbreak = NULL; /* current program break */ void * ret; @@ -65,7 +72,7 @@ void *_sbrk(int incr) { pbreak = CONFIG_HEAP_START; } - if ((CONFIG_HEAP_END - pbreak < incr) || + if (((void*)&ret - pbreak < incr + __sbrk_stack_reserve) || (pbreak - CONFIG_HEAP_START < -incr)) { errno = ENOMEM; return (void *)-1; From 05c305c3dc2f73869126d85c3a960b99a0b7f26e Mon Sep 17 00:00:00 2001 From: justinschoeman <37309347+justinschoeman@users.noreply.github.com> Date: Mon, 20 Aug 2018 21:10:47 +0200 Subject: [PATCH 3/4] Delete syscalls.c --- .../variants/generic_stm32f103c/syscalls.c | 183 ------------------ 1 file changed, 183 deletions(-) delete mode 100644 STM32F1/variants/generic_stm32f103c/syscalls.c diff --git a/STM32F1/variants/generic_stm32f103c/syscalls.c b/STM32F1/variants/generic_stm32f103c/syscalls.c deleted file mode 100644 index d8b751cf3..000000000 --- a/STM32F1/variants/generic_stm32f103c/syscalls.c +++ /dev/null @@ -1,183 +0,0 @@ -/****************************************************************************** - * The MIT License - * - * Copyright (c) 2010 Perry Hung. - * Copyright (c) 2011, 2012 LeafLabs, LLC. - * - * Permission is hereby granted, free of charge, to any person - * obtaining a copy of this software and associated documentation - * files (the "Software"), to deal in the Software without - * restriction, including without limitation the rights to use, copy, - * modify, merge, publish, distribute, sublicense, and/or sell copies - * of the Software, and to permit persons to whom the Software is - * furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be - * included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, - * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF - * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND - * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS - * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN - * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN - * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE - * SOFTWARE. - *****************************************************************************/ - -/** - * @file wirish/syscalls.c - * @brief newlib stubs - * - * Low level system routines used by newlib for basic I/O and memory - * allocation. You can override most of these. - */ - -#include - -#include -#include -#include - -/* If CONFIG_HEAP_START (or CONFIG_HEAP_END) isn't defined, then - * assume _lm_heap_start (resp. _lm_heap_end) is appropriately set by - * the linker */ -#ifndef CONFIG_HEAP_START -extern char _lm_heap_start; -#define CONFIG_HEAP_START ((void *)&_lm_heap_start) -#endif -#ifndef CONFIG_HEAP_END -extern char _lm_heap_end; -#define CONFIG_HEAP_END ((void *)&_lm_heap_end) -#endif - -/* - * _sbrk -- Increment the program break. - * - * Get incr bytes more RAM (for use by the heap). malloc() and - * friends call this function behind the scenes. - * - * The following can be included in application code to reserve - * a minimum amount of space for future stack growth: - * extern int __sbrk_stack_reserve; - * __sbrk_stack_reserve=10240; - * - */ -volatile int __sbrk_stack_reserve = 256; -void *_sbrk(int incr) { - static void * pbreak = NULL; /* current program break */ - void * ret; - - if (pbreak == NULL) { - pbreak = CONFIG_HEAP_START; - } - - if (((void*)&ret - pbreak < incr + __sbrk_stack_reserve) || - (pbreak - CONFIG_HEAP_START < -incr)) { - errno = ENOMEM; - return (void *)-1; - } - - ret = pbreak; - pbreak += incr; - return ret; -} - -__weak int _open(const char *path __attribute__((unused)), int flags __attribute__((unused)), ...) { - return 1; -} - -__weak int _close(int fd __attribute__((unused))) { - return 0; -} - -__weak int _fstat(int fd __attribute__((unused)), struct stat *st) { - st->st_mode = S_IFCHR; - return 0; -} - -__weak int _isatty(int fd __attribute__((unused))) { - return 1; -} - -__weak int isatty(int fd __attribute__((unused))) { - return 1; -} - -__weak int _lseek(int fd __attribute__((unused)), off_t pos __attribute__((unused)), int whence __attribute__((unused))) { - return -1; -} - -__weak unsigned char getch(void) { - return 0; -} - - -__weak int _read(int fd __attribute__((unused)), char *buf, size_t cnt __attribute__((unused))) { - *buf = getch(); - - return 1; -} - -__weak void putch(unsigned char c __attribute__((unused))) { -} - -__weak void cgets(char *s, int bufsize) { - char *p; - int c; - int i; - - for (i = 0; i < bufsize; i++) { - *(s+i) = 0; - } -// memset(s, 0, bufsize); - - p = s; - - for (p = s; p < s + bufsize-1;) { - c = getch(); - switch (c) { - case '\r' : - case '\n' : - putch('\r'); - putch('\n'); - *p = '\n'; - return; - - case '\b' : - if (p > s) { - *p-- = 0; - putch('\b'); - putch(' '); - putch('\b'); - } - break; - - default : - putch(c); - *p++ = c; - break; - } - } - return; -} - -__weak int _write(int fd __attribute__((unused)), const char *buf, size_t cnt) { - int i; - - for (i = 0; i < cnt; i++) - putch(buf[i]); - - return cnt; -} - -/* Override fgets() in newlib with a version that does line editing */ -__weak char *fgets(char *s, int bufsize, void *f __attribute__((unused))) { - cgets(s, bufsize); - return s; -} - -__weak void _exit(int exitcode __attribute__((unused))) { - while (1) - ; -} From 6851b5ae48537346d0179a0a5199cc701624ab70 Mon Sep 17 00:00:00 2001 From: justinschoeman <37309347+justinschoeman@users.noreply.github.com> Date: Thu, 23 Aug 2018 19:42:23 +0200 Subject: [PATCH 4/4] Add -fno-use-cxa-atexit compiler flag --- STM32F1/platform.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/STM32F1/platform.txt b/STM32F1/platform.txt index fbeaac41e..7a0218579 100644 --- a/STM32F1/platform.txt +++ b/STM32F1/platform.txt @@ -22,7 +22,7 @@ compiler.c.elf.flags={build.flags.optimize} -Wl,--gc-sections {build.flags.ldspe compiler.S.cmd=arm-none-eabi-gcc compiler.S.flags=-c -g -x assembler-with-cpp -MMD compiler.cpp.cmd=arm-none-eabi-g++ -compiler.cpp.flags=-c -g {build.flags.optimize} {compiler.warning_flags} -std=gnu++11 -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} +compiler.cpp.flags=-c -g {build.flags.optimize} {compiler.warning_flags} -std=gnu++11 -MMD -ffunction-sections -fdata-sections -nostdlib --param max-inline-insns-single=500 -fno-rtti -fno-exceptions -fno-use-cxa-atexit -DBOARD_{build.variant} -D{build.vect} -DERROR_LED_PORT={build.error_led_port} -DERROR_LED_PIN={build.error_led_pin} compiler.ar.cmd=arm-none-eabi-ar compiler.ar.flags=rcs compiler.objcopy.cmd=arm-none-eabi-objcopy @@ -174,4 +174,4 @@ tools.hid_upload.path.linux={runtime.hardware.path}/tools/linux tools.hid_upload.path.linux64={runtime.hardware.path}/tools/linux64 tools.hid_upload.upload.params.verbose=-d tools.hid_upload.upload.params.quiet=n -tools.hid_upload.upload.pattern="{path}/{cmd}" "{build.path}/{build.project_name}.bin" {serial.port.file} \ No newline at end of file +tools.hid_upload.upload.pattern="{path}/{cmd}" "{build.path}/{build.project_name}.bin" {serial.port.file}