ไม่มีอะไรน่าหงุดหงิดไปกว่าการที่โปรเจคเกือบจะทำงานได้ตามที่ตั้งใจไว้ แต่เราพิมพ์ข้อมูลลง Serial ได้แค่นั้นแหละเพื่อจะเข้าใจโค้ดตัวเอง
นี่แหละคือจุดที่เครื่องมือดีบัก (Debugging Tools) เข้ามาช่วยชีวิต มันจะยอมให้เราหยุดการทำงานของโค้ดที่จุดที่เราต้องการ และให้เราตรวจสอบค่าตัวแปรต่างๆ ได้ แถมยังเดินโค้ดทีละบรรทัดได้ถ้าอยากด้วย
เราสามารถใช้ระบบดีบัก GDB ร่วมกับฮาร์ดแวร์ดีบักเจอร์ภายนอกกับบอร์ด Arduino Nano 33 IoT ได้ ต้องขอบคุณจุดต่อ (breakouts) บนบอร์ดนี่แหละ แค่บัดกรีนิดหน่อยก็ใช้ได้แล้ว
ด้วยชุดซอฟต์แวร์ Arduino IDE + Visual Micro + Visual Studio เราจะได้ประสบการณ์ IDE แบบเต็มรูปแบบ พร้อมกับเครื่องมือดีบักพวกนี้แบบพร้อมใช้เลย
ลึกลงไปในรายละเอียดทางเทคนิค
- โปรโตคอล SWD (Serial Wire Debug):
- พินและการสื่อสาร: ไม่เหมือนกับมาตรฐาน JTAG 20 พิน, SWD ใช้แค่สองพิน: SWDIO (Serial Wire Data I/O) และ SWCLK (Serial Wire Clock) พวกนี้อยู่ที่แผ่นแพดเล็กๆ บนด้านล่างของ Nano 33 IoT
- การจำลองวงจรในตัว (In-Circuit Emulation): SWD อนุญาตให้โพรบภายนอกเข้ามาควบคุมโปรแกรมเคาน์เตอร์ของ ARM Core ได้ ทำให้สามารถดีบักในโหมด "หยุด" (Stop-Mode) ซึ่งทั้งระบบ SoC จะหยุดนิ่ง รวมถึงตัวจับเวลาและสถานะของเพอริเฟอรัลต่างๆ ด้วย
- GDB (GNU Debugger) และ Segger J-Link:
- ลอจิกตัวกลาง: Segger J-Link ทำหน้าที่เป็นตัวแปลภาษา มันแปลงสัญญาณดีบักความเร็วสูงที่เป็นกรรมสิทธิ์ของชิป ให้เป็นสตรีมมาตรฐาน TCP/IP หรือ Serial ที่ GDB (ที่รันบนพีซีของเรา) สามารถเข้าใจได้
- เบรกพอยต์และฮาร์ดแวร์วอทช์พอยต์: SAMD21 มีจำนวน ฮาร์ดแวร์เบรกพอยต์ ที่จำกัด (ปกติ 4-6 อัน) พวกนี้ถูกนำไปใช้ผ่านหน่วยเบรกพอยต์ (BPU) ในแกน Cortex-M0+ ไม่เหมือนกับซอฟต์แวร์เบรกพอยต์ที่ต้องไปแก้ไขโค้ดเครื่อง ฮาร์ดแวร์เบรกพอยต์จะคอยเฝ้าดูบัสแอดเดรสและหยุด CPU เมื่อมีการเข้าถึงแอดเดรสหน่วยความจำที่ระบุไว้
- ความท้าทายจากการออปติไมซ์คอมไพเลอร์:
- แฟล็ก
-O0: เพื่อให้การเดินโค้ดทีละบรรทัดแม่นยำ โค้ดต้องถูกคอมไพล์ด้วย ระดับการออปติไมซ์เป็นศูนย์ (Optimization Level Zero) การคอมไพล์ Arduino แบบมาตรฐาน (-Os) มักจะ "จัดเรียงโค้ดใหม่" หรือลบตัวแปรที่ไม่ได้ใช้ออกเพื่อประหยัดพื้นที่ ซึ่งทำให้เคอร์เซอร์ของดีบักเกอร์กระโดดไปมาระหว่างโค้ดอย่างไม่เป็นระเบียบ vMicro จะจัดการการเปลี่ยนโหมดนี้ให้อัตโนมัติเมื่อเลือกโหมด "Debug"
- แฟล็ก
- การแยกเลเยอร์ไดรเวอร์ USB (Zadig):
- Windows มักจะตั้งค่าไดรเวอร์พอร์ตอนุกรมมาตรฐาน (COM port) ให้กับโพรบที่เชื่อมต่อโดยอัตโนมัติ นักพัฒนาต้องใช้ เครื่องมือ Zadig เพื่อบังคับให้ติดตั้งไดรเวอร์ "WinUSB" หรือ "libusb-win32" ลงบน Interface 0 ของ J-Link การทำแบบนี้จะทำให้ซอฟต์แวร์ระดับล่าง เช่น OpenOCD หรือ Segger GDB Server สามารถข้ามสแต็กไดรเวอร์มาตรฐานของระบบปฏิบัติการไปได้ เพื่อเข้าถึงฮาร์ดแวร์โดยตรง
งานบัดกรี
ก่อนที่เราจะเชื่อมต่อบอร์ด Nano 33 IoT ของเราเข้ากับดีบักเจอร์ภายนอกได้ เราต้องบัดกรีสายจัมเปอร์หัวเมียลงบนแผ่นแพดที่ด้านหลังของบอร์ดก่อน ตามรูปด้านล่างเลย


