Home Use VS Code with the AVR toolchain
Post
Cancel

Use VS Code with the AVR toolchain

Overview

This guide will take you through the steps to configure Visual Studio Code for AVR programming in C/C++, including working Intellisense and a build task to execute your Makefile with different targets.

Prerequisites

Setup AVR toolchain

If you haven’t already done so, start by setting up the AVR tool chain on your system so you can build AVR projects.

Follow the appropriate guide for your platform:

While you’re at it you might as well head over and set up a Makefile to build your project now too as we’ll need that later when we set up the build task:

Install Visual Studio Code

Download and install Visual Studio Code

Install C/C++ extension pack

Install the C/C++ extension pack

Review Visual Studio Code C/C++ documentation

If you’re not familiar with using VS Code with C/C++ on your chosen platform (Windows, WSL, Linux) I encourage you read through the VS Code documentation first before continuing.

Basic configuration

Cross-compiling (which is what we’re doing with AVR)

Open the sample project

Start by opening the folder for your AVR project in VS Code. I’m going to use the blinker sample created in previous tutorials which consists of a folder named blinker, a single .c file named blink.c, and a Makefile. If you don’t already have a known working project to use, I suggest

Edit C/C++ configuration

Open the Command Palette (Ctrl+Shift+P)

Search for and run C/C++: Edit Configurations (JSON). This will create a new c_cpp_properties.json file in the .vscode/ directory of your project and open it for editing.

You will need to make the following changes (see platform specific settings below):

  • compilerPath: Update to avr-gcc (see platform specific settings below)

    "-mmcu=atmega328p"Will ensure MCU defines are set correctly
    "-DF_CPU=16000000UL"Will ensure F_CPU is set correctly
    "-Os"Will avoid optimization warnings re: _delay
  • intelliSenseMode: Update to {os}-gcc-{arch} (“windows-gcc-x64” or “linux-gcc-x64” most likely)
  • compilerArgs: Add any compiler arguments you use such as the mcu, F_CPU define, and optimization (-Os). These are necessary for the compiler and VS Code to work together to produce the right set of macros #defines for your MCU.

includePath: No need to specify the AVR include paths as they will be included automatically.

From the VS Code documentation: “You only need to modify the Include path if your program includes header files that aren’t in your workspace, or that are not in the standard library path. The C/C++ extension populates the include path by querying the compiler specified by Compiler path. If the extension can’t find the path for the target system libraries, you can enter the include path manually”

On WSL / Linux:

  • Change “intelliSenseMode” to “linux-gcc-x64”
  • Update the compilerPath to “/usr/bin/avr-gcc”
  • Include path: (Only if necessary)
    • e.g. /usr/lib/avr/include/
    • You can find the path by running the command:
      1
      
        dpkg -L avr-libc | grep avr/io.h
      

On Windows:

  • Change “intelliSenseMode” to “windows-gcc-x64”
  • Update the compilerPath to avr-gcc.exe
    • e.g. C:\AVR\avr8-gnu-toolchain\bin\avr-gcc.exe
  • Include path: (Only if necessary)
    • This is under the avr8-gnu-toolchain directory we created in the install
    • e.g. C:\AVR\avr8-gnu-toolchain\avr\include\

When you’re done it should like one of these examples below (depending on your platform).

On Linux:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{
    "configurations": [
        {
            "name": "Linux",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [],
            "compilerPath": "/usr/bin/avr-gcc",
            "cStandard": "gnu11",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "linux-gcc-x64",
            "compilerArgs": [
                "-mmcu=atmega328p",     // Will ensure MCU defines are set correctly
                "-DF_CPU=16000000UL",   // Will ensure F_CPU is set correctly
                "-Os"                   // Will avoid optimization warnings re: _delay
            ]
        }
    ],
    "version": 4
}

On Windows:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
{
    "configurations": [
        {
            "name": "Win32",
            "includePath": [
                "${workspaceFolder}/**"
            ],
            "defines": [
                "_DEBUG",
                "UNICODE",
                "_UNICODE"                
            ],
            "compilerPath": "C:/AVR/avr8-gnu-toolchain/bin/avr-gcc.exe",
            "cStandard": "gnu11",
            "cppStandard": "gnu++14",
            "intelliSenseMode": "windows-gcc-x64",
            "compilerArgs": [
                "-mmcu=atmega328p",     // Will ensure MCU defines are set correctly
                "-DF_CPU=16000000UL",   // Will ensure F_CPU is set correctly
                "-Os"                   // Will avoid optimization warnings re: _delay
            ]
        }
    ],
    "version": 4
}

Now that the above configration has been completed, your Intellisense should be working and you could use the built-in gcc build tasks via Run Build Task… (Ctrl+Shift+B) to run a simple build, but we’re going to use a Makefile. If you don’t have a Makefile for your project, you can create one in Building AVR projects with make.

In the next step we’ll configure VS Code to build the project using your Makefile.

Build tasks

Let’s start by creating a tasks.json in our .vscode directory to define our new build task. While you can do this manually, we’re going to have VS Code generate the basic template for us.

  1. From the Terminal menu, select Configure Tasks…. Or search for Configure Task from the Command Palette (Ctrl+Shift+P)
  2. Choose Create tasks.json file from template
  3. Choose Others

Setting up a build task using make

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "make",
            "detail": "Run make",
            "type": "shell",
            "command": "${input:makeTarget} ",
            "options": {
                "env": {
                }
            },
            "problemMatcher": [
                "$gcc"
            ],
            "group": {
                "kind": "build"
            }
        }
    ],
    "inputs": [
        { 
            "type": "pickString", 
            "id": "makeTarget", "description": "Select a build target", 
            "options": [
                "make all", "sudo make flash", "make disassemble", "make squeaky_clean", "make size", "make debug",
            ],
            "default": "make all"
        }
    ]
}

Variations

Windows but using WSL for make

make via WSL from Windows

1
wsl make all

Using Windows-based tools that aren’t

access to windows maked tools

1
2
3
4
"Setting AVR build paths"
$toolpath = "C:\AVR"
$Env:PATH += ";$toolpath\avr8-gnu-toolchain\bin"
$Env:PATH += ";$toolpath\avrdude"

Troubleshooting

VS Code can’t find my AVR headers.
  1. First check that your AVR headers are installed. On Ubuntu Linux/WSL this is a separate package: avr-libc.
  2. Next check that you’ve specified the compilerPath and compilerArgs appropriately as VS Code finds the include paths by interrogating the compiler.
VS Code STILL can’t find my AVR headers.
Add the path to the AVR include paths manually.

On Linux:

  • e.g. /usr/lib/avr/include/
  • You can find the path by running the command:
    1
    
      dpkg -L avr-libc | grep avr/io.h
    

On Windows:

  • This is under the avr8-gnu-toolchain directory we created in the install
  • e.g. C:\AVR\avr8-gnu-toolchain\avr\include\
It’s still not working
Check out the VS Code FAQ for more help.
© Copyright 2022, Tony Mitchell

Building AVR projects with make

Apply updates to multiple WSL Linux environments quickly