STM32F4 – Deploy FreeRTOS Embedded OS in under 10 seconds!

In this tutorial I describe how to build and deploy the FreeRTOS embedded operating system on STM32F4 Discovery board under 10 seconds. So why would you use operating system on such a small embedded system in the first place?

Typically, you don’t if you have a single task problem. However, if you have a multitasking problem (What’s that? See the youtube clip below.), OS provides you among other benefits an infrastructure to seamlessly implement tasks and to run them simultaneously.

Each task receives a fair proportion of CPU time (in our case ~1 ms per time slice). After a task uses its allocated time slice, OS interrupts its execution. Then context switch occurs. Current task is stored (i.e. current CPU register values, stack, heap,…) and next scheduled task is loaded and executed seamlessly. Actually, you could implement these OS functions all by yourself, however it is easier to use the existing, tested and already working OS code, such as FreeRTOS. πŸ™‚

1. Prerequisites

cd ~
# Remove the official package
sudo apt-get purge binutils-arm-none-eabi \
                   gcc-arm-none-eabi \
                   gdb-arm-none-eabi \

# Add 3rd party repository
sudo add-apt-repository ppa:terry.guo/gcc-arm-embedded
sudo apt-get update
# Check the GCC package version in the PPA repository
sudo apt-cache policy gcc-arm-none-eabi

# Install software requirements
sudo apt-get install build-essential git openocd \
 gcc-arm-none-eabi qemu-system-arm \
 symlinks expect

# Clone my git repository and init submodules
git clone
cd ~/stm32
git submodule update --init


2.Β  Build the FreeRTOS project

Use the provided Makefile to automagically build and deploy the project.

cd ~/stm32/examples/FreeRTOS

make clean
make -j4 # Non-optimized build
# Other build options
# make -j4 release # Non-optimized Build
# make -j4 release-memopt # Size Optimized Build
# make -j4 debug # Debug Build

sudo make deploy

… and the result.


The green LED toggles every 1.5 s. You can toggle the red LED by pressing the blue button.

The green LED toggles every 1.5 s. You can toggle the red LED by pressing the blue button.

In fact, you can have this FreeRTOS project as a project template. As long as you add or remove appropriate files from inc and src directories, the Makefile will automagically include them during the build time. πŸ˜‰

Q: Deployment fails repeatedly due to some OpenOCD issue. 😦 Is there a workaround?
A: Yes, the current official Ubuntu package (Aug 2014) contains a prehistoric OpenOCD version. You should build a newer version from scratch. I provide step-by-step instructions here (2nd section, it takes less than 3 minutes to build it). When you are done, just return here and continue as nothing happened. It will work out of the box. πŸ™‚

3. How to Hook up FreeRTOS Source Code

In this section I describe how I hooked up FreeRTOS and a standalone project.

I used the generic project template from the section 5 of the Hello World! tutorial (stm32/examples/GPIO). I added FreeRTOS source and includes. More detailed file list is provided in the project’s tree structure below. I removed duplicate (conflicting) interrupt handlers from stm32f4xx_it.c file. I provided main.c file to initialize hardware, OS and 3 threads.