วิศวกรรมและการลงมือทำ: บัดกรีอย่างประณีตสำหรับ SMD: การเข้าถึงแพดดีบักต้องใช้เทคนิคการบัดกรีแบบ "Dead-Bug" ต้องใช้ฟลักซ์ (Flux) เป็นเรื่องจำเป็นที่นี่ เพื่อให้แน่ใจว่าการเชื่อมต่อระหว่างสายจัมเปอร์ขนาด 30AWG กับแผ่นแพดชุบทองบน Nano 33 IoT จะสะอาดและไม่มีสะพานเชื่อม การใช้จัมเปอร์หัวเมียทำให้บอร์ดสามารถเสียบตรงเข้ากับเฮดเดอร์ IDC 20 พินของ J-Link ได้เลย จัดไปวัยรุ่น!
ตัวดีบักฮาร์ดแวร์ภายนอก
มีอุปกรณ์ดีบักฮาร์ดแวร์ภายนอกให้เลือกใช้หลายแบบ ในตัวอย่างนี้เราจะใช้ดีบักเกอร์ Segger J-Link (รุ่น EDU ที่ราคาถูกสำหรับการศึกษา)
มีดีบักเกอร์ตัวอื่นอย่าง Black Magic Probe ด้วยนะ ซึ่งเชื่อมต่อแบบเดียวกันกับที่แสดงที่นี่ และมันก็พร้อมใช้งานใน Visual Micro อยู่แล้ว หรือจะสร้าง Probe ใช้เองก็ได้ตามที่เคยเขียนไว้ในบทความเกี่ยวกับ Nano 33 BLE
การเชื่อมต่อระหว่างอุปกรณ์ทั้งสองแสดงไว้ด้านล่าง


