Visual Studio Code for C/C++ with ARM Cortex-M: Part 7 – FreeRTOS

This is a new article in my series about using Microsoft Visual Studio Code: After installation, project setup, building, debugging, setting up a kit and IntelliSense. This one is about setting up and using FreeRTOS:

Microsoft Visual Studio Code with Debugging FreeRTOS application on ARM Cortex-M

Outline

FreeRTOS is probably the most used and common RTOS for the embedded microcontroller world. It is is very easy to learn, efficient and because it is widely used, there is tools support for it.

In this article I show how you can use FreeRTOS and debug it with Visual Studio Code, including having thread awareness. I assume you have read my previous tutorial articles (see links at the end of this article).

You can find the shared projects on GitHub: https://github.com/ErichStyger/mcuoneclipse/tree/master/Examples/VisualStudioCode. I’m using the FRDM-K22F_Blinky in this article.

Setup

First, have the McuLib with FreeRTOS in your project which includes FreeRTOS:

McuLib with FreeRTOS

In your CMakeLists.txt add the FreeRTOS source files:

RTOS Source Files
        McuLib/src/McuRTOS.c

        McuLib/FreeRTOS/FreeRTOShooks.c
        McuLib/FreeRTOS/Source/croutine.c
        McuLib/FreeRTOS/Source/event_groups.c
        McuLib/FreeRTOS/Source/list.c
        McuLib/FreeRTOS/Source/queue.c
        McuLib/FreeRTOS/Source/stream_buffer.c
        McuLib/FreeRTOS/Source/tasks.c
        McuLib/FreeRTOS/Source/timers.c
        McuLib/FreeRTOS/Source/portable/MemMang/heap_1.c
        McuLib/FreeRTOS/Source/portable/MemMang/heap_2.c
        McuLib/FreeRTOS/Source/portable/MemMang/heap_3.c
        McuLib/FreeRTOS/Source/portable/MemMang/heap_4.c
        McuLib/FreeRTOS/Source/portable/MemMang/heap_5.c
        McuLib/FreeRTOS/Source/portable/MemMang/heap_useNewlib.c
        McuLib/FreeRTOS/Source/portable/GCC/ARM_CM4F/port.c
        McuLib/FreeRTOS/Source/portable/GCC/ARM_CM4F/portasm.s

List the RTOS include directories:

        McuLib/FreeRTOS/Source/include
        McuLib/FreeRTOS/Source/portable/GCC/ARM_CM4F

Update the configuration to include FreeRTOS:

FreeRTOS Configuration
/* ------------------- RTOS ---------------------------*/
#define McuLib_CONFIG_SDK_USE_FREERTOS              (1)
#define configTOTAL_HEAP_SIZE                       (24*1024)
#define configUSE_HEAP_SECTION_NAME                 (1)
#define configHEAP_SECTION_NAME_STRING              ".bss.$SRAM_LOWER.FreeRTOS"
#define configQUEUE_REGISTRY_SIZE                   (10)

With this, build the application and add tasks as needed.

Debugging with FreeRTOS Thread Awareness

I’m using SEGGER J-Link for debugging. It has an option to turn on FreeRTOS thread awareness. Add the following to the launch.json file:

"rtos": "FreeRTOS"
FreeRTOS Awareness for J-Link Debug Connection

With this, I can debug with all the FreeRTOS threads listed:

Summary

There is basic support for FreeRTOS in Visual Studio code including thread awareness. For sure it is not up-to-par with FreeRTOS debugging support you get in free Eclipse based IDEs like the NXP MCUXpresso IDE, but it is suffient to debug FreeRTOS applications on any ARM Cortex.

Happy FreeRTOSing 🙂

Links

