Làm cách nào để in thông báo gỡ lỗi lên bảng điều khiển gdb với bảng khám phá STM32 bằng GDB, OpenOCD và arm-none-eabi-gcc?


15

Tôi đang lập trình một bảng khám phá STM32 Cortex M0 (32F0308DISCOVERY) bằng OpenOCD, arm-none-eabi-gcc và gdb. Tôi đã tự hỏi nếu có bất kỳ cách đơn giản để đăng nhập các thông báo gỡ lỗi qua SWD. Tôi đã đọc về tùy chọn semihosting, nhưng điều này dường như đòi hỏi phải kéo vào newlib hoặc các thư viện lớn khác. (Chỉ có sẵn 64k flash.) Có cách nào nhẹ hơn để ghi nhật ký văn bản qua SWD không, hoặc sử dụng UART là tùy chọn thực tế duy nhất?


1
Tôi đề nghị bạn thử tùy chọn semihosting. Bằng cách chỉ định, các thư viện được cung cấp bởi CooCox (môi trường Windows Cortex-M miễn phí) cho M3 / 4 khá tối giản, chuyển một byte của họ là 17 hướng dẫn lắp ráp. Việc xây dựng lại một dự án cũ (STM32F4) với semihosting của họ và -O0 đã thêm 48 byte vào kích thước mã.
Markt

Bạn có thể không có trình liên kết của bạn tước mã không sử dụng. Đối với các lựa chọn thay thế, repo github của texane để lái các công cụ stlink có sơ đồ hộp thư đơn giản, mặc dù tôi chưa thử.
Chris Stratton

Câu trả lời:


15

Cảm ơn các con trỏ, markt và chris-stratton. Tùy chọn semihosting hóa ra khá đơn giản. Tôi quản lý để tìm nguồn cho một vài thói quen ghi nhật ký đơn giản có thể gửi tin nhắn đến bảng điều khiển OpenOCD. Tôi sẽ đăng chúng ở đây vì (i) họ yêu cầu một số sửa đổi để hoạt động và (ii) Tôi nghĩ rằng thông tin này không dễ tìm thấy đối với những người mới bắt đầu.

Đầu tiên, mã D ở đây dễ dàng được điều chỉnh để cung cấp chức năng C sau:

void send_command(int command, void *message)
{
   asm("mov r0, %[cmd];"
       "mov r1, %[msg];"
       "bkpt #0xAB"
         :
         : [cmd] "r" (command), [msg] "r" (message)
         : "r0", "r1", "memory");
}

Ví dụ về cách gọi send_command để viết một chuỗi vào bảng điều khiển OpenOCD:

const char s[] = "Hello world\n";
uint32_t m[] = { 2/*stderr*/, (uint32_t)s, sizeof(s)/sizeof(char) - 1 };
send_command(0x05/* some interrupt ID */, m);

Thứ hai, hàm putChar được đưa ra trong các nhận xét ở đây hoạt động tốt, ngoại trừ việc tôi phải thêm '#' trước 0x03:

void put_char(char c)
{
    asm (
    "mov r0, #0x03\n"   /* SYS_WRITEC */
    "mov r1, %[msg]\n"
    "bkpt #0xAB\n"
    :
    : [msg] "r" (&c)
    : "r0", "r1"
    );
}

Để xem kết quả đầu ra từ các chức năng này, trước tiên tôi khởi động OpenOCD, sau đó kết nối bằng arm-none-eabi-gdb như sau:

target remote localhost:3333
monitor arm semihosting enable
monitor reset halt
load code.elf
continue

Lưu ý rằng các thông báo xuất hiện trên thiết bị xuất chuẩn của quy trình OpenOCD, không phải trong bảng điều khiển GDB.


1
Có một lỗi, sizeof () phải là strlen ().

1
Cảm ơn người dùng107642. Trong thực tế, có thể sử dụng sizeof ở đây nếu 's' là một mảng chứ không phải là một con trỏ, vì vậy tôi đã sửa đổi nó theo cách đó.
gấp

Câu trả lời chính xác! Bạn cũng có thể viết putcharđơn giản nhưvoid putchar(char c) { send_command(3,&c); }
mvds

1
"Sizeof" sẽ đếm số \ 0 của chuỗi, trong khi strlen thì không. Nếu openocd chỉ in ra thiết bị xuất chuẩn và cửa sổ đầu cuối xterm, điều đó có lẽ sẽ không tạo ra sự khác biệt đáng chú ý vì thiết bị đầu cuối có thể sẽ bỏ qua nó. Nhưng nếu bạn kết thúc việc đưa mọi thứ vào một tệp, tôi nghĩ bạn sẽ ngạc nhiên khi tìm thấy những con số không trong đó. Hoặc giao thức xác định rằng bạn cần gửi các chuỗi với dấu kết thúc?
dùng242579

Ah, điểm tốt người dùng242579. Tôi đã thêm '-1' để tính đến dấu \ 0.
gấp
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.