Belajar Embedded Engineer - Debugging & Toolchain
Episode 9 of 28

Belajar Embedded Engineer - Debugging & Toolchain

Membekali diri dengan senjata debugging profesional: OpenOCD + GDB untuk breakpoint dan memory inspection, pendekatan sistematis memburu bug, trace berbasis SEGGER RTT, dan logic analyzer untuk melihat sinyal fisik, ditutup praktik sesi debug pada firmware yang sengaja dibuat rusak

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

Semua episode sebelumnya membangun kode; episode ini membangun kemampuan menemukan kesalahan. Di embedded, debugging tidak semewah di desktop — tidak ada console error yang rapi, dan bug bisa bersembunyi di persimpangan software dan hardware: kabel longgar, timing salah, register salah set.

Kabar baiknya, toolchain yang kalian siapkan di episode 0 — OpenOCD dan GDB — mampu melakukan debugging level profesional di MCU: breakpoint, menelusuri memory, membaca register peripheral, dan trace. Kemampuan inilah yang memisahkan engineer yang memburu bug seminggu dari yang menemukannya dalam satu jam. Episode ini membangun keterampilan itu.

Alur Debugging: OpenOCD sebagai Jembatan

OpenOCD adalah debug adapter: ia menerjemahkan perintah GDB menjadi sinyal debug (SWD/JTAG) ke MCU lewat probe ST-Link. Alur kerjanya:

Alur sesi debug
GDB (client) <--TCP 3333--> OpenOCD <--SWD--> MCU target

Langkah pertama, jalankan OpenOCD dengan konfigurasi probe dan target:

Jalankan OpenOCD untuk ST-Link + STM32F4
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg

Jika berhasil, kalian akan melihat output Info : stm32f4x.cpu: hardware has 6 breakpoints, 4 watchpoints. Artinya server debug sudah siap di port 3333. Selanjutnya hubungkan GDB:

Hubungkan GDB (terminal terpisah)
arm-none-eabi-gdb -q firmware.elf
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) continue

Perintah monitor reset halt me-reset MCU dan menghentikannya di reset vector — jadi kalian bisa melangkah dari awal. load mem-flash binary. Setelah itu kalian bisa memakai semua perintah GDB klasik.

Perintah GDB yang Wajib Dikuasai

Inilah perintah yang menutupi 90% kebutuhan debugging firmware:

PerintahFungsi
break main / break file.c:42Set breakpoint
continueJalan sampai breakpoint berikutnya
next / stepLangkah per baris (next melompati fungsi)
info registersLihat semua register CPU
x/16wx 0x20000000Dump 16 word dari RAM
p/x GPIOA->ODRBaca register peripheral
btBacktrace — dari mana fungsi ini dipanggil
watch variableBreak saat variabel berubah

Contoh sesi — firmware hang di main, kalian ingin tahu di mana:

Sesi GDB singkat
(gdb) break main
(gdb) continue
(gdb) step
(gdb) p GPIOA->MODER
$1 = 0x00000200      # hanya pin 5 yang jadi output
(gdb) x/8xw 0x20000000
0x20000000: 0x00000000 0x00000000 ...

Pola debugging yang terbukti efektif: set breakpoint di awal fungsi yang dicurigai → step baris demi baris → periksa variabel dan register di tiap titik. Bukan menebak. Memory inspection (x) sering kali menemukan jawaban lebih cepat daripada berpikir.

Trace: Melihat Program "Dari Dalam"

Kadang breakpoint mengubah perilaku program (efek observasi — bug hanya muncul saat tidak di-debug). Solusinya trace: merekam jejak eksekusi tanpa menghentikan program.

Opsi paling praktis untuk MCU kecil: SEGGER RTT — buffer kecil di RAM yang ditulis cepat oleh firmware, dan dibaca oleh host lewat debug probe. Bekerja seperti "printf tanpa UART" dengan dampak minimal:

c
#include "SEGGER_RTT.h"
 
SEGGER_RTT_printf(0, "sensor=%u adc=%u\n", (unsigned)sensor_id, (unsigned)adc);

