So I've been quietly chugging along updating this code with new examples. The latest example shows some interesting techniques for stack and heap usage and debugging. I don't use FreeRTOS
with this one, I found a less complex cooperative multitasking library with less features but much smaller. Find the code here: https://github.com/RickKimball/bluepill ... /example08
I've provide a few different linker scripts that work with the 'C" based Reset_Handler. The default script stm32f103cb.ld uses the normal stack and memory layout you would expect. Flash for the code, Stack at 0x20005000 growing down, heap starting after the bss end.
A more interesting ldscript places the stack at the bottom of memory and grows it down towards 0x20000000. You can see how I use the _Min_Stack_Size
to set the top of the stack and set the beginning of RAM to start after it
. The advantage to this approach is that the stack and the heap will never collide. If you exceed the stack size, it will trigger a HardFault_Handler and you can know that your stack is too small. To help you diagnose the problem you can use the vectorstate
macro I include as part of invoking "$ make debug". So if it gets stuck in one of the exception handlers, press CTRL-C and then type vectorstate to see what is going on. Also, if you exceed heap memory, it will also trigger a BusFault if it goes past the end of memory. This is actually much safer than having the heap write over the stack and never being able to detect it.
Another feature I added was "Coloring" the memory. When the Reset_Handler first gets control, it will optionally write a pattern to the STACK (0xcccccccc) memory and HEAP (0xcdcdcdcd) memory.
If you use gdb to examine memory, you can see which memory addresses have actually been used. This can help you optimally set your STACK and HEAP sizes.
And finally I created a "ram" make target. This builds the code so it runs all in memory. You will never wear out your flash using this option, assuming all your code, stack and heap can fit in 20K
Code: Select all
$ make clean ram
$ make debug
(gdb) monitor reset init
All the peripherals are being accessed using only the device header (stm32f103xb.h) however I did add some simple cooperative multitasking using the Arduino Scheduler Library. Surprising as it seems, it actually doesn't use any Arduino code at all and it only implemented for arm cortex chips. It is nice and small and doesn't really add much overhead. It is only a couple of files, Scheduler.cpp and Scheduler.h. If you don't use any newlib printing features, the binary for a 2 task .elf file comes in at less than 2K of flash and defaults to 1K of heap memory, however you can probably cut that down to less than 256 bytes of heap.
And finally, I'm compiling all this stuff with the latest linaro arm-eabi-gcc binary. It uses std++17 and gcc 8.3.0.
This exampl08 is still a work in progress, but I thought I'd post an update here and get it into github before I lose it
As much as I don't want to admit it, I'm really enjoying using the vscode editor and the environment it provides to hide the ugliness of raw git, raw make, and raw gdb.