Seluruh kebenaran tentang RTOS. Artikel # 31. Diagnostik dan pengecekan kesalahan RTOS



Penanganan kesalahan bukanlah hal yang paling umum untuk sistem operasi yang dirancang untuk aplikasi sistem tertanam. Ini adalah hasil dari sumber daya yang terbatas, karena semua sistem yang tertanam memiliki batasan tertentu. Dan hanya sejumlah kecil sistem yang memiliki kemampuan untuk berperilaku seperti sistem desktop, yaitu, menawarkan kepada pengguna kemampuan untuk memilih tindakan jika terjadi peristiwa luar biasa.

Dalam Nucleus SE, secara umum, ada tiga jenis pemeriksaan kesalahan:
  • sarana untuk memverifikasi kesehatan konfigurasi yang dipilih untuk memastikan bahwa parameter yang dipilih tidak mengarah pada kesalahan;
  • secara opsional menyertakan kode untuk memeriksa perilaku runtime;
  • Fungsi API tertentu yang berkontribusi pada pengembangan kode yang lebih kuat.

Semua ini akan dibahas dalam artikel ini, bersama dengan beberapa ide mengenai diagnostik oleh pengguna.

Artikel sebelumnya dalam seri:


Verifikasi Pengaturan


Nucleus SE dirancang dengan fokus pada konfigurasi pengguna yang tinggi, yang harus memastikan penggunaan terbaik sumber daya yang tersedia. Konfigurasi seperti itu adalah tugas yang kompleks, karena jumlah parameter yang mungkin dan saling ketergantungan di antara mereka sangat besar. Seperti yang dinyatakan dalam banyak artikel sebelumnya, sebagian besar langkah pengguna untuk mengkonfigurasi Nucleus SE dilakukan menggunakan arahan #define dalam file nuse_config.h .

Untuk membantu mengidentifikasi kesalahan konfigurasi, file nuse_config.c melalui #include menyertakan file nuse_config_check.h , yang melakukan pemeriksaan integritas pada arahan #define . Berikut ini cuplikan dari file ini:
/*** Tasks and task control ***/ #if NUSE_TASK_NUMBER < 1 || NUSE_TASK_NUMBER > 16 #error NUSE: invalid number of tasks - must be 1-16 #endif #if NUSE_TASK_RELINQUISH && (NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER) #error NUSE: NUSE_Task_Relinquish() selected - not valid with priority scheduler #endif #if NUSE_TASK_RESUME && !NUSE_SUSPEND_ENABLE #error NUSE: NUSE_Task_Resume() selected - task suspend not enabled #endif #if NUSE_TASK_SUSPEND && !NUSE_SUSPEND_ENABLE #error NUSE: NUSE_Task_Suspend() selected - task suspend not enabled #endif #if NUSE_INITIAL_TASK_STATE_SUPPORT && !NUSE_SUSPEND_ENABLE #error NUSE: Initial task state enabled - task suspend not enabled #endif /*** Partition pools ***/ #if NUSE_PARTITION_POOL_NUMBER > 16 #error NUSE: invalid number of partition pools - must be 0-16 #endif #if NUSE_PARTITION_POOL_NUMBER == 0 #if NUSE_PARTITION_ALLOCATE #error NUSE: NUSE_Partition_Allocate() enabled – no partition pools configured #endif #if NUSE_PARTITION_DEALLOCATE #error NUSE: NUSE_Partition_Deallocate() enabled – no partition pools configured #endif #if NUSE_PARTITION_POOL_INFORMATION #error NUSE: NUSE_Partition_Pool_Information() enabled – no partition pools configured #endif #endif 

Kode di atas melakukan pemeriksaan berikut:
  • periksa setidaknya satu, tetapi tidak lebih dari enam belas tugas yang dikonfigurasikan;
  • Konfirmasi bahwa fungsi API yang dipilih kompatibel dengan penjadwal yang dipilih dan parameter tertentu lainnya;
  • verifikasi bahwa tidak lebih dari enam belas contoh objek kernel lain dibuat;
  • Konfirmasi bahwa fungsi API yang terkait dengan objek yang tidak dideklarasikan belum dipilih.
  • memastikan bahwa fungsi API untuk sinyal dan waktu sistem tidak digunakan ketika dukungan untuk layanan ini dinonaktifkan;
  • verifikasi jenis penjadwal yang dipilih dan parameter terkait.

