Minimal C wrapper + Go bindings for the SEGGER J-Link API.
Cross‑platform: Windows & Linux.
Uses Zig to build a tiny C wrapper, making J-Link API calls accessible from Go without CGO headaches.
A very small, low‑level wrapper around the official J-Link API:
- Thin C layer compiled with Zig
- Go bindings on top
- Dynamic loading of the SEGGER shared library
- No abstractions, no magic — just direct access to the API
Perfect if you want to call J-Link functions from Go with minimal overhead.
- SEGGER J-Link Software installed
- Shared library available at runtime:
- Windows:
JLink_x64.dllorJLinkARM.dll - Linux:
libjlinkarm.so
- Windows:
- Zig compiler (to build the C wrapper)
- Go toolchain
-
Install the official SEGGER J-Link package
(download from the SEGGER website). -
Ensure the shared library is discoverable:
- place it next to your executable
-
Install MSYS2 (Windows)
(instructions available at the MSYS2 website). -
Install the Go toolchain
(available at the Go downloads page). -
Install the Zig compiler
(download from the Zig website).
git clone https://github.com/SimonTechv/gojlink.git
cd gojlinkCC="zig cc -target aarch64-linux-gnu" \
CGO_ENABLED=1 \
GOOS=linux \
GOARCH=arm64 \
go build .CC="zig cc" \
CGO_ENABLED=1 \
GOOS=windows \
GOARCH=amd64 \
go build .package main
import (
"fmt"
"time"
"github.com/SimonTechv/gojlink/jlink"
)
var JLinkEmuSerialNumber uint32 = 123456 // Put your emulator SN here
func main() {
// Load the J-Link shared library (.dll / .so)
emu, err := jlink.APIInit()
if err != nil {
return
}
defer func() {
emu.Close()
time.Sleep(100 * time.Millisecond)
_ = emu.APIClose() // Unload the shared library
if err != nil {
fmt.Printf("Error: %s", err.Error())
}
}()
fmt.Println("Select EMU")
if err = emu.SelectByUSBSN(JLinkEmuSerialNumber); err != nil {
return
}
fmt.Println("Connect to EMU")
if err = emu.Open(); err != nil {
return
}
fmt.Println("Select IF")
if err = emu.TIFSelect(jlink.SWD); err != nil {
return
}
fmt.Println("Select target")
if err = emu.ExecCommand("Device = STM32F103C8"); err != nil {
return
}
fmt.Println("Connect to target")
if err = emu.Connect(); err != nil {
return
}
// Simple read/write test (RAM on STM32)
fmt.Println("Write to RAM: 0xFAFAFAFA")
if err = emu.WriteU32(0x20000000, 0xFAFAFAFA); err != nil {
return
}
mem, err := emu.ReadMemU32(0x20000000, 1)
if err != nil {
return
}
fmt.Printf("Read from RAM: 0x%X\n", mem[0])
}