[Edward.Hartmann – Mon Aug 20, 2018 2:26 pm] –
…Is there any way around this?
Don’t allocate more than the available memory
.
Without an OS to dish out memory, the simpler embedded algorithms don’t have any checks.
If you want some code to implement your own free ram check, there is a recent thread which covers this:
viewtopic.php?f=3&t=4009
But be careful, as the libc malloc is a block allocator, so it will allocate more than you request – how much more depends on a number of heuristics.
EDIT:
The simplest free space check should be something like:
char foo; // this will place a variable on the *bottom* of the stack area
uint32_t freespace = &foo - (char*)sbrk(0); // sbrk(0) will return the *top* of the heap area
[Edward.Hartmann – Mon Aug 20, 2018 2:26 pm] –
If I use malloc() with a size greater than the available memory, the malloc hangs instead of returning an null pointer. Is there any way around this?
- You could provide your own malloc /free _sbrk routines. Look in stm32STM32F1/variants/generic_stm32f103c/wirish/syscalls.c
- You could malloc all the memory you need in setup() and dole it out yourself.
- You could declare a global uint8_t buffer[8192] array as a global variable and manage its use yourself.
- You could make a custom c++ class and override the operator new and delete routines. Again snagging all the memory you need up front.
- You could change platform.txt and use -spec=nano.specs to use the smaller/faster to release newlib malloc routines
You can prevent the heap from overflowing the stack with a small change to _sbrk in sycalls.c:
//if ((CONFIG_HEAP_END - pbreak < incr) || // change this to
if (((void*)&ret - pbreak < incr) ||
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 ((CONFIG_HEAP_END - pbreak < incr) ||
if (((void*)&ret - pbreak < incr + __sbrk_stack_reserve) ||
(pbreak - CONFIG_HEAP_START < -incr)) {
errno = ENOMEM;
return (void *)-1;
}
ret = pbreak;
pbreak += incr;
return ret;
}
extern "C" char* sbrk(int incr);
static int FreeStack() {
char top = 't';
return &top - reinterpret_cast<char*>(sbrk(0));
}
https://en.wikipedia.org/wiki/Memory_management_unit
there isn’t an OS and more than that there isn’t *virtual memory*, since a long time back when x86 become the 286, 386 with transition to 32 bits is the other addition which is the MMU that creates a 4GB virtual address space, along with that elaborate memory management by the os kernel and libraries etc. that makes it possible for hardware memory protection and more importantly *between processes*
i think stm32 (even including the F1) has an MPU, but the MPU isn’t the MMU and it is somewhat a ‘dark art’ (pretty much ignored as the thoughts is there is (only) 20k of sram, u’d just use whatever there is out there
)
i did a little google and run into a few articles about the largely ignored/neglected MPU, i doubt if it is literally in use as that would cost likely more codes and memory usage on bp/mm etc
https://www.embedded.com/electronics-bl … Cortex-MPU
https://www.st.com/resource/en/applicat … 272912.pdf
^^ this doc from ST tells quite abit about the memory architecture of Cortex-M procesors, one of the key things mentioned is “fixed default memory map” (section 2.1 memory model). i.e. no virtual address, hence you can’t create the illusion that the app has all the memory to itself and create elaborate page fault management (e.g. you can’t separate ‘stack’ and global memory, they are in the *same* memory)
given this, i’d think it is quite possible the stack grows downwards and overwrite ‘global’ memory where the global variables are stored (it is 20k of sram after all). if one really want to explore the depths, one may delve deeper into the MPU to see how that may help.
bare metal programming is pretty much a compromise of sorts, pretty much a ‘best effort’ basis given the extremely limited ram etc
i’d think the safest *dynamic* memory is the *stack* (i.e. local variables), for a queue, i used fixed length circular buffer
https://hackaday.com/2015/10/29/embed-w … r-buffers/