cd ~/stm32/examples/FreeRTOS
# tree
# .
# β”œβ”€β”€ bin
# β”œβ”€β”€ inc
# β”‚Β Β  β”‚ # Added FreeRTOS Includes
# β”‚Β Β  β”œβ”€β”€ FreeRTOS
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/croutine.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/event_groups.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/FreeRTOS.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/list.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/mpu_wrappers.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/portable.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/timers.h
# β”‚   β”‚Β Β  β”œβ”€β”€ Source/include/projdefs.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/queue.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/semphr.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/StackMacros.h
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/include/task.h
# β”‚Β Β  β”‚Β Β  └── Source/portable/GCC/ARM_CM4F/portmacro.h
# |   |
# |   | # Added FreeRTOS Config File
# |   | # Here you can edit FreeRTOS settings
# β”‚Β Β  β”œβ”€β”€ FreeRTOSConfig.h
# β”‚Β Β  β”‚
# β”‚Β Β  β”‚ # Existing Hello World Project Includes
# β”‚Β Β  β”œβ”€β”€ CMSIS/Include
# β”‚Β Β  β”œβ”€β”€ stm32f4_discovery.h
# β”‚Β Β  β”œβ”€β”€ STM32F4xx/Include
# β”‚Β Β  β”œβ”€β”€ stm32f4xx_conf.h
# β”‚Β Β  β”œβ”€β”€ stm32f4xx_it.h
# β”‚Β Β  └── STM32F4xx_StdPeriph_Driver/inc
# |
# β”œβ”€β”€ src
# β”‚Β Β  β”‚ # Added New FreeRTOS Source Files
# β”‚Β Β  β”œβ”€β”€ FreeRTOS
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/croutine.c
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/event_groups.c
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/portable/MemMang/heap_1.c
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/list.c
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/portable/GCC/ARM_CM4F/port.c
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/queue.c
# β”‚Β Β  β”‚Β Β  β”œβ”€β”€ Source/tasks.c
# β”‚Β Β  β”‚Β Β  └── Source/timers.c
# |   |
# |   | # Here you can add multi-threaded applications.
# β”‚ Β  β”œβ”€β”€ main.c
# |   |
# |   | # Existing Hello World Project Source Files
# β”‚Β Β  β”œβ”€β”€ startup_stm32f4xx.s
# β”‚Β Β  β”œβ”€β”€ stm32f4_discovery.c
# |   | # Removed duplicate (conflicting)
# |   |   interrupt handlers
# β”‚Β Β  β”œβ”€β”€ stm32f4xx_it.c
# β”‚Β Β  β”œβ”€β”€ STM32F4xx_StdPeriph_Driver/src
# β”‚Β Β  └── system_stm32f4xx.c
# |
# | # Existing IO Toggle Project Makefile and
# | # Linker Script
# β”œβ”€β”€ Makefile # DON'T TOUCH
# └── stm32_flash.ld # DON'T TOUCH


4. How to Write an RTOS Application

The source code of the above application is located in the main.c file (Just don’t freak out, when you open the file. πŸ™‚ It’s only half as bad as it seems.) The main.c call flow is depicted in the UML activity diagram below.FreeRTOS Applications

First, the general purpose inputs/outputs are initialized (initHW()). Second, the following 3 tasks are created.

  • ToggleLED_Timer() toggles the green LED each 1.5 s.
  • DetectButtonPush() detects push button events and notifies ToggleLED_IPC task via inter-processes communication.
    • When a button is pushed, two metal contacts of the button strike together. Unfortunately, they start to bounce apart before making a steady contact. Microprocessor samples the input fast enough to misinterpret this bouncing as repeated push events. We handle the contact bounce by waiting until transient response passes and input reaches steady state.
    • The single event information is then relayed toΒ ToggleLED_IPC task via FreeRTOS inter-process communication, i.e. a message queue.
  • ToggleLED_IPC() reads the message queue. When it receives a push button event message, it toggles the red LED (GPIOD Pin 14).
    • The task checks for new messages very efficiently. If the message queue is empty, it rather blocks and waits to be awaken by OS, when a new message arrives. The alternative is prohibitively expensive busy waiting, which waist CPU cycles by polling.

After these task are created, they are immediately moved into the ready state. Third, the scheduler is started. Fourth, each of the following tasks receive a fair proportion of CPU time.


About istarc

Embedded Systems Developer.
This entry was posted in Embedded Systems, STM32F4 and tagged , , , , . Bookmark the permalink.

