<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: 11cookies11</title>
    <description>The latest articles on Forem by 11cookies11 (@_320e4b0df17e757ca44eb).</description>
    <link>https://forem.com/_320e4b0df17e757ca44eb</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3653862%2F7750748c-71fc-45aa-a6f0-40c64bba9d20.jpg</url>
      <title>Forem: 11cookies11</title>
      <link>https://forem.com/_320e4b0df17e757ca44eb</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/_320e4b0df17e757ca44eb"/>
    <language>en</language>
    <item>
      <title>VSCode + Renode: Building a Modern Embedded Simulation Workflow</title>
      <dc:creator>11cookies11</dc:creator>
      <pubDate>Wed, 10 Dec 2025 05:47:52 +0000</pubDate>
      <link>https://forem.com/_320e4b0df17e757ca44eb/vscode-renode-building-a-modern-embedded-simulation-workflow-22gm</link>
      <guid>https://forem.com/_320e4b0df17e757ca44eb/vscode-renode-building-a-modern-embedded-simulation-workflow-22gm</guid>
      <description>&lt;p&gt;In traditional embedded development, we usually rely on physical development boards, hardware debuggers (ST-Link/J-Link), various drivers, and heavyweight IDEs such as IAR or Keil. This setup not only makes the environment cumbersome to configure, but also limits testing capabilities due to hardware availability, physical conditions, and debugging risks.&lt;/p&gt;

&lt;p&gt;With the maturity of Renode (from Antmicro), we can finally:&lt;/p&gt;

&lt;p&gt;Use VSCode + GCC for a lightweight, modern development experience&lt;/p&gt;

&lt;p&gt;Use Renode to simulate CPUs and peripherals&lt;/p&gt;

&lt;p&gt;Use GDB Server to debug firmware remotely&lt;/p&gt;

&lt;p&gt;Even run Renode on a server (Raspberry Pi / Orange Pi) and access it from anywhere&lt;/p&gt;

&lt;p&gt;Over the past few days, I built a complete workflow from VSCode → Renode → GDB, solved a series of pitfalls, and documented everything — configurations, scripts, common errors, and fixes.&lt;/p&gt;

&lt;p&gt;📌 1. Why Renode + VSCode?&lt;/p&gt;

&lt;p&gt;Modern embedded development is shifting away from:&lt;/p&gt;

&lt;p&gt;❌ IAR + physical board + hardware programmer + serial cables&lt;br&gt;
❌ Breakpoints and stepping limited to physical devices&lt;br&gt;
❌ Reinstalling toolchains when switching MCU families&lt;/p&gt;

&lt;p&gt;Towards:&lt;/p&gt;

&lt;p&gt;✔ VSCode + GCC — lightweight, modern, cross-platform&lt;br&gt;
✔ Renode — full simulation of STM32 / ESP32 devices, including UART, SPI, I2C, GPIO, DMA&lt;br&gt;
✔ GDB Remote Debugging — platform-agnostic, can debug over network&lt;br&gt;
✔ Automation-ready — suitable for CI/CD and reproducible testing&lt;/p&gt;

&lt;p&gt;This workflow is very common in international companies because:&lt;/p&gt;

&lt;p&gt;It dramatically improves development efficiency&lt;/p&gt;

&lt;p&gt;Enables automated testing&lt;/p&gt;

&lt;p&gt;Allows CI pipelines to run MCU simulations&lt;/p&gt;

&lt;p&gt;Reduces dependency on hardware&lt;/p&gt;

&lt;p&gt;However, it is still uncommon in domestic environments, so I created this article to serve as a practical guide.&lt;/p&gt;

&lt;p&gt;Steps&lt;/p&gt;

&lt;p&gt;Install Renode&lt;/p&gt;

&lt;p&gt;Configure Renode (write .resc script)&lt;/p&gt;

&lt;p&gt;Configure VSCode (.vscode/tasks.json / .vscode/launch.json)&lt;/p&gt;

&lt;p&gt;Verify end-to-end debugging&lt;/p&gt;

&lt;p&gt;Goals&lt;/p&gt;

&lt;p&gt;Write code that interacts with Renode-simulated peripherals&lt;/p&gt;

&lt;p&gt;Use VSCode + Renode for full-featured debugging workflows&lt;/p&gt;

