Bagaimana cara mencetak pesan debug ke gdb console dengan papan penemuan STM32 menggunakan GDB, OpenOCD dan arm-none-eabi-gcc?

15

Saya memprogram papan penemuan STM32 Cortex M0 (32F0308DISCOVERY) menggunakan OpenOCD, arm-none-eabi-gcc, dan gdb. Saya bertanya-tanya apakah ada cara mudah untuk mencatat pesan debug melalui SWD. Saya sudah membaca tentang opsi semihosting, tetapi ini tampaknya memerlukan menarik di newlib atau perpustakaan besar lainnya. (Hanya tersedia 64k flash.) Apakah ada cara yang lebih ringan untuk mencatat teks melalui SWD, atau menggunakan UART satu-satunya pilihan praktis?

foldl
sumber
1
Saya sarankan Anda mencoba opsi semihosting. Sebagai indikasi, perpustakaan yang ditawarkan oleh CooCox (lingkungan Windows Cortex-M gratis) untuk M3 / 4 cukup minimalis, transfer byte tunggal mereka adalah 17 instruksi perakitan. Pembangunan kembali proyek lama (STM32F4) dengan semihosting dan -O0 ditambahkan 48 byte ke ukuran kode.
tandai
Anda mungkin tidak memiliki tautan yang menghapus kode yang tidak digunakan. Adapun alternatif, repo github texane untuk mengemudi alat stlink memiliki skema kotak surat sederhana, meskipun saya belum mencobanya.
Chris Stratton

Jawaban:

15

Terima kasih atas petunjuk, tanda dan chris-stratton. Opsi semihosting ternyata cukup mudah. Saya berhasil menemukan sumber untuk beberapa rutinitas logging sederhana yang dapat mengirim pesan ke konsol OpenOCD. Saya akan mempostingnya di sini karena (i) mereka memerlukan beberapa modifikasi untuk bekerja dan (ii) Saya pikir info ini tidak super mudah ditemukan bagi orang-orang yang baru memulai.

Pertama, kode D di sini mudah disesuaikan untuk menyediakan fungsi C berikut:

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");
}

Contoh memanggil send_command untuk menulis string ke konsol 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);

Kedua, fungsi putChar yang diberikan dalam komentar di sini berfungsi dengan baik, kecuali bahwa saya harus menambahkan '#' sebelum 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"
    );
}

Untuk melihat output dari fungsi-fungsi ini, pertama-tama saya memulai OpenOCD, kemudian terhubung menggunakan arm-none-eabi-gdb sebagai berikut:

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

Perhatikan bahwa pesan muncul di stdout dari proses OpenOCD, bukan di konsol GDB.

foldl
sumber
1
Ada bug, sizeof () harus strlen ().
1
Terima kasih user107642. Sebenarnya adalah mungkin untuk menggunakan sizeof di sini jika 's' adalah array daripada pointer, jadi saya telah memodifikasinya seperti itu.
foldl
Jawaban bagus! Anda juga dapat menulis putcharsesederhanavoid putchar(char c) { send_command(3,&c); }
mvds
1
"Sizeof" akan menghitung trailing \ 0 dari string, sedangkan strlen tidak akan. Jika openocd hanya mencetak ke stdout dan jendela terminal xterm, itu mungkin tidak akan membuat perbedaan nyata karena terminal mungkin akan mengabaikannya. Tetapi jika Anda akhirnya meletakkan sesuatu dalam file, saya pikir Anda akan terkejut menemukan angka nol di sana. Atau apakah protokol menentukan bahwa Anda perlu mengirim string dengan terminator trailing?
user242579
Ah, poin bagus user242579. Saya telah menambahkan '-1' untuk memperhitungkan trailing \ 0.
foldl