Redirect printf () dari STM32 ke Qt Creator Console

kdpv.svg


Seringkali ketika debugging perangkat lunak mikrokontroler, menjadi perlu untuk menampilkan pesan debugging, log, data yang diambil dan hal-hal lain ke layar PC. Pada saat yang sama, saya ingin output menjadi lebih cepat, dan bahwa garis tidak boleh ditampilkan di mana pun, tetapi langsung di IDE - tanpa menyimpang dari kode, jadi untuk berbicara. Sebenarnya, ini tentang artikel - bagaimana saya mencoba printf () untuk menampilkan dan menampilkan di dalam favorit saya, tetapi tidak terlalu mikrokontroler, lingkungan Qt Creator.


Secara umum, Anda dapat menemukan sejumlah besar cara untuk menampilkan informasi teks dari mikrokontroler. Namun, teknik yang paling umum digunakan tidak begitu banyak:



Semihosting agak lambat, RTT terkait dengan solusi hardware dan software Segger *, USB tidak ada di setiap mikrokontroler. Karena itu, biasanya, saya lebih suka dua yang terakhir - penggunaan UART dan ITM. Tentang mereka dan akan dibahas di bawah.


* Pembaruan. - sebenarnya, seperti yang disarankan dalam komentar, ini tidak begitu. Ada opsi di sisi perangkat lunak dan perangkat keras. Oleh karena itu, dari metode di atas, RTT mungkin yang paling universal.


Dan segera beberapa penjelasan tentang perangkat lunak yang akan digunakan selanjutnya. Sebagai OS, saya sekarang memiliki Fedora 28, dan bundel perangkat lunak saat ini untuk bekerja dengan mikrokontroler adalah:



Redirect printf () dalam GCC


Jadi, untuk mengarahkan output printf () di GCC, Anda perlu menambahkan kunci tautan


-specs=nosys.specs -specs=nano.specs 

Jika Anda perlu menampilkan angka floating point, maka Anda perlu mengingat kuncinya


 -u_printf_float 

Dan mengimplementasikan fungsi _write (). Misalnya, sesuatu seperti ini


 int _write(int fd, char* ptr, int len) { (void)fd; int i = 0; while (ptr[i] && (i < len)) { retarget_put_char((int)ptr[i]); if (ptr[i] == '\n') { retarget_put_char((int)'\r'); } i++; } return len; } 

di mana retarget_put_char () adalah fungsi yang akan memuat karakter langsung ke antarmuka yang diinginkan.


printf () -> ITM -> Qt Creator


Instrumentasi Trace Macrocell (ITM) adalah blok di dalam inti Cortex-M3 / M4 / M7 yang digunakan untuk menghasilkan berbagai jenis informasi diagnostik non-invasif (melacak). Untuk menerapkan printf () tentang ITM, Anda perlu mengetahui yang berikut:


  • Menggunakan jam TRACECLKIN, yang frekuensinya biasanya sama dengan frekuensi inti
  • Memiliki 32 buah port stimulus yang disebut untuk output data
  • CMSIS menggabungkan fungsi ITM_SendChar (), yang memuat simbol ke port stimulus 0
  • Data adalah output baik melalui bus sinkron (TRACEDATA, TRACECLK) atau melalui jalur SWO kawat tunggal asinkron (TRACESWO)
  • Garis SWO biasanya multiplexing dengan JTDO, yang berarti hanya bekerja dalam mode debug oleh SWD
  • Penarikan oleh SWO dilakukan baik menggunakan kode Manchester atau NRZ (UART 8N1)
  • Data ditransmisikan dalam bingkai format tertentu - Anda memerlukan parser di sisi penerima
  • ITM biasanya dikonfigurasi dari IDE atau utilitas yang sesuai (namun, tidak ada yang melarang pengaturannya dalam kode program - maka output ke SWO akan bekerja tanpa sesi debugging yang ditingkatkan)

Cara yang paling nyaman untuk menggunakan ITM adalah untuk menghasilkan melalui SWO menggunakan pengkodean NRZ - dengan demikian, Anda hanya perlu satu baris, dan akan mungkin untuk menerima data tidak hanya menggunakan debugger dengan input khusus, tetapi juga adaptor USB-UART biasa, meskipun pada kecepatan yang lebih rendah.


Saya mengikuti jalan menggunakan debugger, dan terpaksa memodifikasi STLink-V2 bahasa Mandarin saya untuk mendukung SWO. Kemudian semuanya sederhana - kita menghubungkan mikrokontroler JTDO / TRACESWO ke pin debugger yang sesuai, dan pergi untuk mengkonfigurasi perangkat lunak.


Openocd memiliki perintah "tpiu config" - dengan itu Anda dapat mengkonfigurasi metode untuk menampilkan informasi jejak (lebih detail dalam Panduan Pengguna OpenOCD ). Jadi misalnya menggunakan argumen


 tpiu config internal /home/esynr3z/itm.fifo uart off 168000000 

konfigurasikan output ke file /home/esynr3z/itm.fifo, gunakan enkode NRZ, dan hitung kecepatan transfer maksimum berdasarkan frekuensi TRACECLKIN dari 168 MHz - untuk STLink itu adalah 2 MHz. Dan tim lain


 itm port 0 1 

akan mengaktifkan port nol untuk transfer data.


