Hướng dẫn debug trên Keil C IDE – Debug chương trình vi điều khiển STM32F103

Debug (gỡ lỗi) là một kĩ năng cần có của một lập trình viên. Mục đích của Debug không chỉ dùng để loại bỏ lỗi (error) khỏi chương trình mà quan trọng debug sẽ giúp lập trình viên hiểu rõ hơn và kiểm tra được sự thực thi của chương trình. Một lập trình viên chưa trang bị cho bản thân kĩ năng debug thì sẽ rất khó kiểm soát sự thực thi chương trình của mình.

[HỌC ONLINE: LẬP TRÌNH VI ĐIỀU KHIỂN STM32, VI XỬ LÝ ARM CORTEX – M]

Bug (lỗi) có thể sinh ra từ chương trình bạn viết ra hoặc từ chương trình bạn kế thừa. Khi một chương trình được chạy nhưng kết quả không như bạn đang mong đợi, đó chính là lỗi (không phải lỗi cú pháp). Đối với những chương trình nhỏ, những đoạn code ngắn, bạn có thể kiểm tra các khối/dòng lệnh để tìm lỗi, nhưng cách đó sẽ không hiệu quả đối với 1 chương trình lớn hơn, với nhiều luồng xử lý, lúc này bạn nên sử dụng công cụ debug. Không chỉ vậy, để kiểm tra được nhiều nhất có thể các trường hợp mà chương trình có thể xẩy ra lúc thực thi, công cụ debug sẽ giúp bạn can thiệp vào chương trình để chương trình chạy theo hướng mình muốn kiểm tra. 

Trong hệ thống nhúng, có 2 cách debug chương trình của bạn:

  • Debug phần mềm:  sử dụng debug phần mềm,  không cần sử dụng board phần cứng.
  • Debug phần cứng: yêu cầu phải được kết nối từ board đến máy tính.

Ở trong phần này,  bài viết sẽ  hướng dẫn các bạn debug phần cứng, gồm các nội dung sau:

  • Quan sát sự thay đổi của thanh ghi thông qua việc nhấp nháy led
  • Quan sát sự thay đổi của biến ở một kiểu dữ liệu bất kì
  • Quan sát sự thay đổi của một mảng ở dữ liệu bất kì

Một số công cụ trên IDE mà các bạn cần biết trước để thuận tiện trong quá trình debug: 

  •  Nhấn  LOAD để nạp code vào bộ nhớ flash.
  • Nhấn debug     để bắt đầu quá trình và bấm lại thêm 1 lần nữa để thoát chế độ debug. Bạn có thể sử dụng nút breakpoint  để cài đặt một điểm break point trong window disassembly hoặc window source.
  • STM32 cho phép đến 6 break point trong quá trình debug phần cứng. Khi chương trình dừng lại ở tại 1 breakpoint, thì câu lệnh tương ứng chưa được thực thi.
  • Bạn có thể quan sát câu lệnh nào đang được thực thi trên cửa sổ disassembly và cửa sổ source.Các nút cho bộ debug

Run: thực hiện từ vị trí hiện tại (hoặc vị trí bắt đầu) cho đến khi click vào stop hoặc chương trình sẽ tạm dừng tại vị trí điểm breakpoint.

Step In: Thực thi một câu lệnh và vào một hàm nếu dòng hiện tại gọi đến hàm đó.

Step Over: Thực thi một câu lệnh và chạy tất các lệnh ở trong hàm nếu bước hiện tại gọi đến hàm đó.

Step Out: Thực thi cho đến trả về hàm hiện tại

1/ Thực hành debug nhấp nháy led ở chân PC13 và quan sát sự thay đổi của thanh ghi, các biến và mảng ở kiểu dữ liệu bất kì:

Sau khi sinh code ở CubeMX và mở project trên KeilC

Bước 1: 

 Khởi tạo một biến Variable kiểu và một mảng Array gồm 2 phần tử kiểu dữ liệu integer để quan sát sự thay đổi trong hàm main.