&lt;p&gt;📌 2. Installing Renode&lt;/p&gt;

&lt;p&gt;Renode provides multiple binary distributions — choose any that works for your platform:&lt;/p&gt;

&lt;p&gt;Repository:&lt;br&gt;
&lt;a href="https://github.com/renode/renode" rel="noopener noreferrer"&gt;https://github.com/renode/renode&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;My choice:&lt;/p&gt;

&lt;p&gt;renode-latest.linux-portable-dotnet.tar.gz&lt;/p&gt;

&lt;p&gt;Reasons:&lt;/p&gt;

&lt;p&gt;Bundles its own .NET runtime&lt;/p&gt;

&lt;p&gt;Does not require system-installed dotnet/mono&lt;/p&gt;

&lt;p&gt;Runs on OrangePi / Raspberry Pi directly&lt;/p&gt;

&lt;p&gt;Extract and launch:&lt;/p&gt;

&lt;p&gt;./renode&lt;/p&gt;

&lt;p&gt;📌 3. Renode Configuration&lt;/p&gt;

&lt;p&gt;Create a minimal Renode .resc script (example for STM32F103).&lt;br&gt;
This file describes the MCU configuration Renode simulates — peripherals, firmware, and debug setup.&lt;/p&gt;

&lt;p&gt;A working version:&lt;/p&gt;

&lt;p&gt;using sysbus&lt;/p&gt;

&lt;p&gt;mach create "stm32f103"&lt;br&gt;
machine LoadPlatformDescription @platforms/cpus/stm32f103.repl&lt;/p&gt;

&lt;h1&gt;
  
  
  Load ELF from OrangePi
&lt;/h1&gt;

&lt;p&gt;machine LoadELF @/home/orangepi/object/renode_portable/firmware.elf&lt;/p&gt;

&lt;h1&gt;
  
  
  Enable UART2 analyzer
&lt;/h1&gt;

&lt;p&gt;showAnalyzer sysbus.usart2&lt;/p&gt;

&lt;h1&gt;
  
  
  Start GDB server on port 3333 for VSCode debugging
&lt;/h1&gt;

&lt;p&gt;machine StartGdbServer 3333 true&lt;/p&gt;

&lt;p&gt;start&lt;/p&gt;

&lt;p&gt;Save it as:&lt;/p&gt;

&lt;p&gt;run_stm32.resc&lt;/p&gt;

&lt;p&gt;📌 4. VSCode Debug Configuration&lt;/p&gt;

&lt;p&gt;The key part is setting up launch.json:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
    "version": "0.2.0",&lt;br&gt;
    "configurations": [&lt;br&gt;
        {&lt;br&gt;
            "name": "Debug STM32F103 on Renode Remote",&lt;br&gt;
            "type": "cppdbg",&lt;br&gt;
            "request": "launch",&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;        "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"
    }
]
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;}&lt;/p&gt;

&lt;p&gt;Core parameters:&lt;/p&gt;

&lt;p&gt;miDebuggerPath → Local GDB executable&lt;br&gt;
miDebuggerServerAddress → Remote Renode GDB endpoint&lt;/p&gt;

&lt;p&gt;And:&lt;/p&gt;

&lt;p&gt;"preLaunchTask": "Run Renode Remote"&lt;/p&gt;

&lt;p&gt;VSCode automatically starts Renode on the remote board before debugging.&lt;/p&gt;

&lt;p&gt;The post-connect sequence:&lt;/p&gt;

&lt;p&gt;Pause simulation&lt;/p&gt;

&lt;p&gt;Reload the ELF from the remote paths&lt;/p&gt;

&lt;p&gt;Reset CPU and sync execution state&lt;/p&gt;

&lt;p&gt;This mirrors what you'd normally do manually.&lt;/p&gt;

&lt;p&gt;tasks.json&lt;/p&gt;

&lt;p&gt;Required build + upload + execution pipeline:&lt;/p&gt;