Bedanya dengan printf UART: tidak butuh kabel serial, tidak memblokir, dan muncul langsung di terminal host. Ini tool terbaik untuk debug timing dan alur log di firmware live. Perangkat lain yang wajib dikenal: SWO/ITM trace (STM32) dan Segger SystemView untuk visualisasi timing task RTOS.

Tip

Logging itu investasi. Tambahkan level log (error/warn/info/debug) sejak awal proyek — bahkan saat "semuanya berjalan". Saat bug muncul di lapangan, log yang baik adalah saksi mata yang tidak bisa disuap; tanpa log, kalian hanya punya tebakan dan tekanan.

Logic Analyzer: Mata untuk Sinyal Fisik

Ketika bug bukan di software tapi di komunikasi nyata — byte UART salah, SPI tidak sinkron, I2C stuck — kalian butuh melihat sinyalnya. Di sinilah logic analyzer berperan: merekam level HIGH/LOW pin sepanjang waktu.

Logic analyzer USB murah (misal berbasis chip 8-channel) cukup untuk memulai. Dengan software seperti PulseView/sigrok:

  1. Hubungkan probe ke pin TX/RX (UART), SCL/SDA (I2C), atau CS/MOSI/MISO (SPI).
  2. Atur sample rate (minimal 4x kecepatan bus).
  3. Dekode protokol otomatis — kalian bisa "membaca" byte yang sebenarnya lewat.

Contoh: display LCD "tidak merespons". Logic analyzer di pin I2C akan menunjukkan apakah address benar, apakah ada ACK, dan di mana komunikasi terhenti — jawaban instan untuk pertanyaan yang biasanya memakan hari.

Praktik: Sesi Debug Lengkap

Praktik untuk mengasah kemampuan:

  1. Buat firmware bare-metal dari episode 6, lalu sengaja rusak: lupa enable clock GPIO.
  2. Debug dengan GDB: periksa GPIOA->MODER setelah led_init — nilainya nol, artinya register tidak berubah. Ini petunjuk: clock tidak jalan.
  3. Perbaiki, lalu sengaja buat stack overflow (rekursi tak berujung) — perhatikan bagaimana GDB menunjukkan backtrace korup.
  4. Pasang RTT log di task FreeRTOS dan amati alur eksekusi di SystemView.

Note

Debug adalah seni bertanya pada sistem. Sebelum mengubah apa pun, tuliskan hipotesis: "Saya pikir X, karena Y". Kemudian gunakan GDB/memory inspection/logic analyzer untuk membuktikan atau membantah hipotesis itu. Engineer yang menebak-nebak tanpa bukti hanya menambah bug baru.

Common Pitfalls

  1. Build tanpa -g — GDB tidak punya symbol → debugging buta. Selalu build debug dengan -g -O0.
  2. Optimasi -O2 saat debug — baris kode tidak lagi satu-ke-satu dengan asm; pindah -O0 saat debug.
  3. Lupa membaca register error — banyak MCU menyimpan detail error di register (misal SR); periksa sebelum menebak.
  4. Breakpoint yang mengubah timing — untuk bug timing, pakai trace bukan breakpoint.

Penutup

Inti yang harus dibawa pulang:

  • OpenOCD menghubungkan GDB ke MCU; sesi debug = target remote, load, breakpoint.
  • Kuasai perintah GDB inti: break, next, step, x, p, bt.
  • Trace (SEGGER RTT / SWO) untuk melihat perilaku tanpa menghentikan program.
  • Logic analyzer untuk membaca sinyal fisik ketika komunikasi bermasalah.
  • Debug = hipotesis + bukti, bukan tebakan.

Di episode 10 selanjutnya kita naik kelas: embedded Linux — kernel basics, device tree, driver, dan rootfs, dengan praktik menyalakan Linux di board. Dunia MCU yang kalian kuasai akan menjadi kompas saat menghadapi kompleksitas yang jauh lebih besar. Sampai jumpa di episode 10!