Dalam semua kasus, deteksi kesalahan mengarah ke pelaksanaan arahan #error saat kompilasi. Ini biasanya menyebabkan kompilasi berhenti dan menampilkan pesan yang sesuai.

File ini tidak menjamin ketidakmungkinan membuat konfigurasi / konfigurasi yang salah, tetapi membuatnya sangat tidak mungkin.

Memeriksa Pengaturan API


Seperti Nucleus RTOS, Nucleus SE memiliki kemampuan untuk memasukkan kode untuk memeriksa parameter fungsi panggilan API saat runtime. Biasanya ini hanya digunakan selama debugging awal dan pengujian, karena dalam kode program akhir konsumsi memori yang berlebihan tidak diinginkan.

Pemeriksaan parameter diaktifkan dengan mengatur parameter NUSE_API_PARAMETER_CHECKING dalam file nuse_config.h ke TRUE . Ini mengarah pada kompilasi dari kode tambahan yang diperlukan. Berikut ini adalah contoh memeriksa parameter fungsi API:
 STATUS NUSE_Mailbox_Send(NUSE_MAILBOX mailbox, ADDR *message, U8 suspend) { STATUS return_value; #if NUSE_API_PARAMETER_CHECKING if (mailbox >= NUSE_MAILBOX_NUMBER) { return NUSE_INVALID_MAILBOX; } if (message == NULL) { return NUSE_INVALID_POINTER; } #if NUSE_BLOCKING_ENABLE if ((suspend != NUSE_NO_SUSPEND) && (suspend != NUSE_SUSPEND)) { return NUSE_INVALID_SUSPEND; } #else if (suspend != NUSE_NO_SUSPEND) { return NUSE_INVALID_SUSPEND; } #endif #endif 

Pemeriksaan parameter semacam itu dapat mengarah pada fakta bahwa panggilan API akan menampilkan kode kesalahan. Ini adalah nilai negatif dari formulir NUSE_INVALID_xxx (misalnya, NUSE_INVALID_POINTER ) - satu set definisi lengkap terkandung dalam file nuse_codes.h .

Untuk memproses nilai-nilai kesalahan, kode aplikasi tambahan (mungkin dibuat menggunakan kompilasi bersyarat) dapat ditambahkan, namun, untuk mendeteksinya, lebih baik menggunakan alat pemantauan dari data para penentang firmware modern.

Memeriksa parameter mengarah pada konsumsi memori tambahan (kode tambahan) dan memengaruhi kinerja kode, oleh karena itu, penggunaannya akan memengaruhi keseluruhan sistem. Karena seluruh kode sumber Nucleus SE tersedia untuk pengembang, verifikasi dan debugging dapat dilakukan secara manual pada kode aplikasi akhir jika akurasi mutlak diperlukan.

Memeriksa tumpukan tugas


Sampai Run to Completion Scheduler digunakan, Nucleus SE menyediakan kemampuan untuk memeriksa tumpukan tugas, yang mirip dengan fungsi serupa di Nucleus RTOS dan menunjukkan ruang yang tersisa di tumpukan. Panggilan utilitas API ini ( NUSE_Task_Check_Stack () ) dijelaskan secara rinci dalam artikel sebelumnya (# 12). Beberapa ide untuk memeriksa kesalahan tumpukan disediakan nanti di artikel ini di bagian Custom Diagnostics.

Informasi Versi


Nucleus RTOS dan Nucleus SE memiliki fungsi API yang hanya mengembalikan versi kernel / membangun informasi.

Panggilan API RTOS Nucleus


Prototipe panggilan layanan:
CHAR * NU_Release_Information (VOID);

Parameter: tidak ada.

Nilai pengembalian:
Pointer ke string yang berisi informasi versi yang diakhiri dengan byte nol.

Nucleus SE API Call


Panggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.

Prototipe panggilan layanan:
char * NUSE_Release_Information (void);

Parameter: tidak ada.

Nilai pengembalian:
Pointer ke string yang berisi informasi versi yang diakhiri dengan byte nol.

Melakukan panggilan untuk mendapatkan informasi perakitan Nucleus SE


Menerapkan panggilan API ini cukup sederhana. Pointer dikembalikan ke baris konstan NUSE_Release_Info , yang dideklarasikan dan diinisialisasi dalam file nuse_globals.c .

Baris ini memiliki bentuk Nucleus SE - Xyymmmdd , di mana:
Status X -build: A = alpha; B = beta; R = rilis
yy - tahun rilis
mm - bulan rilis
dd - hari rilis

Kompatibel dengan RTOS Inti


Nucleus RTOS berisi dukungan majalah sejarah opsional. Kernel mencatat detail berbagai tindakan sistem. Ada fungsi API yang memungkinkan program untuk:
  • aktifkan / nonaktifkan logging;
  • buat entri jurnal;
  • Dapatkan entri jurnal.

Fitur ini tidak didukung di Nucleus SE.

Nucleus RTOS juga memiliki beberapa makro manajemen kesalahan yang memungkinkan Anda untuk melakukan konfirmasi kesalahan (ASSERT) dan memberikan kemampuan untuk memanggil fungsi kesalahan kritis yang ditentukan pengguna. Mereka secara opsional termasuk dalam rakitan OS. Nucleus SE tidak mendukung fungsi ini.

Diagnostik Pengguna


Sejauh ini dalam artikel ini, kita telah melihat alat diagnostik dan pengecekan kesalahan yang disediakan oleh Nucleus SE itu sendiri. Sekarang perlu diceritakan bagaimana alat diagnostik yang ditetapkan oleh pengguna atau berorientasi pada aplikasi tertentu dapat diimplementasikan menggunakan alat yang disediakan oleh kernel dan / atau pengetahuan kita tentang struktur internal dan implementasinya

Diagnostik khusus aplikasi


Di hampir setiap aplikasi, Anda dapat menambahkan kode tambahan untuk memverifikasi integritasnya saat runtime. Inti multitasking memudahkan dan sederhana untuk membuat tugas khusus untuk pekerjaan ini. Jelas, dalam artikel ini kami tidak akan mempertimbangkan kasus diagnosis yang terlalu tidak biasa, tetapi mempertimbangkan beberapa ide umum.

Pemeriksaan memori


Jelas, operasi memori yang tepat sangat penting untuk integritas sistem prosesor apa pun. Tidak kurang jelas bahwa kesalahan kritis tidak akan memungkinkan Anda untuk menjalankan, tidak hanya diagnosa, tetapi seluruh produk perangkat lunak secara keseluruhan ( catatan penerjemah: Omong-omong, ini persis kasus yang kami teliti dalam artikel "Pil Biru Palsu" ). Namun, ada situasi ketika kesalahan tertentu muncul, yang merupakan penyebab serius yang perlu diperhatikan, tetapi tidak mengganggu eksekusi kode. Pengujian memori adalah topik yang agak rumit yang berada di luar cakupan artikel ini, jadi saya hanya akan memberikan beberapa gagasan umum.

Dua kesalahan paling umum yang terjadi pada RAM adalah:
  • "Sticky bits" ketika bit memiliki nilai 0 atau 1, yang tidak dapat diubah;
  • "Crosstalk" ketika bit yang berdekatan menyebabkan gangguan satu sama lain.

Kedua kesalahan dapat diperiksa dengan menulis dan membaca pola pengujian tertentu untuk setiap area RAM secara bergantian. Beberapa pemeriksaan dapat dilakukan hanya pada saat startup, bahkan sebelum stack terbentuk ( catatan penerjemah: dalam artikel yang disebutkan di atas ternyata itu adalah penggunaan pertama dari stack yang menghancurkan semuanya sekaligus ). Misalnya, "unit yang berjalan" memeriksa, di mana setiap bit memori diberi nilai satu, dan semua bit lainnya diperiksa untuk memastikan bahwa mereka sama dengan nol. Pola pengujian bitwise lainnya dapat dilakukan selama operasi, asalkan saat area RAM rusak, pengalihan konteks tidak akan terjadi. Menggunakan makro pembatasan bagian kritis Nucleus SE NUSE_CS_Enter () dan NUSE_CS_Exit () cukup sederhana dan dapat diskalakan.

Berbagai jenis ROM juga rentan terhadap kesalahan berkala, tetapi tidak ada banyak alat untuk memeriksanya. Sebuah checksum yang dihitung setelah kode telah dikumpulkan dapat berguna di sini. Pemeriksaan ini dapat dilakukan saat boot, dan mungkin saat runtime.

Kesalahan dalam logika pengalamatan memori dapat memengaruhi ROM dan RAM. Anda dapat mengembangkan pemeriksaan khusus untuk kesalahan ini, tetapi kemungkinan besar akan terdeteksi sebagai bagian dari pemeriksaan yang dijelaskan di atas.

Menguji Periferal


Selain CPU, sirkuit periferal juga dapat rawan kesalahan. Tentu saja, ini sangat bervariasi dari satu sistem ke sistem lainnya, namun di sebagian besar perangkat ada berbagai cara untuk memeriksa integritasnya menggunakan perangkat lunak diagnostik. Misalnya, saluran komunikasi mungkin memiliki mode verifikasi loopback di mana setiap data yang masuk ke saluran segera dikembalikan.

Layanan Watchdog


Pengembang yang disematkan sering menggunakan anjing penjaga. Ini adalah perangkat periferal yang mengganggu CPU dan menunggu respons, atau (lebih disukai) memerlukan akses berkala dari perangkat lunak. Dalam kedua kasus, hasil umum dari pengawas waktu adalah reset sistem.

Penggunaan pengawas yang efektif di lingkungan multitasking adalah masalah yang kompleks. Jika Anda membuat tugas yang secara berkala mengaksesnya (pengawas waktu), itu akan mengkonfirmasi bahwa tugas khusus ini berfungsi. Sebuah solusi yang mungkin bisa menjadi implementasi dari "tugas operator". Contoh dari tugas semacam itu akan diberikan di bawah ini.

Stack overflow check


Jika Anda tidak menggunakan Run to Completion Scheduler, tumpukan akan dibuat untuk setiap tugas dalam aplikasi Nucleus SE. Integritas tumpukan ini sangat penting, tetapi jumlah RAM cenderung terbatas, oleh karena itu, penting untuk membuat ukuran aplikasi optimal. Memprediksi secara statis persyaratan untuk tumpukan setiap tugas dimungkinkan, tetapi sangat sulit. Tumpukan harus cukup besar bahkan untuk fungsi yang paling bersarang, bersama dengan pengendali interrupt yang paling menuntut. Pendekatan yang lebih sederhana untuk menyelesaikan masalah ini adalah dengan menggunakan pengujian runtime lengkap.

Secara umum, ada dua pendekatan untuk menumpuk verifikasi. Jika Anda menggunakan debugger perangkat lunak tertanam yang canggih, batas-batas tumpukan dapat dimonitor dan semua pelanggaran akan terdeteksi. Lokasi dan ukuran tumpukan Nucleus SE tersedia dalam struktur data ROM global: NUSE_Task_Stack_Base [] dan NUSE_Task_Stack_Size [] .

Alternatif adalah pengujian runtime. Pendekatan umum adalah dengan menggunakan "kata-kata penjaga" di akhir setiap tumpukan, biasanya elemen pertama dari setiap area data tumpukan. Kata-kata ini diinisialisasi dengan nilai bukan nol yang dikenali. Tugas layanan / diagnostik kemudian memeriksa untuk melihat apakah kata-kata ini telah berubah, dan melakukan tindakan yang sesuai. Menghancurkan kata keamanan tidak berarti bahwa tumpukan sudah penuh, tetapi menunjukkan bahwa ini akan terjadi. Oleh karena itu, perangkat lunak dapat terus berfungsi, Anda mungkin perlu mengambil tindakan korektif atau melaporkan kesalahan kepada pengguna.

Tugas Pengawas


Terlepas dari kenyataan bahwa Nucleus SE tidak menyimpan salah satu dari enam belas tugas yang mungkin untuk kebutuhannya sendiri, pengguna dapat memilih satu tugas untuk diagnostik. Ini bisa menjadi tugas dengan prioritas rendah yang hanya menggunakan waktu prosesor "bebas", atau bisa menjadi tugas dengan prioritas tinggi yang berjalan secara berkala, mengambil periode waktu singkat, yang memastikan bahwa diagnostik dilakukan secara teratur.

Berikut ini adalah contoh bagaimana tugas serupa mungkin bekerja.

Bendera sinyal dari tugas dispatcher digunakan untuk melacak operasi enam tugas sistem kritis. Masing-masing tugas ini menggunakan flag tertentu (dari bit 0 ke bit 5) dan harus ditetapkan secara teratur. Tugas operator ulang semua bendera, dan kemudian berhenti pekerjaannya untuk jangka waktu tertentu. Ketika dia melanjutkan kembali pekerjaannya, dia berharap bahwa keenam tugas tersebut "diperiksa" dengan mengatur bendera yang sesuai, kemudian dia mencari kecocokan yang tepat dengan nilai b00111111 (dari file nuse_binary.h ). Jika semuanya memenuhi persyaratan, itu akan mengatur ulang bendera dan berhenti lagi. Jika tidak, ini disebut rutin penanganan kesalahan kritis, yang pada gilirannya dapat, misalnya, reboot sistem.

Dalam implementasi alternatif, kelompok bendera acara dapat digunakan. Ini masuk akal jika sinyal tidak digunakan di tempat lain dalam aplikasi (jika tidak, ini akan menyebabkan penggunaan RAM yang berlebihan oleh semua tugas) dan terutama jika flag event digunakan untuk tujuan lain.

Menelusuri dan membuat profil


Terlepas dari kenyataan bahwa banyak debugger perangkat lunak tertanam modern memiliki tingkat penyesuaian yang tinggi dan dapat digunakan untuk bekerja dengan RTOS, men-debug aplikasi multi-utas masih sulit. Pendekatan yang banyak digunakan adalah profil pasca-eksekusi, di mana kode (RTOS) diimplementasikan sehingga audit rinci pekerjaannya dapat dianalisis dalam retrospeksi. Biasanya, implementasi layanan seperti itu mencakup dua komponen:
  1. Kode tambahan ditambahkan ke RTOS untuk mencatat tindakan. Biasanya, itu akan dibungkus dalam arahan preprocessor untuk menggunakan kompilasi bersyarat. Kode ini merekam beberapa byte informasi ketika peristiwa penting terjadi (misalnya, memanggil fungsi API atau mengalihkan konteks). Informasi tersebut dapat meliputi:
    • alamat saat ini (PC);
    • ID tugas saat ini (indeks);
    • indeks benda bekas lainnya;
    • kode yang sesuai dengan operasi yang dilakukan.

  2. Tugas yang dialokasikan untuk menurunkan buffer informasi profil ke penyimpanan eksternal, biasanya ke komputer host.

Analisis data yang diperoleh juga membutuhkan beberapa pekerjaan, tetapi tidak lebih rumit daripada menggunakan lembar kerja Excel biasa.

Pada artikel berikutnya, kita akan memeriksa secara rinci kompatibilitas Nucleus SE dan Nucleus RTOS.

Tentang Pengarang: Colin Walls telah bekerja di industri elektronik selama lebih dari tiga puluh tahun, mencurahkan sebagian besar waktunya untuk firmware. Dia sekarang adalah seorang insinyur firmware di Mentor Embedded (sebuah divisi dari Mentor Graphics). Colin Walls sering berbicara di konferensi dan seminar, penulis berbagai artikel teknis dan dua buku tentang firmware. Tinggal di Inggris. Blog profesional Colin , email: colin_walls@mentor.com.

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


All Articles