ตัวเลือก Black Magic Probe: Black Magic Probe มันพิเศษตรงที่มันโฮสต์เซิร์ฟเวอร์ GDB บนตัว Probe เอง เลย ไม่ต้องไปวุ่นวายตั้งค่าไดรเวอร์ซับซ้อนอย่าง OpenOCD บน PC
ตั้งค่าไดรเวอร์
ดีบักเกอร์บางตัวต้องการติดตั้ง USB Driver เพิ่มเติมบน Windows เพื่อให้การดีบักทำงานถูกต้อง
ในตัวอย่าง J-Link ของเรา คุณจะต้องใช้เครื่องมือ Zadig เพื่อติดตั้งไดรเวอร์ให้ตรงกัน
เปิดเครื่องมือ Zadig หลังจากดาวน์โหลดมาแล้ว
เลือก Options > List All Devices
ตอนนี้เลื่อนดรอปดาวน์ลิสต์อุปกรณ์แล้วเลือกอุปกรณ์ของคุณ (ในกรณีนี้คือ JLink)
ถ้ามีอุปกรณ์สองตัว ให้เลือก "Interface 0" ของอุปกรณ์
ถ้าเวอร์ชันไดรเวอร์ไม่ตรงกัน ให้คลิก Install Driver
มีรายการข้อมูลดีบักเกอร์และไดรเวอร์เพิ่มเติมที่เป็นประโยชน์อยู่
ตั้งค่าการดีบัก
เมื่อคุณตั้งค่า Arduino IDE + Visual Studio + Visual Micro เรียบร้อยแล้ว คุณก็เริ่มดีบักได้ทันที
แค่เปิดโปรเจคของคุณแล้วเลือกบอร์ดและพอร์ต COM ที่ถูกต้อง
ตอนนี้คุณสามารถตั้งค่าดีบักเกอร์เป็น "Hardware" ซึ่งจะแสดงรายการดีบักเกอร์ที่กำหนดค่าไว้ล่วงหน้าใหม่
เลือกตัวที่คุณใช้อยู่ และตรวจสอบให้แน่ใจว่า vMicro > Debugger > Optimisation ถูกตั้งค่าเป็น "No Project + Libraries"
เพิ่มจุดพัก (breakpoint) ในตำแหน่งที่คุณต้องการหยุดครั้งแรก จุดพักเหล่านี้สามารถย้ายได้หลังจากที่คุณเริ่มดีบักเกอร์แล้ว และมักจะมีขีดจำกัดที่ 6 จุดพักพร้อมกัน
ตอนนี้ก็แค่บิลด์และอัปโหลดโค้ดของคุณ แล้วแนบดีบักเกอร์ คุณสามารถทำทั้งหมดนี้ในขั้นตอนเดียวได้โดยกด Debug > Start Debugging
เวิร์กโฟลว์ของ Visual Micro: เอ็กซ์เทนชัน Visual Micro สำหรับ Visual Studio มี "แดชบอร์ด" สำหรับการดีบัก มันอนุญาตให้ใช้ตรรกะ "Break on Exception" ซึ่งจะหยุดโปรเซสเซอร์ทันทีถ้าโค้ดพยายามเข้าถึงพอยน์เตอร์ที่เป็นค่าว่างหรือทำการหารด้วยศูนย์
การแสดงข้อมูลแบบเรียลไทม์: นอกเหนือจากการสเตปแล้ว ฮาร์ดแวร์ดีบักเกอร์ยังอนุญาตให้ใช้ Variable Watches ได้ด้วย คุณสามารถติดตามค่าผลลัพธ์ของ analogRead หรือตัวแปรความแรงสัญญาณ Wi-Fi ได้แบบเรียลไทม์ โดยไม่ต้องเพิ่ม "โอเวอร์เฮดสำหรับดีบัก" หรือความล่าช้าใดๆ ลงในโค้ดที่ใช้จริง
วิดีโอของส่วนตั้งค่าการดีบักนี้อยู่ด้านล่าง:
มาจัดการปัญหากันเถอะ
ตอนนี้น้องน่าจะหยุดอยู่ที่ Breakpoint แล้ว และมีหน้าต่างอื่นๆ อีกเพียบในเมนู Debug > Windows ถ้าน้องยังไม่เห็นหน้าต่าง Watches / Autos ฯลฯ ที่อยากใช้ ก็ไปเปิดมาได้เลย
ใช้เครื่องมือ Stepping กับ Inspection เดินไล่โค้ดไปเรื่อยๆ แล้วจะเจอจุดบั๊กเอง
เลิกเดาแล้วมาไล่โค้ดกันดีกว่า: ใช้เครื่องมือ GDB ระดับโปร กับบอร์ด Nano 33 IoT ของน้องให้เป็นเรื่องเป็นราว
ลิงก์ที่เป็นประโยชน์
เริ่มต้นใช้งาน Arduino NANO 33 IoT
Segger J-Link Debug Probes
Segger EDU Debug Probes
Black Magic Wiki และรายการฮาร์ดแวร์ / ผู้ขาย
Zadig USB Driver Tool
Visual Micro - ภาพรวมการดีบั๊ก Nano 33 IoT
Visual Micro - รายการดีบักเกอร์ที่รองรับ (ทั้งหมด)
บทช่วยสอน: สร้าง Debug Probe และใช้กับ Nano 33 BLE