34 Responses to STM32F4 – Deploy FreeRTOS Embedded OS in under 10 seconds!

  1. fendi boots says:

    Do you mind if I quote a few of your posts as long as I provide credit and sources back
    to your website? My blog is in the exact same area of interest as yours and my users would genuinely
    benefit from some of the information you provide here.
    Please let me know if this ok with you. Cheers!

    • istarc says:

      Hi! Thanks for asking. Of course, you may use all the available material. I would be happy if you provide credit and sources back to my blog. πŸ™‚ Best regards, Iztok.

  2. supriya says:

    Hey, i am trying to install FreeRTOS on STM32F4-DISCO board, i executed all the instruction u have mentioned above and after making “make deploy”, nothing is happening.
    can u help me with what i m supposed to do? and also, how i will get to know that the FreeRTOS is installed successfully on board? Can u also tell, how i can write small C-programs and execute them. Please do reply and thanks in advance for ur help.

    • istarc says:


      @FreeRTOS: “sudo make deploy” should do the trick (the latest OpenOCD is required, so check the In-circuit Debugging post or run the script, it may also work if you install OpenOCD via apt-get).

      @Small C programs: Check the Section 2 of the Behold the Project Wizard! to generate a minimal project template. I also provide the usage instructions in this post. Again, use “make” and “sudo make deploy”. I hope this helps you further. πŸ™‚

      BR, Iztok

  3. 213ss says:

    I’m new to RTOS and I’m trying to get freertos working with stm32f4 discovery board to get a better grip with embedded RTOS. I have searched all that I can to install freertos with the discovery board but I haven’t found instructions that help.
    I tried all above steps and finally i get error message as follows
    supriya@supriya-Vostro-3546 ~/stm32/examples/FreeRTOS $ sudo make deploy
    /opt/openocd/bin/openocd -f /opt/openocd/share/openocd/scripts/board/stm32f4discovery.cfg -c “program bin/”outp.elf” verify reset”
    Open On-Chip Debugger 0.9.0-dev-00346-g3e1dfdc (2015-03-20-17:08)
    Licensed under GNU GPL v2
    For bug reports, read
    Info : The selected transport took over low-level target control. The results might differ compared to plain JTAG/SWD
    adapter speed: 2000 kHz
    adapter_nsrst_delay: 100
    none separate
    srst_only separate srst_nogate srst_open_drain connect_deassert_srst
    Info : Unable to match requested speed 2000 kHz, using 1800 kHz
    Info : Unable to match requested speed 2000 kHz, using 1800 kHz
    Info : clock speed 1800 kHz
    in procedure ‘program’
    in procedure ‘init’ called at file “embedded:startup.tcl”, line 471
    in procedure ‘ocd_bouncer’
    in procedure ‘transport’
    ** OpenOCD init failed **
    shutdown command invoked
    embedded:startup.tcl:449: Error:
    in procedure ‘program’
    in procedure ‘program_error’ called at file “embedded:startup.tcl”, line 472
    in procedure ‘shutdown’ called at file “embedded:startup.tcl”, line 449
    make: *** [deploy] Error 1

    I have tried all that I can to get it working but I’m probably missing something trivial which I can’t seem to put my finger on. If anyone could provide me with a tutorial/project of a working blink example that would be amazing.

    I have tried to make the example in the freertos website to work but I still haven’t been able to, that is why I’m asking for help here.

    I have been at this for 2-3 weeks now so if anyone can provide the project I will be extremely. thankful. E-mail ID

    • istarc says:

      Hi, “make && sudo make deploy” should work out-of-the-box. πŸ™‚ Try with the VirtualBox image (do not forget to install the ST LINK USB driver if you use Win host, and to mount the STM32 STLINK device once the virtual image is booted). Good luck!

  4. sa says:

    Thanks alot for ur help, i could install the os using all the instructions u have mentioned above :).
    Thanks a ton.

    Now can u help me by giving instructions or steps to
    1. install the freertos which i have downloaded from official sit, without cloning to github?
    My assignment’s first step is to download freertos and install that in the card and give the steps to my teacher, after which i should start programming for different scenarios.

    Thanks again,

  5. sa says:

    Is there any way to use some terminal like Putty or something similar and display out on the terminal instead of making LED Blink? If i have a Hello world program and when i put binary on the card, an interface to display the files on the card and an way to execute it using the terminal.
    Thanks for all your replies, there are helping alot and i m moving ahead in my project.

    • istarc says:

      Yes, it is possible to re-target STDIO to a serial interface. For example:

      a) Check out the BaseBoardUART.mbed-Retarget project (at stm32/examples), where STDIO is re-targeted to UART6. This and the project below are tailored to the STM32F4 Discovery Base Board.

      b) You may also check out the BaseBoardUART.mbed-Serial project (at stm32/examples), which is slightly different approach, where mbed library is used to create Serial object, which in turn is used for serial communication. This and the above approach require a serial cable and putty (or any other serial client) for UART communication.

      c) Check out the ARM semihosting approach (NativeSemihosting.mbed-cpput project at stm32/examples-xunit/native), where STDIO operations trigger software interrupts, which are in turn caught by OpenOCD debugger. This approach is the easiest to set up as it requires only the (already) attached USB cable. πŸ™‚ So, it works out-of-the-box (without additional setup or STM32F4 Discovery Base Board).

      In each case use “make clean && make -j4 && sudo make deploy” to build a project and deploy the binary.

      Good luck!

  6. sa says:

    can i do this in freertos?
    program 1 calling program 2 and 3 and executing program 1 and 2 (keep swtiching between p1 and p2). can u guide through this?
    tanx in advance, have a nice day.

    • istarc says:


      According to the FreeRTOS manual (see (buy the book :-)) it is possible to start a new task from within another task after the scheduler has started. I.e., create p2 within p1 by using xTaskCreate() function.

      Best regards, Iztok

  7. sa says:

    Thanks for the reply πŸ™‚ (i will buy the book).
    I have one more question: i want to write printf statements in main.c and print some message like “hello world” on putty. when i deploy the os on the board, i want to see the output of printf on the putty terminal. Is there a way to do that. I have been trying but the connection between the board and putty terminal does not get established.
    Can i deploy a main.c which has printf statements and when executed the output should be shown on putty.

  8. sa says:


    I Need ur help again to understand something, hope its ok with u :).
    I have created 2 tasks in main and they run properly. What i want to do is access local variables of task 2 with passing then by reference or by value neither by creating global variables. I want to print the complete stack of task2 and find local variable addresses and change them or access them in Task1.
    can u suggest me a way to do this?
    Thanks in advance πŸ™‚

    • istarc says:

      Why would you do such a thing?

      Check the FreeRTOS examples, where the use of the inter-process communication (IPC) is demonstrated. πŸ™‚ It is vastly superior to shared-memory approach you are trying to achieve right now, because sleep and wakeup is used instead of spin-lock (saves CPU cycles), and there are no concurrency issues, because send and receive IPC operations are atomic (“interruptible”). Check Tanenbaum’s Modern Operating Systems for more infos.

      Best regards, Iztok

  9. maxaxam says:


    Really appreciate your blog, it has saved me many a time.

    I have an existing project that depends on mbed for GPIO/ADC/I2C access. I would like to integrate FreeRTOS into this project. I notice your FreeRTOS main file does not go through mbed. Will I run into issues trying to combine my existing mbed-based code with your FreeRTOS template project?


    • istarc says:


      It should work out of the box. Create a new project using my project wizard /w mbed-freertos switch. Then place your existing files in the src and inc directories. Do not overwrite main.cpp, which includes a FreeRTOS example, but appropriately customize it. Good luck!

      Best regards, Iztok

  10. Vijay Karthik says:

    Hi I’m Vijay, I’m Trying to Deploy FreeRTOS onto STM32F429I-DISCO using Eclipse and GCC Plugin in Windows, Could you suggest me a way to do this task?

    • istarc says:

      Hi Vijay, can you provide some additional information? You could e.g. install Cygwin + GCC ARM Embedded for Windows, clone my stm32 repository, create a new project via my project wizard, import newly created project in Eclipse as a existing makefile project. Then you could use either (1) OpenOCD for Windows, (2) ST-LINK debugger or (3) J-Link Debugger for flashing and debugging. I hope this help you further. Best regards, Iztok.

      • Vijay Karthik says:

        Thank you istarc for your suggestion,
        I’ll try to clone your repository and experiment on it as i already have a working eclipse environment for stn32f429i-disco, I just needed the step to configure the FreeRTOS to suit the microcontroller.

        If successful I’ll definitely acknowlege you in the project.

      • istarc says:

        Thanks, Vijay, I would really appreciate your feedback. Good luck with the project! πŸ™‚

  11. Amperture says:

    Having never worked with FreeRTOS, I’m curious. Why are StdPeriph and CMSIS symlinked into the project folder, but FreeRTOS source is actually copied?

    • istarc says:

      In the earlier projects I used symlinks and it turned out to be a poor design choice. They break as soon as CMSIS is updated. Source file copying is not ideal solution either, because it creates redundancies that are hard to maintain when a new FreeRTOS version is available, but at least overcome symlinks issues. The “silver bullet” for the maintenance issue is the use of git submodules, but this would require some additional effort, i.e. I would have to improve the build scripts.

  12. Siha says:

    I have a project where I have to make a debugger software under FreeRTOS and I want as FreeRTOS using dgbserver as cmd.exe terminal windows. Thank you

  13. davngr says:


    Thanks a lot for the tutorial. So when I execute the above I get this error.

    Open On-Chip Debugger 0.7.0 (2013-10-22-17:42)
    Licensed under GNU GPL v2
    For bug reports, read
    Info : This adapter doesn’t support configurable speed
    Info : STLINK v2 JTAG v27 API v2 SWIM v6 VID 0x0483 PID 0x3748
    Info : Target voltage: 3.259082
    Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints
    target state: halted
    target halted due to debug-request, current mode: Thread
    xPSR: 0x01000000 pc: 0x0800019c msp: 0x20000450
    ** Programming Started **
    auto erase enabled
    Info : device id = 0x10076413
    Info : flash size = 512kbytes
    Segmentation fault (core dumped)
    make: *** [deploy] Error 139

    Is there something I am missing? AS I am completley new to this, I am not able to identify it. I tried the hello program you gave and that also did not work. Any idea what I could have missed?

    • istarc says:

      Hi! First, I apologize for the late reply. Did you try with sudo? There is also something fishy with the openocd execution (see segmentation fault). Could you perhaps try with a different version? Br, Iztok

  14. ralienpp says:

    Why are you removing the packages from the original repo and replacing them with custom versions? Are there any known issues with them?

    I would like to understand the rationale instead of just parroting the instructions.

    • istarc says:

      Hi! Do you refer to the interrupt handlers (=packages)? FreeRTOS uses some, too. Better approach would be to merge both files. In this simple example the merge didn’t make sense, so I deleted the conflicting one. I hope this helps. I applogize for the late reply. Br, Iztok

  15. I am not an expert, but: any multitasking ends as memory bottleneck throughput division, data&instruction overheads, and lowering of information density. It is a lot easier to implement a single core-single program efficiently. Any RTOS in hardware-resources narrow environment is not a good idea. Minimal platform is something about stm32F7/H7, but in practise microprocessors are absolutely minimal requirement ( microcontrollers are still too weak for Operating Systems in practise ). To sum up: MCU’s should be written ( erased&programmed ) with specialized single thread C programs ( consider implementing a finite state machine ).

    • istarc says:

      Hi Piotr, such a cooperative multitasking/node.js-event-loop-like design (I hope I got your conclusion right) has some benefits — no concurrency issues. But also considerable drawbacks. It would be most likely oblivious to hard deadlines, and would most likely violate real-time constraints, i.e. from the event/trigger to the system response. Can you imagine hitting an abort button, but the system does not respond in time due to some less important job (like some telemetry service)? Br, Iztok

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Google photo

You are commenting using your Google account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s