Bước 2:

  • Tăng giá trị của biến Variable cùng với những phần tử trong mảng Array lên 1 
  • Đảo trạng thái led PC13 với tần số 1s 1 lần.

Bước 4:

  • Biên dịch chương trình
  • Nhấn vào nút debug

Chú ý: Cứ mỗi lần có thay đổi gì ở source thì nên biên dịch lại rồi mới nạp hoặc biên dịch lại code rồi mới debug.Bước 5:

Hiển thị giao diện debug và một số chức năng của window:

Bước 6:

  • Bôi đen biến Variable 
  • Nhấn chuột phải và chọn Add “Variable” vào cửa sổ Watch1 để theo dõi sự thay đổi của biến
  • Tương tự ta thực hiện cho các phần tử mảng Array

Bước 7:

Sau khi Add các biến vào Watch 1,  chọn vào ô cửa sổ để quan sát các biến. Ở đây, chúng ta thấy các biến đã được Add vào Watch 1

Bước 8:

Quan sát được sử thay đổi của các biến,  tương ứng với 1s nó sẽ tăng lên 1 lần.

Bước 9:

Quan sát biến ở dạng thập phân:

  • Nhấn chuột phải vào biến
  • Bỏ chọn Hexadecimal Display

Bước 10:

  • Vào Peripheral và chọn System Viewer
  • Theo dõi các bit thay đổi trên những thanh ghi này

Bước 11:

Sau đó, nó sẽ hiện ra các thanh ghi của ngoại vi IO ở Port C.

Ở đây chúng ta sẽ thấy bit ODR13 thanh ghi Output Data Register ở bit 13 sẽ thay đổi:

2/ Dùng breakpoint để debug:

Breakpoint là những điểm (vị trí) trong chương trình được người lập trình chọn, tại điểm đó chương trình thực thi sẽ dừng lại, breakpoint được sử dụng trong debug mode. Breakpoint  rất hữu hiệu trong việc phát triển chương trình và gỡ lỗi.

• Sử dụng breakpoint để kiểm tra chương trình của bạn có thực hiện được đến câu lệnh mà bạn đặt breakpoint hay không. Nếu chương trình bạn chạy mãi không dừng, thì chứng tỏ lệnh tại breakpoint không bao giờ được thực hiện. Như vậy chương trình của bạn đã có lỗi.
• Sử dụng breakpoint để theo dõi, kiểm tra và thay đổi giá trị các biến, bộ nhớ, các thanh nghi ngoại vi, thanh ghi CPU, thanh ghi ngoại vi tại thời điểm dừng câu lệnh để quan sát chương trình chạy có đúng hay không, xem xét các giá trị có theo dự kiến  hoặc để tác động trực tiếp vào chương trình. 
• Sử dụng breakpoint tạm dừng chương trình để người sử dụng tương tác vào thông qua các ngoại vi, từ đó quan sát luồng chương trình có thực hiện đúng hay không sau khi tác động. 
Bước 1:

  • Nhấn chuột chọn vị trí đặt breakpoint
  • Nhấn biểu tượng trên thanh công cụ để thiết lập breakpoint. Ở đây, chúng ta đặt breakpoint khi vào hàm main.c 
  • Bật chế độ debug

Bước 2:

Sau khi bật debug thì chương trình đã dừng tại dòng 74

Chúng ta sử dung Step out để bỏ qua thực thi các hàm cấu hình trước khi vào hàm while để theo dõi các biến

Bước 3:

Chương trình sau khi vào vòng while

  • Thực thi từng câu lệnh để quan sát từng sự thay đổi ở các biến bằng Step (F11)
  • Quan sát sự thay đổi sau khi thực thi từng câu lệnh

Trên là một số hướng dẫn. Chúc các bạn thành công!

Xem thêm: Tổng hợp các bài hướng dẫn Lập trình vi điều khiển STM32 tại đây.

Nhóm Tapit ARM R&D