&lt;p&gt;{&lt;br&gt;
    "version": "2.0.0",&lt;br&gt;
    "tasks": [&lt;br&gt;
        {&lt;br&gt;
            "label": "CMake Configure",&lt;br&gt;
            "type": "shell",&lt;br&gt;
            "command": "cmake",&lt;br&gt;
            "args": [&lt;br&gt;
                "-S", "${workspaceFolder}",&lt;br&gt;
                "-B", "${workspaceFolder}/build",&lt;br&gt;
                "-DCMAKE_BUILD_TYPE=Debug"&lt;br&gt;
            ]&lt;br&gt;
        },&lt;br&gt;
        {&lt;br&gt;
            "label": "CMake Build",&lt;br&gt;
            "type": "shell",&lt;br&gt;
            "command": "cmake",&lt;br&gt;
            "args": [&lt;br&gt;
                "--build", "${workspaceFolder}/build",&lt;br&gt;
                "--config", "Debug"&lt;br&gt;
            ],&lt;br&gt;
            "dependsOn": ["CMake Configure"]&lt;br&gt;
        },&lt;br&gt;
        ...&lt;br&gt;
    ]&lt;br&gt;
}&lt;/p&gt;

&lt;p&gt;This pipeline uploads ELF and .resc to the remote machine, restarts Renode, and attaches GDB automatically.&lt;/p&gt;

&lt;p&gt;Testing&lt;/p&gt;

&lt;p&gt;Once configured, press F5 in VSCode:&lt;/p&gt;

&lt;p&gt;Renode boots remotely&lt;/p&gt;

&lt;p&gt;Firmware loads automatically&lt;/p&gt;

&lt;p&gt;UART output and breakpoints work as expected&lt;/p&gt;

</description>
      <category>tooling</category>
      <category>vscode</category>
      <category>productivity</category>
      <category>tutorial</category>
    </item>
    <item>
      <title>I Built a Runtime Framework That Executes Serial/TCP Protocols from YAML — No More Upper-PC Coding</title>
      <dc:creator>11cookies11</dc:creator>
      <pubDate>Tue, 09 Dec 2025 14:22:51 +0000</pubDate>
      <link>https://forem.com/_320e4b0df17e757ca44eb/i-built-a-runtime-framework-that-executes-serialtcp-protocols-from-yaml-no-more-upper-pc-coding-20ed</link>
      <guid>https://forem.com/_320e4b0df17e757ca44eb/i-built-a-runtime-framework-that-executes-serialtcp-protocols-from-yaml-no-more-upper-pc-coding-20ed</guid>
      <description>&lt;p&gt;In the world of embedded systems, automated testing, and industrial communication, there’s a pain we all share:&lt;/p&gt;

&lt;p&gt;The same communication logic gets re-implemented again and again.&lt;/p&gt;

&lt;p&gt;MCU bootloader upgrades? Write a PC tool.&lt;/p&gt;

&lt;p&gt;Modbus testing? Another tool.&lt;/p&gt;

&lt;p&gt;TCP console? One more.&lt;/p&gt;

&lt;p&gt;Automated testers? Rewrite the whole thing.&lt;/p&gt;

&lt;p&gt;The protocol never changes — only the execution context does. Yet we keep wasting time rewriting upper-layer tools.&lt;/p&gt;

&lt;p&gt;I used to think this was normal.&lt;/p&gt;

&lt;p&gt;Until I built this project:&lt;/p&gt;

&lt;p&gt;ToolOfCOM&lt;/p&gt;

&lt;p&gt;A runtime that reads YAML and executes communication protocol logic.&lt;br&gt;
Write YAML, not code. That’s it.&lt;/p&gt;

&lt;p&gt;🧠 Why Does ToolOfCOM Exist?&lt;/p&gt;

&lt;p&gt;When debugging a device, we’re not really “using a serial port.” What we’re actually doing is:&lt;/p&gt;

&lt;p&gt;Waiting for events&lt;/p&gt;

&lt;p&gt;Parsing responses&lt;/p&gt;

&lt;p&gt;Handling timeouts&lt;/p&gt;

&lt;p&gt;Executing the next step&lt;/p&gt;

&lt;p&gt;Managing multi-step protocol flows&lt;/p&gt;

&lt;p&gt;In other words, every PC-side tool is a communication state machine.&lt;/p&gt;

&lt;p&gt;Traditionally, we hard-code this logic in Python / C# / LabVIEW, which leads to the real problem:&lt;/p&gt;

&lt;p&gt;One protocol → One PC tool&lt;/p&gt;

&lt;p&gt;That’s where the duplication begins.&lt;/p&gt;

