Tüm eğitimler
TEKNİK REHBER GÖMÜLÜ LİNUX DEBUG 2026

OpenOCD & JTAG
Hardware Debug

JTAG/SWD ile donanım seviyesinde debug — OpenOCD, GDB, flash programlama ve RTOS-aware thread analizi.

00 JTAG ve SWD temelleri

JTAG ve SWD, gömülü işlemcilerin donanım seviyesinde debug edilmesini, programlanmasını ve test edilmesini sağlayan standart arayüzlerdir.

JTAG — Joint Test Action Group (IEEE 1149.1)

JTAG, başlangıçta üretim testi için tasarlanmış (boundary scan), zamanla debug arayüzüne dönüşmüş bir standarttır. Her cihaz bir TAP (Test Access Port) içerir; TAP'lar bir daisy-chain üzerinde birbirine bağlanarak tek bir JTAG bağlantısıyla birden fazla cihaza erişim sağlar.

TCKTest Clock — JTAG state machine'i ve shift register'ları bu saat ile senkronize edilir.
TMSTest Mode Select — TAP Controller state machine'inin durumunu belirler.
TDITest Data In — debug probe'dan target'a veri akışı (shift register girişi).
TDOTest Data Out — target'tan debug probe'a veri akışı (shift register çıkışı).
TRSTTest Reset (opsiyonel) — TAP Controller'ı reset eder. Bazı sistemlerde yoktur; TMS sekansıyla da reset yapılabilir.
SRSTSystem Reset — hedef sistemin hard reset pini; OpenOCD reset komutlarında kullanılır.

TAP Controller state machine

TAP Controller, 16 durumlu bir state machine'dir. TMS pininin her TCK yükselen kenarında aldığı değer (0 veya 1) bir sonraki durumu belirler. Temel akışlar: Shift-DR veri register'ına erişim; Shift-IR instruction register'ına komut yazımı.

Test-Logic-Reset → Run-Test/Idle → Select-DR → Capture-DR → Shift-DR → Exit1-DR → Update-DR → ...

IR ve DR register'ları

RegisterAmaçÖrnek komutlar
IR (Instruction)TAP'a hangi DR'nin seçileceğini yazarBYPASS, IDCODE, SAMPLE/PRELOAD, EXTEST
DR (Data)Seçilen fonksiyona göre değişirBoundary scan chain, debug data register
IDCODECihaz kimliği (manufacturer, part, version)32-bit, IR'a IDCODE yazıldığında DR'den okunur
BYPASS1-bit pass-through; daisy-chain'de kullanılmayan TAP'ları atlaIR'a tümü-1 yazıldığında seçilir

SWD — Serial Wire Debug

SWD, ARM tarafından geliştirilen 2 telli, ARM özelinde bir debug arayüzüdür. JTAG'ın 4–5 pinini 2 pine (SWDIO + SWCLK) indirger; dar PCB alanlarında ve küçük paketlerde kritik avantaj sağlar. Cortex-M serisi için özellikle yaygındır.

ÖzellikJTAGSWD
Pin sayısı4–5 (TCK, TMS, TDI, TDO, TRST)2 (SWDIO, SWCLK)
Daisy-chainEvet; birden fazla TAPHayır; single target
StandartIEEE 1149.1 (açık)ARM özel (açık doküman)
HızBenzerBenzer; bazı probe'larda biraz daha hızlı
PlatformEvrensel (ARM, RISC-V, MIPS, vb.)ARM Cortex-M / Cortex-A / Cortex-R
Ne zaman kullanCortex-A, çok çekirdek, daisy-chainCortex-M, dar alan, basit setup

Debug probe türleri

