You have probably noticed there is more power in the STM32 processors than simple tasks can use. In this case you probably want to run some more “tasks”.
FreeRTOS has just the stuff you need – tasks, mutexes/semaphores, queues.
Unfortunately I ran into trouble with newlib and FreeRTOS not playing nicely as they should. Memory allocation (malloc) didn’t work as expected and caused the CPU to Bus-Fault. Then I realized there is another allocator in the FreeRTOS, and why does one need 2 allocators on embeded system ?
First of all, you need to be sure that you compiled newlib with something like (MALLOC_PROVIDED being the important here)
make CFLAGS_FOR_TARGET="-msoft-float -DMALLOC_PROVIDED" CCASFLAGS="-msoft-float -DMALLOC_PROVIDED"
By doing this you tell newlib that you are going to provide malloc and friends (that includes: free, realloc, calloc)
Go ahead and fetch the sources of FreeRTOS from HERE. Unpack them. Examples are taking the most of space in the package. Most of them are ready to compile (if you have the correct compiler/IDE)
Next thing you need is a “glue” that tells newlib to use the allocator of FreeRTOS. I suggest that you use heap2.c allocator. (allocator heap1.c is too simple for this use. Heap3.c uses external library, which could have been malloc from newlib, if it were working right :) )
The glue can be downloaded here: alloc.c.
It implements functions like _malloc_r, _free_r, etc. (R standing for reentrant?) All of these functions are straight-forward, except realloc, that needs to copy some memory. I have not done very extensive testing on this. The state is now “Works-For-ME”, so far I have tested sprintf function while testing gcc to support soft-float. The sprintf probably uses only malloc and free.
If you have any suggestions, patches, please comment.
I have created project that runs on Olimex’s stm32-103stk using FreeRTOS. The project includes:
- Makefile (to help putting everything together – not my work)
- SPI Master driver (using DMA transfers, and locking support)
- Simple menu for the LCD.
- Nokia 3310 LCD driver (again not my work, but heavily modified to support my SPI driver)
If anyone is interested just leave a comment, I will put together some releasable version :)
Update: I have created git repository with my projects HERE.
Some notes about newlib:
Don’t use [s|vs|…]printf if you are dealing with integers only. Use *iprintf versions instead, these don’t include printing of floating point, reduce size of final code, and should be faster – they use static buffer instead of allocating one.
12 comments
Comments feed for this article
March 10, 2010 at 09:14
Michal
Very interesting. I spent last night trying to compile FreeRTOS 6.0.2 Demo for STM32 with GCC (using STM32 IAR tree as a base and a couple of bits and bobs from other demos) but got stuck in linking with:
…./arm-none-eabi/lib/thumb/libc.a(lib_a-sbrkr.o): In function `_sbrk_r’:
sbrkr.c:(.text+0xc): undefined reference to `_sbrk’
…./arm-none-eabi/lib/thumb/libc.a(lib_a-writer.o): In function `_write_r’:
writer.c:(.text+0x10): undefined reference to `_write’
…./arm-none-eabi/lib/thumb/libc.a(lib_a-closer.o): In function `_close_r’:
closer.c:(.text+0xc): undefined reference to `_close’
[..etc..]
I don’t posses the board the demo is written for so I couldn’t test my mods anyway, just wanted to have a working build environment before starting with my experiments.
However if you could send me your code that might help a lot. It doesn’t need to be polished, I don’t have the Olimex board either. I just need a working FreeRTOS project ready to compile with GCC for reference.
Thanks!
March 10, 2010 at 10:40
Michal
i have created git repo on github, you can download the whole project. If you need any help, just ask ;)
March 10, 2010 at 23:32
Michal
Got it, thanks. FYI compiles fine with
arm-none-eabi-gcc (Sourcery G++ Lite 2009q3-68) 4.4.1
March 11, 2010 at 06:46
Michal
just be sure that you check the interrupt vector !
The one I have is for medium density devices, other densities might have different order. Check with CMSIS headers or datasheet.
I spent 3 hours figuring out the NVIC interrupt controller :)
May 21, 2010 at 14:13
serious
A godsend. I’ve been pulling my hair out with Hard Faults and spent the last 5 hours down in single-step-assembly mode to then find out that CodeSourcery’s C++ “new” is calling the internal malloc which isn’t even close to properly initialized (my loader script is focused on the heap2.c mechanisms) so it’s stomping all over RAM. How does _sbrk fit into this equation?
May 21, 2010 at 14:52
Michal
_sbrk is only needed for the newlib malloc. heap2.c does not use dynamic heap allocation, it has large static array, and does allocation in this array. Size of this array is controlled by “configTOTAL_HEAP_SIZE” in freertos.h
I think I have found a way to fix the malloc, but don’t have the time to implement or test it. You need to implement some stubs from the newlib for the malloc to work properly in multi-thread application. I’ll look into it in few weeks – I am rather busy now :(
May 21, 2010 at 15:35
serious
I guess it’s not as simple as wrapping a mutex around the calls and ensuring that portions of the malloc are non-preemptable (like is built into heap2 already), huh?
May 21, 2010 at 15:50
Michal
You should read this article http://www.embedded.com/story/OEG20020103S0073
It will tell you more about the stubs in newlib library.
You will need to implement __malloc_lock, __malloc_unlock stubs. I guess that recursive mutex is the best for the job. Just be sure to initialize it soon enough :) (before the start of scheduler ? )
July 7, 2011 at 15:28
Justin
One thing I found when writing my own similar realloc() is that block->xBlockSize is actually the size of the full block, including the block header. So you really want to copy xBlockSize – heapSTRUCT_SIZE, to avoid corruption problems.
October 28, 2013 at 22:14
tomi
Can you share program or script for can_boot. How to upload bin file with this bootloader ?
October 29, 2013 at 10:54
Michal
can-boot has never been tested, and i think the message handling is not written correctly. It will needs some tweaking and testing.
Idea was to use linux socket-can api, to comunicate with the boards.
If you get it working, please let me know.
October 30, 2013 at 19:47
tomi
I have small home automation network on CAN bus. I can try debug and ifx up STM32 code, but I don’t have experience with linux programing. Can you help with python socket-can api or another script to use this bootloader ?