&lt;p&gt;ToolOfCOM does one simple but transformative thing:&lt;/p&gt;

&lt;p&gt;It turns communication logic into a YAML-based DSL&lt;/p&gt;

&lt;p&gt;Protocols become Drivers&lt;/p&gt;

&lt;p&gt;Channels become Communication endpoints&lt;/p&gt;

&lt;p&gt;Execution becomes a state machine&lt;/p&gt;

&lt;p&gt;Communication logic is no longer code.&lt;br&gt;
It’s textual, reusable, versionable data.&lt;/p&gt;

&lt;p&gt;🚀 ToolOfCOM in One Sentence&lt;/p&gt;

&lt;p&gt;It’s a runtime engine for communication protocols that executes YAML as a state machine.&lt;/p&gt;

&lt;p&gt;Compare the mindset shift:&lt;/p&gt;

&lt;p&gt;Tool Type   Mental Model&lt;br&gt;
Traditional Tool    “Click buttons + write logic”&lt;br&gt;
ToolOfCOM   “Write YAML = define execution”&lt;/p&gt;

&lt;p&gt;It doesn’t replace existing tools.&lt;/p&gt;

&lt;p&gt;It elevates them.&lt;/p&gt;

&lt;p&gt;📐 Architecture — Minimal, Brutal, Effective&lt;br&gt;
YAML DSL&lt;br&gt;
  ↓ parser&lt;br&gt;
ScriptAST&lt;br&gt;
  ↓ executor&lt;br&gt;
Runtime Engine&lt;br&gt;
  ├─ ActionRegistry&lt;br&gt;
  ├─ Protocol Drivers (XMODEM / Modbus RTU/ASCII/TCP / YMODEM)&lt;br&gt;
  └─ Channels (UART / TCP / Logging)&lt;/p&gt;

&lt;p&gt;Decomposed into human terms:&lt;/p&gt;

&lt;p&gt;YAML = Communication description language&lt;/p&gt;

&lt;p&gt;Parser = Converts YAML → AST&lt;/p&gt;

&lt;p&gt;Runtime Engine = State-machine executor&lt;/p&gt;

&lt;p&gt;Actions = Actual tasks&lt;/p&gt;

&lt;p&gt;Drivers = Protocol stacks&lt;/p&gt;

&lt;p&gt;Channels = UART/TCP abstractions&lt;/p&gt;

&lt;p&gt;Protocol, channel, and logic are fully decoupled.&lt;/p&gt;

&lt;p&gt;🧾 This YAML Is Not Configuration — It’s Code&lt;/p&gt;

&lt;p&gt;A real executable script:&lt;/p&gt;

&lt;p&gt;version: 1&lt;br&gt;
vars: { block: 1, file_path: ./firmware.bin }&lt;/p&gt;

&lt;p&gt;channels:&lt;br&gt;
  boot: { type: uart, device: COM5, baudrate: 115200 }&lt;/p&gt;

&lt;p&gt;state_machine:&lt;br&gt;
  initial: wait_C&lt;br&gt;
  states:&lt;br&gt;
    wait_C:&lt;br&gt;
      on_event: { "C": send_block }&lt;br&gt;
      timeout: 5000&lt;br&gt;
      on_timeout: fail&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;send_block:
  do:
    - action: send_xmodem_block
      args: { block: "$block" }
  on_event: { ACK: next_block, NAK: send_block }
  timeout: 2000
  on_timeout: fail

next_block:
  do: [ - set: { block: "$block + 1" } ]
  when: "$block &amp;lt;= file.block_count"
  goto: send_block
  else_goto: send_eot

send_eot:
  do: [ - action: send_eot ]
  on_event: { ACK: done }

done: { do: [ - log: "Completed" ] }
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;

&lt;p&gt;This is not a config file.&lt;/p&gt;

&lt;p&gt;This is executable communication logic.&lt;/p&gt;

&lt;p&gt;🔁 How Does It Run?&lt;/p&gt;

&lt;p&gt;The full pipeline looks like this:&lt;/p&gt;

&lt;p&gt;toolofcom run upgrade.yaml&lt;br&gt;
→ Parse YAML → Build state machine → Initialize UART/TCP channels&lt;br&gt;
→ Register actions/protocol drivers&lt;br&gt;
→ Execute instructions → Listen for events/timeout&lt;br&gt;
→ State transitions → TX/RX → Repeat&lt;br&gt;
→ done&lt;/p&gt;