ProbeProtokolFiyatÖzellik
ST-Link v2/v3SWD, JTAGDüşük (10–25 $)STM32 için yerleşik (Nucleo/Discovery); standalone da var
J-Link (Segger)SWD, JTAGOrta–Yüksek (50–600 $)Geniş MCU/SoC desteği; hızlı; ticari lisans gerekir
CMSIS-DAP / DAPLinkSWD, JTAGDüşük (5–20 $)ARM standardı; açık kaynak; USB HID; geniş destek
FTDI (FT2232H)SWD, JTAG, SPI, I2CDüşük (15–30 $)Çok yönlü; OpenOCD FTDI sürücüsüyle; ham GPIO modu
OpenOCD + Raspberry PiJTAG (GPIO bitbang)Sıfır (Pi'niz varsa)Yavaş; prototip ve kurtarma için kullanışlı
Black Magic ProbeSWD, JTAGOrta (50–80 $)GDB server probe içinde; OpenOCD gerekmez
NOT

CMSIS-DAP, ARM'ın standart debug probe arayüzüdür ve USB HID üzerinden çalışır — özel sürücü gerektirmez. Yeni bir proje için düşük maliyetli bir CMSIS-DAP probe (örn. Picoprobe — RP2040 tabanlı) ile başlamak makul bir seçimdir.

Bu bölümde

  • JTAG 4-5 pin; TAP controller state machine; IR/DR register'ları
  • SWD 2 pin; ARM özelinde; Cortex-M için ideal
  • JTAG ne zaman: daisy-chain, Cortex-A, RISC-V; SWD ne zaman: Cortex-M, dar alan
  • Probe seçimi: ST-Link (STM32), J-Link (genel), CMSIS-DAP (açık standart)

01 OpenOCD kurulumu ve yapılandırma

OpenOCD (Open On-Chip Debugger), GDB server, flash programcı ve JTAG/SWD arayüzü olarak işlev gören açık kaynaklı debug altyapısıdır.

Kurulum

bash — kurulum
# Ubuntu/Debian paket yöneticisi (genellikle eski sürüm)
sudo apt install openocd

# Sürümü kontrol et
openocd --version
# Open On-Chip Debugger 0.12.0

# Daha yeni sürüm için kaynak koddan build
sudo apt install build-essential pkg-config libusb-1.0-0-dev \
    libjaylink-dev libhidapi-dev

git clone https://github.com/openocd-org/openocd.git
cd openocd/
./bootstrap
./configure --enable-stlink \
             --enable-jlink \
             --enable-cmsis-dap \
             --enable-ftdi
make -j$(nproc)
sudo make install

udev kuralları (USB erişimi)

bash — udev kuralları
# OpenOCD udev kuralları — root olmadan USB erişimi
sudo cp /usr/share/openocd/contrib/60-openocd.rules \
    /etc/udev/rules.d/

# Kaynak build için
sudo cp openocd/contrib/60-openocd.rules \
    /etc/udev/rules.d/

# Kuralları yeniden yükle
sudo udevadm control --reload-rules
sudo udevadm trigger

# Kullanıcıyı plugdev grubuna ekle
sudo usermod -aG plugdev $USER
# (oturumu kapatıp açın)

Konfigürasyon dosyası hiyerarşisi

OpenOCD, başlatılırken üç katmanlı bir konfigürasyon dosyası hiyerarşisi kullanır. Bu dosyaların sırası önemlidir: önce interface (probe), sonra transport (JTAG/SWD), ardından target (hedef chip), son olarak isteğe bağlı board düzeyinde ayarlar yüklenir.

interface config (probe donanımı) → target config (CPU/SoC) → board config (opsiyonel: reset, flash)
DizinİçerikÖrnek
/usr/share/openocd/scripts/interface/Debug probe tanımlarıstlink.cfg, jlink.cfg, cmsis-dap.cfg
/usr/share/openocd/scripts/target/CPU / SoC tanımlarıstm32f4x.cfg, am335x.cfg, rp2040.cfg
/usr/share/openocd/scripts/board/Hazır board konfigürasyonlarıst_nucleo_f4.cfg, ti_beaglebone.cfg
./openocd.cfgProje özelinde üst seviye configProjenizin kök dizininde
bash — OpenOCD başlatma örnekleri
# ST-Link + STM32F4 target
openocd \
    -f interface/stlink.cfg \
    -f target/stm32f4x.cfg

# Hazır board konfigürasyonu kullan
openocd -f board/st_nucleo_f4.cfg

# J-Link + AM335x
openocd \
    -f interface/jlink.cfg \
    -f target/am335x.cfg

# Özel config dosyasıyla
openocd -f openocd.cfg

Bu bölümde

  • apt install openocd hızlı başlangıç; güncel sürüm için kaynak build
  • udev kuralları USB erişimi için zorunlu; kullanıcıyı plugdev grubuna ekle
  • Hiyerarşi: interface → target → board konfigürasyonu
  • openocd -f interface/stlink.cfg -f target/stm32f4x.cfg en yaygın kullanım

02 Debug probe konfigürasyonu

Her debug probe'un OpenOCD ile kullanımı farklı interface konfigürasyon dosyası ve ayarlar gerektirir.

ST-Link

interface/stlink.cfg — içerik
# ST-Link v2 ve v3 otomatik tanınır
source [find interface/stlink.cfg]

# Transport: SWD (Cortex-M için) veya JTAG
transport select hla_swd     # SWD modu (varsayılan ST-Link)
# transport select hla_jtag  # JTAG modu

# Hız ayarı (kHz)
adapter speed 4000   # 4 MHz — başlangıç için güvenli
bash — ST-Link bağlantı testi
# STM32F4 Discovery veya Nucleo bağlı STM32 için
openocd \
    -f interface/stlink.cfg \
    -f target/stm32f4x.cfg \
    -c "init; reset halt; exit"
# Info : STLINK V2J45S7 (API v2) VID:PID 0483:3748
# Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints

J-Link

openocd.cfg — J-Link konfigürasyonu
source [find interface/jlink.cfg]

# J-Link serial number (birden fazla J-Link bağlıysa)
# adapter serial 000123456789

transport select jtag
adapter speed 10000   # 10 MHz

# JTAG chain'de birden fazla TAP varsa
# jtag newtap ... komutu ile tanımla

CMSIS-DAP

openocd.cfg — CMSIS-DAP
source [find interface/cmsis-dap.cfg]

# CMSIS-DAP v2 (USB bulk — daha hızlı)
# cmsis_dap_backend hid   # HID modu (eski)
# cmsis_dap_backend usb_bulk  # USB Bulk (daha hızlı, CMSIS-DAP v2)

transport select swd
adapter speed 10000

FTDI (FT2232H)

openocd.cfg — FTDI interface
source [find interface/ftdi/olimex-arm-usb-ocd-h.cfg]

# Özel FTDI konfigürasyonu (doğrudan)
interface ftdi
ftdi vid_pid 0x0403 0x6010   # FT2232H VID:PID
ftdi channel 0              # Interface A (channel 0)

# GPIO pin eşlemeleri (FT2232H ADBUS)
ftdi layout_init 0x0008 0x000b
# TCK=0, TDI=1, TDO=2, TMS=3, TRST=4, SRST=5 (donanıma göre değişir)

transport select jtag
adapter speed 6000
NOT

Bağlantı hızını (adapter speed) gereksiz yüksek ayarlamayın. Uzun JTAG kabloları veya parazitli ortamlarda yüksek frekans hatalara yol açar. Güvenilir bağlantı kurulduktan sonra hızı kademeli artırın; STM32 SWD için 4–8 MHz genellikle güvenli başlangıç noktasıdır.

Bu bölümde

  • ST-Link: interface/stlink.cfg + transport select hla_swd
  • J-Link: interface/jlink.cfg; seri no ile belirli probe seçimi
  • CMSIS-DAP: interface/cmsis-dap.cfg; USB bulk v2 daha hızlı
  • FTDI: interface ftdi + ftdi vid_pid; GPIO pin eşlemeleri donanıma göre

03 Target konfigürasyonu

Target konfigürasyon dosyası, hedef işlemciyi ve reset mekanizmasını tanımlar; OpenOCD'nin CPU ile nasıl iletişim kuracağını belirler.

STM32F4x target konfigürasyonu

target/stm32f4x.cfg — temel yapı
# STM32F4 serisi — Cortex-M4 çekirdeği
if { [info exists CHIPNAME] } {
    set _CHIPNAME $CHIPNAME
} else {
    set _CHIPNAME stm32f4x
}

# JTAG IDCODE
if { [info exists CPUTAPID] } {
    set _CPUTAPID $CPUTAPID
} else {
    set _CPUTAPID 0x2ba01477
}

# TAP tanımla
jtag newtap $_CHIPNAME cpu \
    -irlen 4 \
    -expected-id $_CPUTAPID

# Target (CPU) tanımla
set _TARGETNAME $_CHIPNAME.cpu
target create $_TARGETNAME cortex_m \
    -chain-position $_TARGETNAME

# Work area: RAM'de 256 KB hızlı buffer (flash algoritması için)
$_TARGETNAME configure \
    -work-area-phys 0x20000000 \
    -work-area-size 0x40000 \
    -work-area-backup 0

Reset türleri

SRSTSystem Reset — donanım reset pini; tüm periferaller dahil tam reset. OpenOCD bunu probe'un GPIO piniyle sürer.
TRSTTest Reset — sadece JTAG TAP controller'ını reset eder. CPU'yu resetlemez. Bazı sistemlerde mevcut değil.
Soft resetCPU'ya yazılım komutu gönderilir (AIRCR.SYSRESETREQ — Cortex-M). Donanım pini kullanılmaz.
openocd.cfg — reset konfigürasyonu
# Reset assert yöntemi
# system_reset: SRST pini (donanım bağlantısı gerekir)
# vector_catch: soft reset (SRST bağlı değilse)
reset_config srst_only

# SRST bağlı değilse yazılım resetini kullan
reset_config none

# Hem SRST hem TRST varsa
reset_config trst_and_srst

# STM32 özelinde: SRST ile reset sonrası halt
stm32f4x.cpu configure -event reset-init {
    adapter speed 4000
    stm32f4x.cpu arp_examine
}

AM335x target konfigürasyonu

openocd.cfg — AM335x (BeagleBone)
source [find interface/jlink.cfg]
transport select jtag
adapter speed 1000   # AM335x başlangıç için düşük hız

source [find target/am335x.cfg]

# AM335x JTAG chain: ICEpick → Cortex-A8
# ICEpick DAP üzerinden target'ı aktive eder

# DDR başlatıldıktan sonra hızı artır
$_TARGETNAME configure -event gdb-attach {
    halt
    adapter speed 10000
}

Endianness ve diğer ayarlar

openocd.cfg — endian ve sysbus
# ARM Cortex-M: little-endian (varsayılan)
# ARM Cortex-A: genellikle little-endian; big-endian de olabilir

# MIPS big-endian target örneği
# target create mips.cpu mips_m4k -chain-position mips.cpu -endian big

# SWD için multidrop (STM32 dual core gibi)
# stm32h745.cpu0 configure -coreid 0
# stm32h745.cpu1 configure -coreid 1

Bu bölümde

  • Target config: TAP tanımı + target create + work area
  • SRST: donanım reset; TRST: TAP reset; soft reset: yazılım AIRCR
  • reset_config srst_only veya none SRST bağlı olup olmadığına göre
  • AM335x: ICEpick aracılığıyla Cortex-A8 JTAG erişimi

04 OpenOCD telnet arayüzü

OpenOCD çalışırken 4444 portunda bir telnet sunucusu sunar; bu arayüz üzerinden CPU kontrolü, bellek erişimi ve flash operasyonları doğrudan yapılabilir.

Telnet bağlantısı

bash — telnet bağlantısı
# OpenOCD arka planda çalışıyor olmalı
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg &

# Telnet ile bağlan
telnet localhost 4444
# Open On-Chip Debugger
# >

# Alternatif: nc (netcat)
nc localhost 4444

CPU kontrol komutları

telnet — CPU kontrolü
# CPU'yu durdur (halt)
> halt
# target halted due to debug-request, current mode: Thread
# xPSR: 0x01000000 pc: 0x080023a4 msp: 0x20020000

# CPU'yu devam ettir
> resume

# Tek adım
> step

# Reset ve halt (halt durumunda başlat)
> reset halt

# Reset ve çalıştır
> reset run

# Sadece reset (çalışmaya devam et)
> reset

Register okuma

telnet — register
# Tüm register'ları listele
> reg
# (0) r0 (/32): 0x00000000
# (1) r1 (/32): 0x00000001
# ...
# (15) pc (/32): 0x080023a4
# (16) xpsr (/32): 0x01000000

# Belirli register oku
> reg pc
# pc (/32): 0x080023a4

# Register'a değer yaz
> reg r0 0xdeadbeef

Bellek okuma ve yazma

telnet — mdw / mww (memory read/write)
# mdw: memory display word (32-bit)
# mdh: memory display halfword (16-bit)
# mdb: memory display byte (8-bit)

# 0x20000000 adresinden 16 word oku
> mdw 0x20000000 16
# 0x20000000: deadbeef 00000000 08000841 20020000
# 0x20000010: ...

# mww: memory write word
> mww 0x20000100 0x12345678
> mww 0x20000104 0xABCDEF01

# Peripheral register'ı oku (STM32 GPIOC ODR)
> mdw 0x40020814

# Peripheral register'a yaz
> mww 0x40020818 0x00000100   # PC8 set (BSRR)

Diğer yararlı komutlar

telnet — diğer komutlar
# Bağlı target'ları listele
> targets

# Target hakkında bilgi
> stm32f4x.cpu curstate
# halted

# Breakpoint koy (donanım breakpoint)
> bp 0x080023a4 2 hw    # adres, boyut, hw/sw

# Tüm breakpoint'leri listele
> bp

# Breakpoint kaldır
> rbp 0x080023a4

# Watchpoint (bellek erişim kırma noktası)
> wp 0x20000100 4 rw    # adres, boyut, erişim tipi (r/w/rw/a)
> rwp 0x20000100

# ELF/binary dosyadan belleğe yükle
> load_image firmware.elf

# Belleği binary dosyaya dump et
> dump_image /tmp/ram_dump.bin 0x20000000 0x20000

Bu bölümde

  • telnet localhost 4444 ile OpenOCD interaktif shell'e erişim
  • halt, resume, step, reset halt CPU kontrolü
  • mdw/mww bellek okuma/yazma; peripheral register erişimi için de kullanılır
  • bp hardware breakpoint; wp watchpoint

05 Flash programlama

OpenOCD, desteklenen hedef flash belleği programlamak için yerleşik flash sürücüleri ve komutlar sağlar; üretim programlamasında da kullanılabilir.

Flash bank bilgisi

telnet — flash bilgisi
# Tanımlı flash bank'larını listele
> flash banks
# #0 : stm32f4x.flash (stm32f2x) at 0x08000000, size 0x00100000,
#       buswidth 0, chipwidth 0

# Flash bank hakkında ayrıntılı bilgi
> flash info 0
# Device ID: 0x10006413
# flash size = 1024 kbytes
# Bank #0 = stm32f4x at 0x08000000, size 0x00100000, buswidth 4, chipwidth 4
#     #  0: 0x00000000 (0x4000 16kB) not protected
#     #  1: 0x00004000 (0x4000 16kB) not protected
#     ...
#     # 11: 0x000e0000 (0x20000 128kB) not protected

Flash programlama komutları

telnet — flash yazma ve doğrulama
# ELF dosyasını flash'a yaz, doğrula ve reset
> program firmware.elf verify reset

# Binary dosya — load adresini belirt
> program firmware.bin verify reset 0x08000000

# Hex dosya (Intel HEX formatı)
> program firmware.hex verify reset

# flash write_image: erase dahil yazma
> flash write_image erase firmware.elf

# Offset ile yazma
> flash write_image erase firmware.bin 0x08010000 bin

# Sadece belirli sektörleri sil
> flash erase_sector 0 0 11   # bank 0, sektör 0'dan 11'e

# Tüm flash'ı sil
> flash erase_address 0x08000000 0x100000

Bash'ten doğrudan programlama

bash — tek satır programlama
# Bağlantı kur, programla ve kapat — CI/CD için ideal
openocd \
    -f interface/stlink.cfg \
    -f target/stm32f4x.cfg \
    -c "program firmware.elf verify reset exit"

# Başarı durumunda exit code 0, hata durumunda 1
# CI/CD pipeline'a entegrasyon için idealdir

Flash koruma

telnet — flash protection
# Sektörleri write-protect et (STM32 WRP)
> flash protect 0 0 3 on     # bank 0, sektör 0-3 koru

# Korumayı kaldır
> flash protect 0 0 last off

# STM32 read-out protection (RDP) — dikkatli kullanın!
> stm32f4x options_write 0 0x55AA

# STM32 option byte'larını oku
> stm32f4x options_read 0
DİKKAT

STM32 RDP (Read-out Protection) Level 2 programlama geri alınamaz: cihaz kalıcı olarak kilitlenir, JTAG/SWD erişimi tamamen kapanır. Level 1'i test ettikten sonra ancak Level 2'ye geçin.

Bu bölümde

  • flash info 0 flash bankını ve sektörlerini listeler
  • program firmware.elf verify reset exit tek adımda programla, doğrula, reset
  • Bash'ten -c "program ... exit" ile CI/CD entegrasyonu
  • RDP Level 2: geri alınamaz cihaz kilitleme — dikkatli kullanın

06 GDB entegrasyonu

OpenOCD, 3333 portunda bir GDB remote server sunar; arm-none-eabi-gdb bu port üzerinden debug oturumu başlatır.

GDB bağlantısı

bash — GDB bağlantısı
# Terminal 1: OpenOCD'yi başlat (arka planda)
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg &

# Terminal 2: GDB'yi başlat
arm-none-eabi-gdb firmware.elf

# GDB içinde OpenOCD'ye bağlan
(gdb) target extended-remote :3333
# Remote debugging using :3333
# 0x080023a4 in main ()

# Alternatif: target remote (non-extended)
(gdb) target remote :3333

Temel GDB komutları (gömülü debug için)

gdb — debug komutları
# Firmware'i yükle (flash programlama)
(gdb) load
# Loading section .isr_vector, size 0x1a4 lma 0x8000000
# Loading section .text, size 0x123c4 lma 0x80001a4

# CPU'yu durdur ve sıfırla
(gdb) monitor reset halt

# Çalıştır
(gdb) continue    # veya: c

# Yazılım breakpoint (flash'ta — Flash breakpoint destekleniyorsa)
(gdb) break main
(gdb) break src/sensor.c:142

# Donanım breakpoint (hbreak) — flash execute için zorunlu
(gdb) hbreak 0x080023a4
(gdb) hbreak uart_irq_handler

# Watchpoint (bellek erişim)
(gdb) watch g_error_count        # write watchpoint
(gdb) rwatch sensor_data.value   # read watchpoint
(gdb) awatch i2c_buffer[0]       # access (r+w) watchpoint

# Adım adım
(gdb) step    # s — kaynak satırı adımı (fonksiyon içine girer)
(gdb) next    # n — satır adımı (fonksiyon çağrısını atlar)
(gdb) stepi   # si — tek makine komutu

# Backtrace
(gdb) backtrace    # veya: bt
(gdb) frame 2      # 2. stack frame'e geç

# Değişken/register
(gdb) print g_tick_count
(gdb) print/x $pc
(gdb) info registers

.gdbinit ile otomatik bağlantı

.gdbinit — proje kökünde
# Projeye özel GDB başlangıç scripti
define myconnect
    target extended-remote :3333
    monitor reset halt
    load
    monitor reset halt
end

# Otomatik bağlan (dikkatli: security uyarısı verebilir)
# set auto-load safe-path /path/to/project
target extended-remote :3333

OpenOCD GDB port konfigürasyonu

openocd.cfg — GDB port ayarı
# GDB server portunu değiştir (birden fazla target için)
stm32f4x.cpu configure -gdb-port 3333
# İkinci target için
# stm32h7.cpu configure -gdb-port 3334

# Telnet portu
telnet_port 4444

# TCL server (scripting)
tcl_port 6666
NOT

Cortex-M çekirdeklerinde flash üzerindeki kod için yazılım breakpoint (INT 3 komutu ekleme) kullanılamaz. Hardware breakpoint (hbreak) kullanın. Cortex-M4 6 donanım breakpoint, 4 watchpoint destekler — bu sınırı aşmamaya dikkat edin.

Bu bölümde

  • target extended-remote :3333 OpenOCD GDB server'a bağlanır
  • load firmware'i yükler; monitor reset halt OpenOCD komutunu iletir
  • Flash üzerinde hbreak (hardware breakpoint) zorunlu; sınır: genellikle 6 BP + 4 WP
  • .gdbinit ile otomatik bağlantı ve özel komutlar tanımlanabilir

07 RTOS-aware debug

OpenOCD, FreeRTOS, Zephyr ve diğer RTOS'ların task/thread yapılarını anlayarak GDB'ye per-thread backtrace ve durum bilgisi sunar.

RTOS desteği konfigürasyonu

openocd.cfg — FreeRTOS RTOS desteği
source [find interface/stlink.cfg]
source [find target/stm32f4x.cfg]

# RTOS desteğini etkinleştir
stm32f4x.cpu configure -rtos FreeRTOS

# Zephyr RTOS
# stm32f4x.cpu configure -rtos Zephyr

# Desteklenen RTOS'lar:
# FreeRTOS, ThreadX, ChibiOS, eCos, embKernel, uCOS-III, Zephyr, nuttx

Thread-aware GDB

gdb — thread komutları
# OpenOCD + RTOS desteği aktifken GDB'de thread listesi
(gdb) info threads
#   Id   Target Id         Frame
#   1    Thread 1 "IDLE"   0x0800112c in vPortYieldFromTick ()
#   2    Thread 2 "sensor" 0x08003456 in sensor_task (pvParam=0x0)
# * 3    Thread 3 "comm"   0x08004abc in xQueueReceive (...)

# Belirli thread'e geç
(gdb) thread 2

# Bu thread'in backtrace'i
(gdb) backtrace
# #0  sensor_task (pvParam=0x0) at src/sensor.c:78
# #1  0x08001234 in prvTaskExitError ()

# Tüm thread'lerde backtrace
(gdb) thread apply all backtrace

# Belirli thread'in yerel değişkenleri
(gdb) thread 2
(gdb) frame 0
(gdb) info locals

# FreeRTOS task listesini OpenOCD telnet'ten de görebilirsiniz
# > rtos threads

FreeRTOS heap ve stack analizi

gdb — FreeRTOS iç durumu
# FreeRTOS sembol dosyası yüklü olmalı (firmware.elf ile)

# Heap kullanımı
(gdb) print xFreeBytesRemaining
(gdb) print xMinimumEverFreeBytesRemaining

# Task listesi
(gdb) print uxCurrentNumberOfTasks

# Stack yüksek su işareti (her task için)
# configCHECK_FOR_STACK_OVERFLOW=2 ile stack overflow detection
(gdb) call uxTaskGetStackHighWaterMark(sensor_task_handle)

Zephyr RTOS aware debug

openocd.cfg — Zephyr
# Zephyr için target konfigürasyonu
stm32f4x.cpu configure -rtos Zephyr

# Zephyr west build ile debug sembol dosyası
# build/zephyr/zephyr.elf

# GDB'de
# (gdb) file build/zephyr/zephyr.elf
# (gdb) target extended-remote :3333
# (gdb) info threads
# Thread 1 "main"  — Zephyr main thread
# Thread 2 "idle"  — idle thread
NOT

OpenOCD RTOS desteği, RTOS'un sembol adlarını (task list pointer, TCB yapısı) firmware ELF dosyasından okur. Firmware ELF'in debug sembolleriyle (-g flag, CONFIG_DEBUG_OPTIMIZATIONS) derlenmiş olması gerekir. Production binary'lerde semboller olmayabilir.

Bu bölümde

  • cpu configure -rtos FreeRTOS OpenOCD config'e ekle; GDB otomatik thread-aware olur
  • info threads tüm RTOS task'larını listeler; thread N ile geç
  • thread apply all backtrace tüm task'ların call stack'ini gösterir
  • RTOS sembolleri için firmware debug sembolleriyle derlenmeli

08 Pratik: STM32 tam debug workflow

STM32F4-Discovery veya Nucleo kartıyla uçtan uca debug ortamı: OpenOCD + GDB + VS Code cortex-debug extension tam kurulumu.

Gereksinimler

BileşenKaynakNotlar
arm-none-eabi-gccapt install gcc-arm-none-eabiÇapraz derleyici
arm-none-eabi-gdbapt install gdb-arm-none-eabiveya toolchain içinde
OpenOCDapt install openocdv0.12.0+ önerilir
VS Codecode.visualstudio.comIDE
cortex-debugVS Code Marketplacemarus25.cortex-debug
STM32F4-Discovery / NucleoST-Link v2 dahili

Proje yapısı

bash — proje dizini
myproject/
├── src/
│   └── main.c
├── startup/
│   └── startup_stm32f407xx.s
├── linker/
│   └── STM32F407VGTx_FLASH.ld
├── Makefile
├── openocd.cfg
└── .vscode/
    ├── launch.json
    └── tasks.json

openocd.cfg

openocd.cfg — proje konfigürasyonu
# STM32F4-Discovery / Nucleo için
source [find interface/stlink.cfg]
transport select hla_swd
adapter speed 4000

source [find target/stm32f4x.cfg]

reset_config srst_only

# FreeRTOS kullanıyorsanız açın
# stm32f4x.cpu configure -rtos FreeRTOS

# GDB bağlandığında otomatik halt
stm32f4x.cpu configure -event gdb-attach {
    halt
}

.vscode/launch.json

.vscode/launch.json — cortex-debug konfigürasyonu
{
    "version": "0.2.0",
    "configurations": [
        {
            "name": "OpenOCD Debug",
            "type": "cortex-debug",
            "request": "launch",
            "servertype": "openocd",
            "configFiles": [
                "openocd.cfg"
            ],
            "executable": "build/firmware.elf",
            "armToolchainPath": "/usr/bin",
            "device": "STM32F407VG",
            "svdFile": "${workspaceRoot}/STM32F407.svd",
            "runToEntryPoint": "main",
            "preLaunchTask": "build",
            "liveWatch": {
                "enabled": true,
                "samplesPerSecond": 4
            }
        },
        {
            "name": "OpenOCD Attach",
            "type": "cortex-debug",
            "request": "attach",
            "servertype": "openocd",
            "configFiles": [
                "openocd.cfg"
            ],
            "executable": "build/firmware.elf",
            "armToolchainPath": "/usr/bin"
        }
    ]
}

.vscode/tasks.json — build task

.vscode/tasks.json
{
    "version": "2.0.0",
    "tasks": [
        {
            "label": "build",
            "type": "shell",
            "command": "make -j$(nproc)",
            "group": {
                "kind": "build",
                "isDefault": true
            },
            "problemMatcher": "$gcc"
        },
        {
            "label": "flash",
            "type": "shell",
            "command": "openocd -f openocd.cfg -c 'program build/firmware.elf verify reset exit'",
            "dependsOn": "build"
        },
        {
            "label": "clean",
            "type": "shell",
            "command": "make clean"
        }
    ]
}

SVD dosyası ile peripheral görüntüleme

SVD (System View Description) dosyası, SoC'un tüm peripheral register'larını adres, isim ve bit alanı tanımlarıyla içerir. cortex-debug bu dosyayı okuyarak VS Code'da gerçek zamanlı peripheral register paneli sunar.

bash — SVD dosyası indirme
# STM32 SVD dosyaları CMSIS-SVD deposunda
git clone https://github.com/cmsis-svd/cmsis-svd-data.git
find cmsis-svd-data/ -name "STM32F407.svd"
# cmsis-svd-data/data/STMicro/STM32F407.svd

cp cmsis-svd-data/data/STMicro/STM32F407.svd /path/to/project/

Komut satırından tam debug workflow

bash — terminal tabanlı tam workflow
# 1. Derle
make -j$(nproc)

# 2. Flash et
openocd -f openocd.cfg \
    -c "program build/firmware.elf verify reset exit"

# 3. OpenOCD debug server başlat (arka planda)
openocd -f openocd.cfg &
OPENOCD_PID=$!

# 4. GDB ile bağlan ve debug et
arm-none-eabi-gdb build/firmware.elf \
    -ex "target extended-remote :3333" \
    -ex "monitor reset halt" \
    -ex "break main" \
    -ex "continue"

# 5. Debug bitince OpenOCD'yi kapat
kill $OPENOCD_PID
NOT

VS Code cortex-debug extension, "svdFile" tanımlandığında peripheral görünümü sağlar — GPIOA_ODR, TIM2_CNT gibi register'lar debug sırasında doğrudan izlenebilir. Bu özellik, osiloskopta ya da logic analyzer'da görmesi zor olayları kod seviyesinden incelemeyi sağlar.

Bu bölümde

  • Proje yapısı: openocd.cfg + .vscode/launch.json + .vscode/tasks.json
  • launch.json: servertype=openocd, configFiles, executable, svdFile
  • SVD dosyası ile VS Code'da gerçek zamanlı peripheral register paneli
  • CI/CD için: openocd -f openocd.cfg -c "program firmware.elf verify reset exit"