Firmware Development On Windows using WSL, Docker, and VSCode

As an embedded systems developer I stayed away from developing on Windows because the Windows command line environment always felt "clunky" when compared to Unix based environments. Since I'm a big proponent for doing as much as possible from the command line(vs. in a GUI) that meant Windows wasn't a good fit for me.

However, the introduction of Windows Subsystem Linux (WSL) has for the most part removed any barriers I used to have when it comes to developing on Windows. The Linux subsystem is very full featured, and it allows you to run Docker which I use to create build environments for all of my projects.

Below is a quick guide on how I set up the Windows development environment I'm currently using.

Enable WSL 2 and Install a Linux Kernel

Before doing anything else, we'll first need to enable WSL v2, and install a Linux distro on it, in my case I installed Ubuntu 20.04 LTS. This guide from Microsoft walks you through the various ways to install WSL and your choice of Linux kernel:

If WSL isn't coming up properly check that you have the necessary features enabled for virtualization.

Once WSL is installed you can easily open up a WSL terminal by typing {% c-line %}wsl{% c-line-end %} in the Windows search bar at the bottom.

Install Docker Desktop For Windows

Next we'll install Docker Desktop For Windows, which utilizes the Linux Containers WSL2 backend. Docker is a great way to encapsulate an entire build environment, making it trivial to share a project between team members, build servers, etc. Check out this article for more on moving your build environment into Docker.

  1. Install Docker Desktop For Windows and make sure to select "Install required Windows components for WSL 2"
  1. Once it's done you'll see a little whale icon with containers in your task bar at the bottom

SSH Keys

Setting up SSH keys on the WSL side will make interacting with remote git servers (e.g. GitHub, BitBucket, GitLab) faster and more secure compared to using https.

  1. If {% c-line %}ssh-keygen -t rsa{% c-line-end %} is not installed go ahead and install it {% c-line %}sudo apt-get update;sudo apt-get install openssh-client{% c-line-end %}
  2. Generate your keys {% c-line %}ssh-keygen -t rsa{% c-line-end %}
    I like to store my keys in{% c-line %}~/.ssh{% c-line-end %}
  3. Then you can get your ssh keys in GitHub, BitBucket, etc with the public key you just created, e.g. {% c-line %}{% c-line-end %}


VSCode is a really nice open-source IDE for firmware development. It has a lot of plugins, with a usable Package Manager, making it a pretty powerful IDE. What's nice, is that VSCode works well with WSL so that you can interact with directories on the WSL side via VSCode, making firmware development easy.

  1. Download and install Visual Studio Code
  2. Open up WSL (type {% c-line %}wsl{% c-line-end %} in the windows search bar and hit enter)
  3. Run {% c-line %}code{% c-line-end %} to open up VSCode from the WSL side
  4. Install the Remote-WSL extension
  1. Install the C/C++ extension on the WSL Side
    This is used for debugging. Again, make sure to install this on the WSL side. If done properly it will say that the extension is enabled on WSL
  1. Clone your favorite project cd into the folder and type {% c-line %}code .{% c-line-end %}
  2. You'll be asked if you want to install VSCode Server, say yes
  3. If everything works as expected you'll see a WSL-Ubuntu green icon in the bottom left of the VSCode IDE. This means that VSCode is successfully integrated with WSL

Wrap Up

With the above installed, I now have everything I need to enjoy developing a new project on Windows!

Notes: You may be tempted to keep your project files in {% c-line %}/mnt/c{% c-line-end %} so that you can access them from both the WSL side and the Windows side. Don't! Read/Write actions on files located in {% c-line %}/mnt{% c-line-end %} are extremely slow because of how file messaging is performed between Windows and WSL. For example a build that takes me 10 seconds in {% c-line %}/home{% c-line-end %} takes me over a minute in {% c-line %}/mnt/c{% c-line-end %}.

Reach out to learn more about Lager's hardware test automation platform.

Try One Month Free