&lt;p&gt;Execution logs show every transition:&lt;/p&gt;

&lt;p&gt;[STATE] wait_C&lt;br&gt;
waiting for handshake...&lt;br&gt;
[STATE] send_block&lt;br&gt;
[STATE] next_block&lt;br&gt;
...&lt;br&gt;
Completed&lt;/p&gt;

&lt;p&gt;Enable the LoggingChannel and you get full TX/RX traces — perfect for automated testing and protocol verification.&lt;/p&gt;

&lt;p&gt;⚡ Why This Matters&lt;/p&gt;

&lt;p&gt;It changes how communication logic is produced:&lt;/p&gt;

&lt;p&gt;Perspective Before  ToolOfCOM&lt;br&gt;
Protocol changes    Modify code Modify YAML&lt;br&gt;
Test engineers  Learn coding    Learn states&lt;br&gt;
Collaboration   Ship tools  Ship scripts&lt;br&gt;
Protocol as asset   ❌ No  ✔ Yes&lt;/p&gt;

&lt;p&gt;And the real breakthrough:&lt;/p&gt;

&lt;p&gt;The same YAML runs across different channels (Serial/TCP/etc.)&lt;/p&gt;

&lt;p&gt;For the first time, protocol logic becomes transport-agnostic.&lt;/p&gt;

&lt;p&gt;🔥 Real-World Applications&lt;/p&gt;

&lt;p&gt;ToolOfCOM already supports:&lt;/p&gt;

&lt;p&gt;Feature Status&lt;br&gt;
XMODEM upgrade pipeline ✔ MCU bootloader testing powerhouse&lt;br&gt;
Modbus RTU/ASCII/TCP    ✔ Field-ready for industrial use&lt;br&gt;
Mixed UART/TCP channels ✔ Hot-swappable execution paths&lt;br&gt;
State-driven automation ✔ No code required&lt;br&gt;
Extensible protocol stack   ✔ Inherit BaseProtocol, add behavior&lt;/p&gt;

&lt;p&gt;You can now share and reuse protocols like source code.&lt;/p&gt;

&lt;p&gt;For the first time, protocols become assets.&lt;/p&gt;

&lt;p&gt;🧭 The Future (This Is the Real Paradigm Shift)&lt;/p&gt;

&lt;p&gt;ToolOfCOM opens a door:&lt;/p&gt;

&lt;p&gt;Protocols are no longer part of programs.&lt;br&gt;
Protocols &lt;em&gt;are&lt;/em&gt; the programs.&lt;/p&gt;

&lt;p&gt;From now on:&lt;/p&gt;

&lt;p&gt;Firmware upgrades are YAML&lt;/p&gt;

&lt;p&gt;Device debugging is YAML&lt;/p&gt;

&lt;p&gt;Automated testing is YAML&lt;/p&gt;

&lt;p&gt;Engineering hand-off is YAML&lt;/p&gt;

&lt;p&gt;No one will ever ask again:&lt;/p&gt;

&lt;p&gt;“Do you have a PC tool for this protocol?”&lt;/p&gt;

&lt;p&gt;The answer becomes:&lt;/p&gt;

&lt;p&gt;Give me the YAML. I’ll run it.&lt;/p&gt;

&lt;p&gt;🏁 Final Words&lt;/p&gt;

&lt;p&gt;I didn’t build this to make another serial tool.&lt;/p&gt;

&lt;p&gt;I built it to offer engineers a new mental model:&lt;/p&gt;

&lt;p&gt;Communication is not commands. It is a process.&lt;br&gt;
Processes shouldn’t be hard-coded; they should be described, shared, and executed.&lt;/p&gt;

&lt;p&gt;ToolOfCOM makes that real.&lt;/p&gt;

&lt;p&gt;📎 Open Source Repository&lt;/p&gt;

&lt;p&gt;👉 &lt;a href="https://github.com/11cookies11/ToolOfCom.git" rel="noopener noreferrer"&gt;https://github.com/11cookies11/ToolOfCom.git&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;End 🚀&lt;/p&gt;

</description>
      <category>automation</category>
      <category>showdev</category>
      <category>tooling</category>
    </item>
  </channel>
</rss>