Kode sumber OpenOCD menyertakan utilitas itmdump (contrib / itmdump.c) - dengan itu Anda dapat mengurai string dari data yang diterima.


Untuk mengkompilasi kita masuk


 gcc itmdump.c -o itmdump 

Saat startup, tentukan file / pipa / ttyUSB * dan -d1 yang diperlukan untuk menampilkan byte data yang diterima sebagai string


 ./itmdump -f /home/esynr3z/itm.fifo -d1 

Dan yang terakhir. Untuk mengirim karakter melalui SWO, kami melengkapi _write (), yang dijelaskan di atas, dengan sebuah fungsi


 int retarget_put_char(int ch) { ITM_SendChar((uint32_t)ch); return 0; } 

Jadi, rencana umumnya adalah ini: di dalam Qt Creator, kami mengonfigurasi openocd untuk menyimpan semua informasi yang diterima di SWO ke pipa bernama yang dibuat sebelumnya, dan kita dapat membaca pipa, string parse dan menampilkannya menggunakan itmdump, yang berjalan sebagai Alat Eksternal. Tentu saja, ada cara yang lebih elegan untuk menyelesaikan masalah - menulis plug-in yang sesuai untuk Qt Creator. Namun, saya berharap pendekatan yang dijelaskan di bawah ini bermanfaat bagi seseorang.


Pergi ke pengaturan plugin Bare Metal (Tools-> Options-> Devices-> Bare Metal).


config_baremetal.png


Pilih server GDB yang digunakan dan tambahkan perintah inisialisasi baris ke akhir daftar


 monitor tpiu config internal /home/esynr3z/itm.fifo uart off 168000000 monitor itm port 0 1 

Sekarang, tepat sebelum debugger menempatkan kursor di awal main (), ITM akan dikonfigurasikan.


Tambahkan itmdump sebagai Alat Eksternal (Tools-> External-> Configure ...).


external_itmdump.png


Jangan lupa atur variabelnya


 QT_LOGGING_TO_CONSOLE=1 

untuk menampilkan output utilitas ke konsol Qt Creator (panel 7 Pesan Umum).


Sekarang nyalakan itmdump, aktifkan mode debug, mulai eksekusi kode dan ... tidak ada yang terjadi. Namun, jika Anda menghentikan debugging, eksekusi itmdump akan berakhir, dan semua baris yang dicetak melalui printf () akan muncul pada tab Pesan Umum.


Setelah penelitian singkat ditemukan bahwa garis-garis dari itmdump harus di-buffer dan ditampilkan di stderr - kemudian muncul di konsol secara interaktif, saat debugging program. Saya mengunggah versi modifikasi itmdump ke GitHub .


Ada satu peringatan lagi. Debug pada saat startup akan tergantung pada pelaksanaan perintah "monitor tpiu config ..." jika itmdump tidak dijalankan sebelumnya. Ini terjadi karena fakta bahwa membuka pipa (/home/esynr3z/itm.fifo) di dalam openocd untuk penulisan memblokir, dan debugger akan menggantung sampai pipa terbuka untuk membaca dari ujung lainnya.


Ini agak tidak menyenangkan, terutama jika pada beberapa titik ITM tidak diperlukan, tetapi Anda harus menjalankannya dengan bermalas-malasan, baik terus-menerus mengganti server GDB atau menghapus / menambah baris dalam pengaturannya. Oleh karena itu, saya harus menggali sedikit sumber openocd dan menemukan tempat di mana Anda perlu mengganti kruk kecil.


Dalam file src / target / armv7m_trace.c ada garis dengan prosedur pembukaan yang diinginkan


 armv7m->trace_config.trace_file = fopen(CMD_ARGV[cmd_idx], "ab"); 

itu perlu diganti oleh


 int fd = open(CMD_ARGV[cmd_idx], O_CREAT | O_RDWR, 0664); armv7m->trace_config.trace_file = fdopen(fd, "ab"); 

Sekarang pipa kami akan segera terbuka dan tidak bersinar. Jadi Anda dapat meninggalkan pengaturan Bare Metal sendirian, dan itmdump hanya berjalan saat diperlukan.


Akibatnya, output pesan selama debugging terlihat seperti ini


debug.png


printf () -> UART -> Qt Creator


Dalam hal ini, semuanya kira-kira sama:


  • Tambahkan fungsi dengan inisialisasi UART ke kode
  • Kami menerapkan retarget_put_char (), di mana karakter akan dikirim ke buffer transceiver
  • Kami menghubungkan adaptor USB-UART
  • Tambahkan utilitas ke Alat Eksternal yang akan membaca baris dari port COM virtual dan menampilkannya di layar.

Saya membuat sketsa utilitas seperti itu di C - uartdump . Penggunaannya cukup sederhana - Anda hanya perlu menentukan nama port dan baudrate.


external_uartdump.png


Namun, perlu diperhatikan satu fitur. Utilitas ini tidak bergantung pada debugging, dan Qt Creator tidak menawarkan opsi apa pun untuk menutup menjalankan Alat Eksternal. Oleh karena itu, untuk berhenti membaca port COM, saya menambahkan alat eksternal lain.


external_uartdump_close.png


Nah, untuk berjaga-jaga, saya akan melampirkan tautan ke templat CMake untuk proyek yang muncul di tangkapan layar - GitHub .

Source: https://habr.com/ru/post/id440024/


All Articles