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.
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ı
| Register | Amaç | Örnek komutlar |
|---|---|---|
| IR (Instruction) | TAP'a hangi DR'nin seçileceğini yazar | BYPASS, IDCODE, SAMPLE/PRELOAD, EXTEST |
| DR (Data) | Seçilen fonksiyona göre değişir | Boundary scan chain, debug data register |
| IDCODE | Cihaz kimliği (manufacturer, part, version) | 32-bit, IR'a IDCODE yazıldığında DR'den okunur |
| BYPASS | 1-bit pass-through; daisy-chain'de kullanılmayan TAP'ları atla | IR'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.
| Özellik | JTAG | SWD |
|---|---|---|
| Pin sayısı | 4–5 (TCK, TMS, TDI, TDO, TRST) | 2 (SWDIO, SWCLK) |
| Daisy-chain | Evet; birden fazla TAP | Hayır; single target |
| Standart | IEEE 1149.1 (açık) | ARM özel (açık doküman) |
| Hız | Benzer | Benzer; bazı probe'larda biraz daha hızlı |
| Platform | Evrensel (ARM, RISC-V, MIPS, vb.) | ARM Cortex-M / Cortex-A / Cortex-R |
| Ne zaman kullan | Cortex-A, çok çekirdek, daisy-chain | Cortex-M, dar alan, basit setup |
Debug probe türleri
| Probe | Protokol | Fiyat | Özellik |
|---|---|---|---|
| ST-Link v2/v3 | SWD, JTAG | Düşük (10–25 $) | STM32 için yerleşik (Nucleo/Discovery); standalone da var |
| J-Link (Segger) | SWD, JTAG | Orta–Yüksek (50–600 $) | Geniş MCU/SoC desteği; hızlı; ticari lisans gerekir |
| CMSIS-DAP / DAPLink | SWD, JTAG | Düşük (5–20 $) | ARM standardı; açık kaynak; USB HID; geniş destek |
| FTDI (FT2232H) | SWD, JTAG, SPI, I2C | Düşük (15–30 $) | Çok yönlü; OpenOCD FTDI sürücüsüyle; ham GPIO modu |
| OpenOCD + Raspberry Pi | JTAG (GPIO bitbang) | Sıfır (Pi'niz varsa) | Yavaş; prototip ve kurtarma için kullanışlı |
| Black Magic Probe | SWD, JTAG | Orta (50–80 $) | GDB server probe içinde; OpenOCD gerekmez |
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
# 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)
# 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.cfg | Proje özelinde üst seviye config | Projenizin kök dizininde |
# 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 openocdhızlı başlangıç; güncel sürüm için kaynak build- udev kuralları USB erişimi için zorunlu; kullanıcıyı
plugdevgrubuna ekle - Hiyerarşi: interface → target → board konfigürasyonu
openocd -f interface/stlink.cfg -f target/stm32f4x.cfgen 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
# 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
# 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
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
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)
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
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
# 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
# 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
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
# 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_onlyveyanoneSRST 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ı
# 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ı
# 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
# 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
# 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
# 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 4444ile OpenOCD interaktif shell'e erişimhalt,resume,step,reset haltCPU kontrolümdw/mwwbellek okuma/yazma; peripheral register erişimi için de kullanılırbphardware breakpoint;wpwatchpoint
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
# 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ı
# 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
# 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
# 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
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 0flash bankını ve sektörlerini listelerprogram firmware.elf verify reset exittek 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ı
# 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)
# 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ı
# 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
# 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
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 :3333OpenOCD GDB server'a bağlanırloadfirmware'i yükler;monitor reset haltOpenOCD komutunu iletir- Flash üzerinde
hbreak(hardware breakpoint) zorunlu; sınır: genellikle 6 BP + 4 WP .gdbinitile 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
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
# 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
# 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
# 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
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 FreeRTOSOpenOCD config'e ekle; GDB otomatik thread-aware olurinfo threadstüm RTOS task'larını listeler;thread Nile geçthread apply all backtracetü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şen | Kaynak | Notlar |
|---|---|---|
| arm-none-eabi-gcc | apt install gcc-arm-none-eabi | Çapraz derleyici |
| arm-none-eabi-gdb | apt install gdb-arm-none-eabi | veya toolchain içinde |
| OpenOCD | apt install openocd | v0.12.0+ önerilir |
| VS Code | code.visualstudio.com | IDE |
| cortex-debug | VS Code Marketplace | marus25.cortex-debug |
| STM32F4-Discovery / Nucleo | — | ST-Link v2 dahili |
Proje yapısı
myproject/
├── src/
│ └── main.c
├── startup/
│ └── startup_stm32f407xx.s
├── linker/
│ └── STM32F407VGTx_FLASH.ld
├── Makefile
├── openocd.cfg
└── .vscode/
├── launch.json
└── tasks.json
openocd.cfg
# 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
{
"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
{
"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.
# 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
# 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
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"