VSCode + Renode: Building a Modern Embedded Simulation Workflow

Published: (December 10, 2025 at 12:47 AM EST)
3 min read
Source: Dev.to

Source: Dev.to

Why Renode + VSCode?

Modern embedded development is moving away from:

  • IAR + physical board + hardware programmer + serial cables
  • Breakpoints and stepping limited to physical devices
  • Reinstalling toolchains when switching MCU families

Towards:

  • VSCode + GCC – lightweight, modern, cross‑platform
  • Renode – full simulation of STM32 / ESP32 devices (UART, SPI, I2C, GPIO, DMA)
  • GDB Remote Debugging – platform‑agnostic, can debug over a network
  • Automation‑ready – suitable for CI/CD and reproducible testing

Benefits observed in many international companies

  • Dramatically improves development efficiency
  • Enables automated testing
  • Allows CI pipelines to run MCU simulations
  • Reduces dependency on physical hardware

Installing Renode

Renode provides several binary distributions. Choose the one that matches your platform.

  • Repository:
  • Example choice: renode-latest.linux-portable-dotnet.tar.gz

Why this version?

  • Bundles its own .NET runtime
  • No need for a system‑installed dotnet/mono
  • Runs directly on Orange Pi / Raspberry Pi

Installation steps

# Download the tarball, then extract
tar -xzf renode-latest.linux-portable-dotnet.tar.gz
cd renode

# Launch Renode
./renode

Renode Configuration

Create a minimal .resc script that describes the MCU and peripherals you want to simulate.
The example below targets an STM32F103.

using sysbus

mach create "stm32f103"
machine LoadPlatformDescription @platforms/cpus/stm32f103.repl

# Load the ELF firmware (adjust the path for your setup)
machine LoadELF @/home/orangepi/object/renode_portable/firmware.elf

# Enable UART2 analyzer
showAnalyzer sysbus.usart2

# Start GDB server on port 3333 (accessible from VSCode)
machine StartGdbServer 3333 true

start

Save this file as run_stm32.resc.

VSCode Debug Configuration

launch.json

{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Debug STM32F103 on Renode Remote",
            "type": "cppdbg",
            "request": "launch",
            "program": "${workspaceFolder}/build/firmware.elf",
            "cwd": "${workspaceFolder}",
            "miDebuggerPath": "arm-none-eabi-gdb",
            "miDebuggerServerAddress": "xxx.xxx.xxx.xxx:3333",
            "preLaunchTask": "Run Renode Remote",
            "stopAtEntry": true,
            "setupCommands": [
                { "text": "set pagination off" },
                { "text": "set confirm off" },
                { "text": "set print pretty on" }
            ],
            "postRemoteConnectCommands": [
                { "text": "monitor machine Pause" },
                { "text": "monitor sysbus LoadELF @/home/orangepi/object/renode_portable/firmware.elf" },
                { "text": "monitor cpu Reset" }
            ],
            "externalConsole": false,
            "targetArchitecture": "arm"
        }
    ]
}

Key parameters

  • miDebuggerPath – path to the local GDB executable.
  • miDebuggerServerAddress – remote Renode GDB endpoint.
  • preLaunchTask – starts Renode on the remote machine before debugging.
  • postRemoteConnectCommands – pauses the simulation, reloads the ELF, and resets the CPU to synchronize state.

tasks.json

{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "CMake Configure",
            "type": "shell",
            "command": "cmake",
            "args": [
                "-S", "${workspaceFolder}",
                "-B", "${workspaceFolder}/build",
                "-DCMAKE_BUILD_TYPE=Debug"
            ]
        },
        {
            "label": "CMake Build",
            "type": "shell",
            "command": "cmake",
            "args": [
                "--build", "${workspaceFolder}/build",
                "--config", "Debug"
            ],
            "dependsOn": ["CMake Configure"]
        },
        {
            "label": "Run Renode Remote",
            "type": "shell",
            "command": "ssh",
            "args": [
                "orangepi@xxx.xxx.xxx.xxx",
                "\"cd /home/orangepi/object/renode_portable && ./renode run_stm32.resc\""
            ],
            "dependsOn": ["CMake Build"]
        }
    ]
}

The task pipeline builds the firmware, copies the ELF and .resc script to the remote machine, starts Renode, and finally attaches the GDB debugger.

Testing

  1. Press F5 in VSCode.
  2. Renode boots on the remote board.
  3. The firmware loads automatically.
  4. UART output appears in the VSCode terminal, and breakpoints work as expected.

You now have a fully functional, modern embedded simulation workflow using VSCode, Renode, and GDB.

Back to Blog

Related posts

Read more »

n8n: Credential - Google Tasks account

Prerequisite - Create a Google OAuth2 API – see the guide: How to create Google OAuth2 APIhttps://dev.to/codebangkok/how-to-create-google-oauth2-api-o29 - Enab...