13 thoughts on “Visual Studio Code for C/C++ with ARM Cortex-M: Part 7 – FreeRTOS

    • Thanks! It is for sure not up to the level what you can get in FreeRTOS, but it is at least something with the ability to see the threads. It would make the debugging experience much better with having access to the RTOS data structures.

      Like

  1. Yes. You are right. I tried out Debugging on VSCode. It lacks some features like directly jumping on to stackoverflowed function, Malloc Failed Function, Listing out the stack traced functions(backtrace) before it overflowed. I really like the UI of VSCode.

    Liked by 1 person

    • Yes, the editor is great, but the IDE lacks important debugging features. I mean it is usable, but not up to the level of other IDEs like Eclipse. Having good debugging features is hard even for Microsoft, because it is very diverse and you have to deal with lots of hardware details. It might take years for Microsoft to catch up if they do not massively invest here. But if they do, this would be the new standard for me. My take is that currently a good combination would be to use VSC for editing and building, then use Eclipse for debugging as external debugger.

      Liked by 1 person

      • “My take is that currently a good combination would be to use VSC for editing and building, then use Eclipse for debugging as external debugger.”

        This approach just doesn’t feel right to me from an efficiency standpoint and is really asking for compatibility issues down the line unless you are *really* careful to ensure that your build tools, make files and libraries are completely in sync between the two IDEs.

        I understand that people prefer the VSC editor and build process to Eclipse but sometimes you have to accept the tools that have the best features and support and not try to implement in a complex process because you feel some features are implemented better in other tools.

        Sorry, but while I think what you’ve done with VSC for doing ARM builds is really interesting and innovative, I think you’re at the point of jumping the shark here (hopefully you get the idiom, if not: https://www.youtube.com/watch?v=lPGz8VLLUWA).

        myke

        Like

        • Hi myke,
          yes, it is probably strange. But that would combine the best of the two worlds. I agree that overall sticking to Eclipse which covers the whole development process is probably the easiest and best approach, at least with the current debugging capabilities of VSC. However if someone really likes and loves the VSC editing and environment, using an external debugger is the way to go for me. This could be Eclipse with gdb, or if someone wants to stick with J-Link then just use Ozone with the IDE. There has been times years ago where the debugger really was an external application, and only over time the debugger got integrated into the IDE. I agree that integration is the preferred way, but the other way I appreciate if I can pick&choose the best tool for each job: either a set of different tools or an ‘all-in-one’. IMHO Eclipse is still superior as an ‘all-in-one’ tool to VSC. VSC is great in many aspects of building and editing, but lacks debugging support. My thought was about a possible compromise. Such a thing is common in the automotive industry too where development teams are using external Lauterbach debuggers because that tool provides the needed debugging features. ‘jumping the shark’ maybe, but I feel it is not about the one or the other, but picking what is best for the development process used. At least there are choices.

          Like

        • When it comes right down to it, my issue with your proposed approach is that you have multiple potential build actions that can take place in your process through the use of multiple IDEs. If you discarded Eclipse all together and went with an external debugger only (like your automotive example with the Lauterbach debuggers), I wouldn’t have reacted so strongly.

          I really appreciated this article and made me think about the way I’ve been doing some things and maybe I could have looked at things differently and considered VSC as an option.

          Regards.

          Liked by 1 person

        • Hi myke,
          I highly appreciate all your thoughts, and maybe I was not clear about my thinking.

          >>my issue with your proposed approach is that you have multiple potential build actions that can take place in your process through the use of multiple IDEs.
          I’m not sure why you would think that there are multiple potential build actions? The build would be within Visual Studio Code (well, cmake with ninja for example), and in Eclipse I purely use the GUI for debugging. No build inside Eclipse at all. Just having a launch configuration with the debugger settings (device, etc) plus pointing to the .elf file generated by the VSC. Purely using Eclipse as a standalone debugger.
          I hope this makes it clear?

          Thanks!
          Erich

          Like

        • “Just having a launch configuration with the debugger settings (device, etc) plus pointing to the .elf file generated by the VSC. Purely using Eclipse as a standalone debugger.”

          I had a pretty good idea of what your thinking was, I just don’t like the workflow in practical terms as a developer.

          Let’s go through the process starting with creating my application on VSC and it builds without any problems. I have to move the source binary and debug files into an Eclipse project – ideally this is automated otherwise I’m doing a lot of dragging and dropping (which is okay if I only have to do the whole project once). Next I start debugging and discover a minor bug in my code, let’s say I should have put in “>=” instead of just “>” as the condition in a for loop.

          What happens from here? I *think* in your process I go back to VSC, make the change, rebuild and then copy the modified source file, binary and debug files back into the Eclipse project – again, ideally this is an automated process that looks for and replaces mismatches with the latest version. Then I restart the Eclipse debug process and continue.

          I can’t think of anybody who would tolerate that process for more than one or two bugs in a project – after about the third one, they’re going to say “The hell with all this, I can modify the source in Eclipse, do a build on it and get back to debugging with a very small fraction of the effort of the established process and I’ll update the VSC project later when I have some time.”

          That “I’ll update the VSC project later when I have some time” line of thinking guarantees you that there will be two different versions of the source almost immediately and the problem will get worse if you have more than one person working on the code image. This is why I put in the comment “If you discarded Eclipse all together and went with an external debugger only…”

          Liked by 1 person

        • Hi myke,
          >> I have to move the source binary and debug files into an Eclipse project…
          No, this is not needed at all: Eclipse launch configuration just points to the binary where it has been built. No copy or move operation at all needed.

          The flow is like this:
          a) build in MVSC
          b) press debug in Eclipse
          No source duplication, no copy. The only difference is that instead you press ‘debug’ in MVSC you press that button in Eclipse. Ideally you have both MSVC and Eclipse open, so it is only a matter of clicking something in the other application. I’m sure even if this would be a problem, someone could write a small extension for MVSC which would do the start of debug from Visual Studio Code directly. Just of someone things that one mouse click more is too much in the process.

          Actually I’m doing the same process for large projects I build outside of Eclipse: the whole build is done outside, and there is just a Eclipse launch configuration which points to the .elf file which then is loaded and debugged: with the debug information inside the ELF/Dwarf binary it finds all the source files/etc so it is a very seamless process.

          I hope this makes the idea clear.

          Erich

          Liked by 1 person

        • Huh. I didn’t realize the .elf by itself has sufficient information for source level debug without any other file loads.

          Thanx for taking the time to explain.

          Liked by 1 person

        • That’s the purpose of the ELF/Dwarf file format: having all the code plus debug in formation in it so you can debug the application.
          >>without any other file loads.
          Just to be clear: the ELF/Dwarf file includes the file info (basically a list of address to source (file/line) mapping). The sources files are not packed into the ELF/Dwarf file, they still remain (of course) external. But they are referenced by path/file name. It is possible to truncate or relocate the files (e.g. if they were built on a different machine). In that case you simply enable file mapping and it will find the correct source files. This is only needed if for whatever reason the location of the source files has changed. But if you point to the binary which has been built and if the sources are still where they are at build time, it will find all the source files that way.
          Just in case: I recommend that you have a look at the ‘Executables’ view in Eclipse: it shows you the references to all the files 🙂

          Liked by 1 person

  2. Pingback: Visual Studio Code for C/C++ with ARM Cortex-M: Part 6 – IntelliSense | MCU on Eclipse

What do you think?

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

WordPress.com Logo

You are commenting using your WordPress.com 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

This site uses Akismet to reduce spam. Learn how your comment data is processed.