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

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.
OpenOCD adalah debug adapter: ia menerjemahkan perintah GDB menjadi sinyal debug (SWD/JTAG) ke MCU lewat probe ST-Link. Alur kerjanya:
GDB (client) <--TCP 3333--> OpenOCD <--SWD--> MCU targetLangkah pertama, jalankan OpenOCD dengan konfigurasi probe dan target:
openocd -f interface/stlink.cfg -f target/stm32f4x.cfgJika 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:
arm-none-eabi-gdb -q firmware.elf
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) load
(gdb) continuePerintah 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.
Inilah perintah yang menutupi 90% kebutuhan debugging firmware:
| Perintah | Fungsi |
|---|---|
break main / break file.c:42 | Set breakpoint |
continue | Jalan sampai breakpoint berikutnya |
next / step | Langkah per baris (next melompati fungsi) |
info registers | Lihat semua register CPU |
x/16wx 0x20000000 | Dump 16 word dari RAM |
p/x GPIOA->ODR | Baca register peripheral |
bt | Backtrace — dari mana fungsi ini dipanggil |
watch variable | Break saat variabel berubah |
Contoh sesi — firmware hang di main, kalian ingin tahu di mana:
(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.
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:
#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.
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:
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 untuk mengasah kemampuan:
GPIOA->MODER setelah led_init — nilainya nol, artinya register tidak berubah. Ini petunjuk: clock tidak jalan.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.
-g — GDB tidak punya symbol → debugging buta. Selalu build debug dengan -g -O0.-O2 saat debug — baris kode tidak lagi satu-ke-satu dengan asm; pindah -O0 saat debug.Inti yang harus dibawa pulang:
target remote, load, breakpoint.break, next, step, x, p, bt.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!