Using Visual Studio Code for ARM Development – Include Paths

This post will describe how I set up the Include Paths for C/C++ in Visual Studio Code to support ARM development.

Visual Studio Code with the C/C++ plugin has many useful features while you are writing your code: syntax highlighting, error checking while you type, and automatic code completion, where it guesses while you type. This can help you reduce errors and write faster. However, if the plugin is not correctly set up, these features will not work correctly or at all.

In order for Visual Studio Code and the C/C++ language plugin to understand your code, it needs to be able to find all of the header files referenced in your program. A header can further reference other headers, so they may be needed even if you didn’t explicitly call them yourself.

(Note that this is completely separate from the compiling and linking steps, which I will cover in a later post. The examples I am using are from a simple program that does build and run correctly.)

In main.c, VSCode is complaining that it cannot open main.h. (Grrr! It’s right there in my workspace, under the inc folder, and I can open it – it’s fine!) The message is a little obscure, but it’s basically saying that it will interpret the file based on keywords and syntax, but can’t tell if things like function or variable names are correct.

So, how do we fix this? If you cursor is on the error, you will see the lightbulb to the left. Click that, and then Update “includePath” setting. VSCode will create and open a file called “c_cpp_properties.json”, in your project under a “.vscode” folder. By default this will contain configurations for Mac, Linux, and Win32. Unless you are developing your project on multiple computers, you don’t need them. These include default includePaths suitable for desktop applications, but are not correct for ARM. I cut them down to a single one, called STM32.

There are two sections with paths. The first, “includePath”, is where VSCode will look for headers for the purpose of checking your code. Unlike GCC, this is not recursive; you need to explicitly list each folder that contains headers that are referenced, directly or indirectly. While the default included “${workspaceRoot}”, it did not cover the inc folder – we will need to add that.

The second section with just “path” is used by IntelliSense to suggest things for you. If you are using massive libraries, you may not want tons of obscure things showing up. You can limit this list to the headers you actually use. This is recursive but you can make it non-recursive if you want. The default also included “${workspaceRoot}” so Intellesense is good for my own stuff.

We will also need to set a file for the symbol database.

This is the initial c_cpp_properties.json file:

{
    "configurations": [
        {
            "name": "STM32",
            "includePath": [
                "${workspaceRoot}",
                "${workspaceRoot}/inc"
            ],
            "defines": [
            ],
            "intelliSenseMode": "clang-x64",
            "browse": {
                "path": [
                    "${workspaceRoot}"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": "${workspaceRoot}/.vscode/browse.vc.db"
            }
        }
    ],
    "version": 3
}

Next problem! The original error has changed, and it’s complaining about a dependency.

In main.h, there are now multiple errors showing.

Basically, this is more of the same. Most of these files are part of the STM32Cube library, that is outside of my project. I’ll add those folders to my paths as well.

But where is stdint.h? GCC has built-in include paths that are used even if my compiler flags don’t specify them. GCC will list the defaults by running “arm-none-eabi-gcc -xc -E -v -“, and add those paths as well. Be sure list all subfolders with headers for the includePath section.

{
    "configurations": [
        {
            "name": "STM32",
            "includePath": [
                "${workspaceRoot}",
                "${workspaceRoot}/inc",
                "C:/Develop/STM32Cube_FW_F4_V1.16.0/Drivers/STM32F4xx_HAL_Driver/Inc",
                "C:/Develop/STM32Cube_FW_F4_V1.16.0/Drivers/CMSIS/Include",
                "C:/Develop/STM32Cube_FW_F4_V1.16.0/Drivers/CMSIS/Device/ST/STM32F4xx/Include",
                "c:/Develop/arm-none-eabi/lib/gcc/arm-none-eabi/6.3.1/include",
                "c:/Develop/arm-none-eabi/lib/gcc/arm-none-eabi/6.3.1/include-fixed",
                "c:/Develop/arm-none-eabi/arm-none-eabi/include",
                "c:/Develop/arm-none-eabi/arm-none-eabi/include/machine",
                "c:/Develop/arm-none-eabi/arm-none-eabi/include/newlib-nano",
                "c:/Develop/arm-none-eabi/arm-none-eabi/include/sys"
            ],
            "defines": [
            ],
            "intelliSenseMode": "clang-x64",
            "browse": {
                "path": [
                    "${workspaceRoot}",
                    "C:/Develop/STM32Cube_FW_F4_V1.16.0/Drivers/STM32F4xx_HAL_Driver/Inc",
                    "C:/Develop/STM32Cube_FW_F4_V1.16.0/Drivers/CMSIS/Include",
                    "C:/Develop/STM32Cube_FW_F4_V1.16.0/Drivers/CMSIS/Device/ST/STM32F4xx/Include",
                    "c:/Develop/arm-none-eabi/lib/gcc/arm-none-eabi/6.3.1/include",
                    "c:/Develop/arm-none-eabi/lib/gcc/arm-none-eabi/6.3.1/include-fixed",
                    "c:/Develop/arm-none-eabi/arm-none-eabi/include"
                ],
                "limitSymbolsToIncludedHeaders": true,
                "databaseFilename": "${workspaceRoot}/.vscode/browse.vc.db"
            }
        }
    ],
    "version": 3
}

Once you add all the paths you need, all of the header inclusion errors will go away.

In their place, you will find yourself faced with a whole new set of frightening errors! It’s getting better, I promise. These are caused by missing compiler defines, and I will explain those in the next post.

Leave a Reply

1 Comment on "Using Visual Studio Code for ARM Development – Include Paths"

Notify of
avatar
Sort by:   newest | oldest | most voted
Kamen
Guest
Hello and thanks for the great article! I want to expand on your article by giving some steps that I had to do when trying to locally setup my Visual Studio Code to handle a project which I expored from the Mbed Online Compiler. The project was the sample Nucle_blink_led app and was expored as GCC (ARM Embedded). My idea was to setup the exported project to only use the ARM GCC compiler (v 6). Since the file comes with a Makefile and it has quite some dependencies, this Makefile is a good place to start. 1. Check Makefile for… Read more »
wpDiscuz