From b760401fd7829e6917feebc01232d7978bf5359f Mon Sep 17 00:00:00 2001 From: Jason Duffy <55949529+Jason-Duffy@users.noreply.github.com> Date: Thu, 29 Jan 2026 15:29:37 +0000 Subject: [PATCH 1/5] added pico2 (rp2350) to build tags where needed --- .../internal/provider/boards/pico2_default.go | 24 +++++++++++++++++++ services/hal/internal/provider/resources.go | 2 +- .../hal/internal/provider/rp2_resources.go | 2 +- services/hal/internal/provider/setup_none.go | 2 +- .../hal/internal/provider/setup_selected.go | 2 +- .../provider/setups/pico_bb_proto_1.go | 2 +- .../internal/provider/setups/pico_rich_dev.go | 2 +- x/fmtx/fmtx_host.go | 2 +- x/fmtx/fmtx_mcu.go | 2 +- x/strconvx/strconvx_host.go | 2 +- x/strconvx/strconvx_mcu.go | 2 +- 11 files changed, 34 insertions(+), 10 deletions(-) create mode 100644 services/hal/internal/provider/boards/pico2_default.go diff --git a/services/hal/internal/provider/boards/pico2_default.go b/services/hal/internal/provider/boards/pico2_default.go new file mode 100644 index 0000000..280520b --- /dev/null +++ b/services/hal/internal/provider/boards/pico2_default.go @@ -0,0 +1,24 @@ +//go:build pico2 + +package boards + +var SelectedBoard = Board{ + Name: "raspberrypi_pico2", + GPIOMin: 0, + GPIOMax: 28, + I2C: []string{"i2c0", "i2c1"}, + SPI: nil, // add when we expose SPI owners + UART: []string{"uart0", "uart1"}, + Defaults: struct { + I2C0_SDA, I2C0_SCL int + I2C1_SDA, I2C1_SCL int + UART0_TX, UART0_RX int + UART1_TX, UART1_RX int + }{ + // RP2040 default pins (GPIO numbers) + I2C0_SDA: 4, I2C0_SCL: 5, + I2C1_SDA: 2, I2C1_SCL: 3, + UART0_TX: 0, UART0_RX: 1, + UART1_TX: 8, UART1_RX: 9, + }, +} diff --git a/services/hal/internal/provider/resources.go b/services/hal/internal/provider/resources.go index 2cac323..854754e 100644 --- a/services/hal/internal/provider/resources.go +++ b/services/hal/internal/provider/resources.go @@ -1,4 +1,4 @@ -//go:build rp2040 +//go:build rp2040 || rp2350 package provider diff --git a/services/hal/internal/provider/rp2_resources.go b/services/hal/internal/provider/rp2_resources.go index 50e7e36..28e24e6 100644 --- a/services/hal/internal/provider/rp2_resources.go +++ b/services/hal/internal/provider/rp2_resources.go @@ -1,4 +1,4 @@ -//go:build rp2040 +//go:build rp2040 || rp2350 package provider diff --git a/services/hal/internal/provider/setup_none.go b/services/hal/internal/provider/setup_none.go index c79515e..2863103 100644 --- a/services/hal/internal/provider/setup_none.go +++ b/services/hal/internal/provider/setup_none.go @@ -1,4 +1,4 @@ -//go:build !(pico && (pico_rich_dev || pico_bb_proto_1)) +//go:build !((rp2040 || rp2350) && (pico_rich_dev || pico_bb_proto_1)) package provider diff --git a/services/hal/internal/provider/setup_selected.go b/services/hal/internal/provider/setup_selected.go index 98225c4..f865eef 100644 --- a/services/hal/internal/provider/setup_selected.go +++ b/services/hal/internal/provider/setup_selected.go @@ -1,4 +1,4 @@ -//go:build pico && (pico_rich_dev || pico_bb_proto_1) +//go:build (rp2040 || rp2350) && (pico_rich_dev || pico_bb_proto_1) package provider diff --git a/services/hal/internal/provider/setups/pico_bb_proto_1.go b/services/hal/internal/provider/setups/pico_bb_proto_1.go index 2ffba25..594ae06 100644 --- a/services/hal/internal/provider/setups/pico_bb_proto_1.go +++ b/services/hal/internal/provider/setups/pico_bb_proto_1.go @@ -1,4 +1,4 @@ -//go:build pico && pico_bb_proto_1 +//go:build (rp2040 || rp2350) && pico_bb_proto_1 package setups diff --git a/services/hal/internal/provider/setups/pico_rich_dev.go b/services/hal/internal/provider/setups/pico_rich_dev.go index 740893b..d2bd8e8 100644 --- a/services/hal/internal/provider/setups/pico_rich_dev.go +++ b/services/hal/internal/provider/setups/pico_rich_dev.go @@ -1,4 +1,4 @@ -//go:build pico && pico_rich_dev +//go:build (rp2040 || rp2350) && pico_rich_dev package setups diff --git a/x/fmtx/fmtx_host.go b/x/fmtx/fmtx_host.go index d6dcad5..848722a 100644 --- a/x/fmtx/fmtx_host.go +++ b/x/fmtx/fmtx_host.go @@ -1,4 +1,4 @@ -//go:build !rp2040 +//go:build !(rp2040 || rp2350) package fmtx diff --git a/x/fmtx/fmtx_mcu.go b/x/fmtx/fmtx_mcu.go index e47bb0a..5fa5b6a 100644 --- a/x/fmtx/fmtx_mcu.go +++ b/x/fmtx/fmtx_mcu.go @@ -1,4 +1,4 @@ -//go:build rp2040 +//go:build rp2040 || rp2350 package fmtx diff --git a/x/strconvx/strconvx_host.go b/x/strconvx/strconvx_host.go index 4a11dc2..bf918c6 100644 --- a/x/strconvx/strconvx_host.go +++ b/x/strconvx/strconvx_host.go @@ -1,4 +1,4 @@ -//go:build !rp2040 +//go:build !(rp2040 || rp2350) package strconvx diff --git a/x/strconvx/strconvx_mcu.go b/x/strconvx/strconvx_mcu.go index 2419083..f88516a 100644 --- a/x/strconvx/strconvx_mcu.go +++ b/x/strconvx/strconvx_mcu.go @@ -1,4 +1,4 @@ -//go:build rp2040 +//go:build rp2040 || rp2350 package strconvx From 303fa2020cab6ed7a5015629c6b048f974029aa8 Mon Sep 17 00:00:00 2001 From: Jason Duffy <55949529+Jason-Duffy@users.noreply.github.com> Date: Thu, 29 Jan 2026 15:30:04 +0000 Subject: [PATCH 2/5] added usb flashing instructions for pico & pico2 --- README.md | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/README.md b/README.md index f959d1d..5f0f7e0 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,13 @@ # devicecode-go +## Flashing ISOC Power Board via USB port on Pico +tinygo flash -stack-size=3KB -monitor -scheduler tasks -target=pico -tags "pico_bb_proto_1" main.go + +## Flashing ISOC Power Board via USB port on Pico2 +tinygo flash -stack-size=3KB -monitor -scheduler tasks -target=pico2 -tags "pico_bb_proto_1" main.go + +------------------- + ## Debugging instructions The following instructions set you up debugging the code on an MCU, using a Pico debug module, connected to a Mac (tested on arm64). From 653ac0be36a8a6fdfaaa03f0c1b5f94a004d7954 Mon Sep 17 00:00:00 2001 From: Jason Duffy <55949529+Jason-Duffy@users.noreply.github.com> Date: Thu, 29 Jan 2026 16:02:09 +0000 Subject: [PATCH 3/5] added .cfg file for each target, set gdp port to default --- debug/{openocd.cfg => openocd_rp2040.cfg} | 2 +- debug/openocd_rp2350.cfg | 17 +++++++++++++++++ 2 files changed, 18 insertions(+), 1 deletion(-) rename debug/{openocd.cfg => openocd_rp2040.cfg} (83%) create mode 100644 debug/openocd_rp2350.cfg diff --git a/debug/openocd.cfg b/debug/openocd_rp2040.cfg similarity index 83% rename from debug/openocd.cfg rename to debug/openocd_rp2040.cfg index 2d5b283..94aece0 100644 --- a/debug/openocd.cfg +++ b/debug/openocd_rp2040.cfg @@ -5,7 +5,7 @@ source [find interface/cmsis-dap.cfg] source [find target/rp2040.cfg] # Confugure Ports -gdb_port 3060 +# gdb_port 3060 # (Seems to work without this - using cortex-debug default ports) tcl_port disabled telnet_port 4060 diff --git a/debug/openocd_rp2350.cfg b/debug/openocd_rp2350.cfg new file mode 100644 index 0000000..3ae65ca --- /dev/null +++ b/debug/openocd_rp2350.cfg @@ -0,0 +1,17 @@ +# Source the config file for the Raspberry Pi Debug Probe +source [find interface/cmsis-dap.cfg] + +# Source the config file for the RP2350 target MCU +source [find target/rp2350.cfg] + +# Confugure Ports +# gdb_port 3060 # (Seems to work without this - using cortex-debug default ports) +tcl_port disabled +telnet_port 4060 + + +# Set Adapter Speed in KHz (Lower speed may be needed for bootloader debugging). +adapter speed 5000 + +# init terminates the config stage and enters the run stage. +init \ No newline at end of file From 72bc7a18b4014d7cfb4c4aa87cb4f9b5a454774d Mon Sep 17 00:00:00 2001 From: Jason Duffy <55949529+Jason-Duffy@users.noreply.github.com> Date: Thu, 29 Jan 2026 16:02:25 +0000 Subject: [PATCH 4/5] added multi target support to vscode automations --- .vscode/launch.json | 57 +++++++++++++++++++++++++-------------------- .vscode/tasks.json | 57 ++++++++++++++++++++------------------------- 2 files changed, 57 insertions(+), 57 deletions(-) diff --git a/.vscode/launch.json b/.vscode/launch.json index bf76ee1..d9696c0 100644 --- a/.vscode/launch.json +++ b/.vscode/launch.json @@ -1,26 +1,33 @@ { - // Use IntelliSense to learn about possible attributes. - // Hover to view descriptions of existing attributes. - // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 - "version": "0.2.0", - "configurations": [ - { - "name": "Debug Microcontroller with TinyGo", - "type": "cortex-debug", - "request": "launch", - "servertype": "external", - "cwd": "${workspaceRoot}", - "executable": "${workspaceFolder}/build/devicecode.elf", - "preLaunchTask": "TinyGo Build", - "configFiles": [ - "${workspaceFolder}/debug/openocd.cfg" - ], - "gdbTarget": "localhost:3060", - "interface": "swd", - "postLaunchCommands": [ - "monitor reset" - ], - "postDebugTask": "Stop OpenOCD" - } - ] -} \ No newline at end of file + "version": "0.2.0", + "configurations": [ + { + "name": "Debug Pico (rp2040)", + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "cwd": "${workspaceFolder}", + "executable": "${workspaceFolder}/build/devicecode.elf", + "preLaunchTask": "TinyGo Build (rp2040)", + "configFiles": [ + "debug/openocd_rp2040.cfg" + ], + "interface": "swd", + "postLaunchCommands": ["monitor reset"] + }, + { + "name": "Debug Pico 2 (rp2350)", + "type": "cortex-debug", + "request": "launch", + "servertype": "openocd", + "cwd": "${workspaceFolder}", + "executable": "${workspaceFolder}/build/devicecode.elf", + "preLaunchTask": "TinyGo Build (rp2350)", + "configFiles": [ + "debug/openocd_rp2350.cfg" + ], + "interface": "swd", + "postLaunchCommands": ["monitor reset"] + } + ] +} diff --git a/.vscode/tasks.json b/.vscode/tasks.json index f40cf47..ea251d8 100644 --- a/.vscode/tasks.json +++ b/.vscode/tasks.json @@ -2,41 +2,34 @@ "version": "2.0.0", "tasks": [ { - "label": "Run OpenOCD", + "label": "TinyGo Build (rp2040)", "type": "shell", - "command": "openocd -f ${workspaceFolder}/debug/openocd.cfg", - "isBackground": true, - "problemMatcher": { - "pattern": [ - { - "regexp": ".", - "file": 1, - "location": 2, - "message": 3 - } - ], - "background": { - "activeOnStart": true, - // Start checking output as soon as OpenOCD starts - "beginsPattern": ".", - // Adjust this line if your OpenOCD prints a different “ready” message - "endsPattern": "for telnet connections" - } - } + "command": "tinygo", + "args": [ + "build", + "-o", "${workspaceFolder}/build/devicecode.elf", + "-stack-size=3KB", + "-serial=none", + "-target=pico", + "-tags", "pico_bb_proto_1", + "-scheduler=tasks" + ], + "problemMatcher": [] }, { - "label": "TinyGo Build", + "label": "TinyGo Build (rp2350)", "type": "shell", - "command": "tinygo build -o ${workspaceFolder}/build/devicecode.elf -stack-size=3KB -serial=none -target=pico -tags pico_bb_proto_1 -scheduler=tasks", - "problemMatcher": [], - "dependsOn": ["Run OpenOCD"] - }, - { - "label": "Stop OpenOCD", - "type": "process", - "command": "pkill", - "args": ["-f", "openocd"], - "problemMatcher": [] + "command": "tinygo", + "args": [ + "build", + "-o", "${workspaceFolder}/build/devicecode.elf", + "-stack-size=3KB", + "-serial=none", + "-target=pico2", + "-tags", "pico_bb_proto_1", + "-scheduler=tasks" + ], + "problemMatcher": [] } ] -} \ No newline at end of file +} From e41eb2a1aa0035a88f8175f5c868fcef29100bd8 Mon Sep 17 00:00:00 2001 From: Jason Duffy <55949529+Jason-Duffy@users.noreply.github.com> Date: Thu, 29 Jan 2026 16:04:48 +0000 Subject: [PATCH 5/5] added image for readme, updated readme --- README.md | 3 +++ assets/image.png | Bin 0 -> 9758 bytes 2 files changed, 3 insertions(+) create mode 100644 assets/image.png diff --git a/README.md b/README.md index 5f0f7e0..a94e2d6 100644 --- a/README.md +++ b/README.md @@ -28,8 +28,11 @@ The Darwin Kernel requires the debugger to have special permissions before it is ### Build and debug from VSCode +- Select target from debug dropdown (Pico or Pico2) - Press F5 to begin debugging +![alt text](/assets/image.png) + An OpenOCD server will be started, a GDB session started. Then the project will be built with flags specified in .vscode/tasks.json. Next, the compiled .elf file will be flashed to the MCU. The MCU will then be reset and control is handed over to you for the debug session. You'll then be able to add breakpoints, pause, resume and reset the MCU remotely using VsCode debug tools. diff --git a/assets/image.png b/assets/image.png new file mode 100644 index 0000000000000000000000000000000000000000..512803e30894fef20329b7331ce6b3542f6d4038 GIT binary patch literal 9758 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