Seluruh kebenaran tentang RTOS. Artikel # 16. Sinyal



Artikel ini akan melihat sinyal, yang merupakan mekanisme interaksi paling sederhana antara tugas-tugas di Nucleus SE. Mereka menyediakan cara murah untuk mentransfer pesan sederhana antar tugas.


Artikel sebelumnya dalam seri:
Artikel # 15. Partisi Memori: Layanan dan Struktur Data
Artikel # 14. Bagian memori: pengantar dan layanan dasar
Artikel # 13. Struktur data tugas dan panggilan API yang tidak didukung
Artikel # 12. Layanan untuk bekerja dengan tugas
Artikel # 11. Tugas: konfigurasi dan pengantar API
Artikel # 10. Penjadwal: fitur canggih dan pelestarian konteks
Artikel # 9. Penjadwal: implementasi
Artikel # 8. Nucleus SE: Desain dan Penyebaran Internal
Artikel # 7. Nucleus SE: Pendahuluan
Artikel # 6. Layanan RTOS lainnya
Artikel # 5. Interaksi tugas dan sinkronisasi
Artikel # 4. Tugas, pengalihan konteks, dan interupsi
Artikel # 3. Tugas dan Perencanaan
Artikel # 2. RTOS: Struktur dan mode waktu-nyata
Artikel # 1. RTOS: pengantar.

Menggunakan sinyal


Sinyal berbeda dari semua jenis objek kernel lainnya karena tidak otonom: sinyal dikaitkan dengan tugas dan tidak dapat ada tanpa itu. Jika aplikasi dikonfigurasi untuk menggunakan sinyal, maka setiap tugas memiliki satu set delapan tanda sinyal.

Tugas apa pun dapat mengatur sinyal untuk tugas lain. Sinyal hanya dapat dibaca oleh pemilik sinyal. Saat membaca, sinyal diset ulang. Tugas tidak dapat membaca atau mengatur ulang sinyal dari tugas lain.

Nucleus RTOS memiliki alat yang memungkinkan tugas untuk menetapkan fungsi yang berjalan ketika tugas lain menetapkan satu atau lebih tanda sinyal. Ini agak mengingatkan pada rutinitas interupsi. Fitur ini tidak didukung di Nucleus SE; di sini, tugas harus meminta tanda sinyal secara eksplisit.

Pengaturan sinyal


Seperti kebanyakan objek Nucleus SE, penyetelan sinyal ditentukan oleh arahan #define di nuse_config.h . Parameter utama adalah NUSE_SIGNAL_SUPPORT , yang mengaktifkan dukungan fungsionalitas (untuk semua tugas dalam aplikasi). Pertanyaan menunjukkan jumlah sinyal tidak layak: 8 flag dialokasikan untuk setiap tugas.

Pengaturan ini memungkinkan parameter berfungsi sebagai penggerak sinyal utama. Ini memberikan struktur data yang jelas memiliki ukuran yang sesuai. Selain itu, opsi ini mengaktifkan pengaturan API.

Aktifkan Panggilan API


Setiap fungsi API (panggilan utilitas) di Nucleus SE diaktifkan oleh arahan #define di nuse_config.h . Untuk sinyal, ini termasuk:

NUSE_SIGNALS_SEND NUSE_SIGNALS_RECEIVE 

Secara default, mereka diatur ke FALSE , sehingga menonaktifkan setiap panggilan layanan dan mencegah kode yang mengaktifkannya diaktifkan. Untuk mengkonfigurasi sinyal dalam aplikasi, Anda harus memilih panggilan API yang diperlukan dan mengatur arahan yang sesuai ke TRUE .

Berikut ini adalah kutipan dari file nuse_config.h default:

 #define NUSE_SIGNAL_SUPPORT FALSE /* Enables support for signals */ #define NUSE_SIGNALS_SEND FALSE /* Service call enabler */ #define NUSE_SIGNALS_RECEIVE FALSE /* Service call enabler */ 

Fungsi API yang diaktifkan dengan dukungan pensinyalan dimatikan akan menghasilkan kesalahan kompilasi. Jika kode Anda menggunakan panggilan API yang belum diaktifkan, kesalahan tata letak akan terjadi karena kode implementasi tidak termasuk dalam aplikasi. Tentu saja, penyertaan dua fungsi API agak tidak perlu, karena tidak ada gunanya mengaktifkan dukungan sinyal tanpa adanya API ini. Aktivator telah ditambahkan untuk kompatibilitas dengan fitur Nucleus SE lainnya.

Sinyal Panggilan


Nucleus RTOS mendukung empat panggilan overhead terkait-sinyal yang menyediakan fungsionalitas berikut:

  • Mengirim sinyal ke tugas yang diberikan. Nucleus SE diimplementasikan dalam fungsi NUSE_Signals_Send () .
  • Penerimaan sinyal. Nucleus SE diimplementasikan dalam fungsi NUSE_Signals_Receive () .
  • Registrasi pengendali sinyal. Tidak diterapkan di Nucleus SE.
  • Menghidupkan / mematikan sinyal (kontrol). Tidak diterapkan di Nucleus SE.

Implementasi dari masing-masing tantangan ini dibahas secara rinci di bawah ini.

Memberi sinyal dan menerima layanan


Operasi mendasar yang dapat dilakukan pada satu set sinyal tugas adalah mengirim data (dapat dilakukan oleh tugas apa pun) dan membaca data (karenanya, membersihkan data hanya dapat dilakukan oleh tugas pemilik). Nucleus RTOS dan Nucleus SE menyediakan dua panggilan API dasar untuk operasi ini, yang akan dijelaskan di bawah ini.

Karena sinyal adalah bit, mereka divisualisasikan sebagai angka biner. Karena standar C secara historis tidak mendukung representasi konstanta biner (hanya oktal dan heksadesimal), Nucleus SE memiliki file header yang bermanfaat nuse_binary.h yang berisi karakter #define seperti b01010101 untuk semua 256 nilai 8-bit. Berikut ini adalah kutipan dari file nuse_binary.h :

 #define b00000000 ((U8) 0x00) #define b00000001 ((U8) 0x01) #define b00000010 ((U8) 0x02) #define b00000011 ((U8) 0x03) #define b00000100 ((U8) 0x04) #define b00000101 ((U8) 0x05) 

Mengirim sinyal


Tugas apa pun dapat mengirim sinyal ke tugas lain dalam aplikasi. Mengirim sinyal melibatkan pengaturan satu atau beberapa flag sinyal. Ini adalah operasi ATAU yang tidak memengaruhi flag yang ditetapkan sebelumnya.

Panggilan untuk mengirim sinyal ke Nucleus RTOS
Prototipe panggilan layanan:
STATUS NU_Send_Signals (tugas NU_TASK *, sinyal TANDA TANGAN);

Parameter:

penunjuk tugas - ke unit kendali tugas di mana bendera sinyal yang ditetapkan berada;
sinyal - nilai flag sinyal yang ditetapkan.

Nilai pengembalian:

NU_SUCCESS - panggilan berhasil diselesaikan;
NU_INVALID_TASK - penunjuk tidak valid untuk tugas;

Panggilan untuk mengirim sinyal ke Nucleus SE
Panggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.

Prototipe panggilan layanan:

STATUS_NUSE_Signals_Send (Tugas NUSE_TASK, sinyal U8);

Parameter:

task - index (ID) dari tugas yang dimiliki flag sinyal yang ditetapkan;
sinyal - nilai flag sinyal yang ditetapkan.

Nilai pengembalian:

NUSE_SUCCESS - panggilan layanan berhasil diselesaikan;
NUSE_INVALID_TASK - indeks tugas tidak valid.

Menerapkan Signaling di Nucleus SE
Di bawah ini adalah kode lengkap untuk fungsi NUSE_Signals_Send ():

 STATUS NUSE_Signals_Send(NUSE_TASK task, U8 signals) { #if NUSE_API_PARAMETER_CHECKING if (task >= NUSE_TASK_NUMBER) { return NUSE_INVALID_TASK; } #endif NUSE_CS_Enter(); NUSE_Task_Signal_Flags[task] |= signals; NUSE_CS_Exit(); return NUSE_SUCCESS; } 

Kode ini sangat sederhana. Setelah setiap verifikasi parameter, nilai sinyal melewati operasi ATAU pada bendera sinyal dari tugas yang ditentukan. Mengunci tugas tidak mempengaruhi sinyal.

Menerima sinyal


Suatu tugas hanya dapat membaca set flag sinyalnya sendiri. Saat membaca, nilai-nilai bendera diatur ulang.

Panggilan untuk menerima sinyal dalam Nucleus RTOS
Prototipe panggilan layanan:
NU_Receive_Signals (VOID) TIDAK DITANDATANGANI;

Parameter: tidak ada.

Nilai pengembalian:
Nilai bendera sinyal.

Panggilan untuk menerima sinyal dalam Nucleus SE
Panggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.

Prototipe panggilan layanan:
U8 NUSE_Signals_Receive (void);

Parameter: tidak ada.

Nilai pengembalian:
Nilai bendera sinyal.

Implementasi Penerimaan Sinyal Inti N
Berikut ini adalah kode lengkap untuk fungsi NUSE_Signals_Receive () :

 U8 NUSE_Signals_Receive(void) { U8 signals; NUSE_CS_Enter(); Signals = NUSE_Task_Signal_Flags[NUSE_Task_Active]; NUSE_Task_Signal_Flags[NUSE_Task_Active] = 0; NUSE_CS_Exit(); return signals; } 

Kode ini sangat sederhana. Nilai bendera disalin, nilai awal diatur ulang, dan salinan dikembalikan oleh fungsi API. Mengunci tugas tidak mempengaruhi sinyal.

Struktur data


Karena sinyal bukan objek independen, penggunaan memori tergantung pada tugas yang menjadi tanggung jawabnya. Di bawah ini adalah beberapa informasi untuk pemahaman lengkap. Sinyal menggunakan satu struktur data (dalam RAM), yang, seperti objek Nucleus SE lainnya, adalah tabel yang dimensinya sesuai dengan jumlah tugas dalam aplikasi. Struktur data ini hanya digunakan jika dukungan sinyal diaktifkan.

Saya sangat merekomendasikan bahwa kode aplikasi tidak mengakses struktur data ini secara langsung, tetapi menggunakan fungsi API yang tersedia. Ini menghindari ketidakcocokan dengan versi Nucleus SE di masa depan, efek samping yang tidak diinginkan, dan juga menyederhanakan porting aplikasi ke Nucleus RTOS. Struktur data dibahas secara rinci di bawah ini untuk menyederhanakan pemahaman panggilan layanan dan prinsip-prinsip debugging.

Struktur data ditempatkan dalam RAM


Struktur data:
NUSE_Task_Signal_Flags [] - larik tipe U8 dengan satu entri untuk setiap tugas yang dikonfigurasi, bendera sinyal disimpan dalam larik ini.

Struktur data ini diinisialisasi ke nol oleh fungsi NUSE_Init_Task () saat memuat Nucleus SE.

Struktur data ditempatkan di ROM


Sinyal tidak memiliki struktur data dalam ROM.

Jumlah memori untuk menyimpan data sinyal


Seperti dengan semua objek inti Nucleus SE, jumlah memori yang diperlukan untuk sinyal dapat diprediksi.

Jumlah data dalam ROM untuk semua sinyal dalam aplikasi adalah 0.

Jumlah memori untuk menyimpan data dalam RAM (dalam byte) untuk semua sinyal dalam aplikasi sama dengan jumlah tugas yang dikonfigurasi ( NUSE_TASK_NUMBER ). Namun pada kenyataannya, data ini milik tugas dan dijelaskan dalam artikel sebelumnya tentang tugas.

Panggilan API yang belum direalisasi


Dua panggilan pensinyalan Nucleus RTOS API tidak diterapkan di Nucleus SE:

Pendaftaran Pengendali Sinyal


Panggilan API ini mengatur prosedur pemrosesan sinyal (fungsi) untuk tugas saat ini. Nucleus SE tidak memerlukan ini karena penangan sinyal tidak didukung.

Prototipe panggilan layanan:
STATUS NU_Register_Signal_Handler (VOID (* signal_handler) (UNSIGNED));

Parameter:
signal_handler - fungsi yang harus dipanggil saat menerima sinyal

Nilai pengembalian:
NU_SUCCESS - panggilan berhasil diselesaikan;
NU_INVALID_POINTER - pointer nol ke penangan sinyal ( NULL )

Kontrol (aktivasi / deaktivasi) sinyal


Layanan ini mengaktifkan dan / atau menonaktifkan sinyal untuk tugas saat ini. Untuk setiap tugas, 32 sinyal tersedia. Setiap sinyal diwakili oleh sedikit di signal_enable_mask . Menambahkan sedikit ke signal_enable_mask memungkinkan sinyal yang sesuai, dan menghapus sedikit menonaktifkannya.

Prototipe panggilan layanan:
NU_Control_Signals UNSIGNED (UNSIGNED enable_signal_mask);

Parameter:
enable_signal_mask - pola bit yang mewakili sinyal yang benar.

Nilai pengembalian:
Mask untuk mengaktifkan / menonaktifkan sinyal sebelumnya.

Kompatibel dengan RTOS Inti


Ketika mengembangkan Nucleus SE, tujuan saya adalah menjaga level kode agar kompatibel dengan Nucleus RTOS. Sinyal tidak terkecuali, dan, dari sudut pandang pengembang, mereka diimplementasikan dalam banyak cara yang sama seperti di Nucleus RTOS. Ada beberapa ketidakcocokan yang saya anggap valid, mengingat bahwa kode akhir jauh lebih mudah dipahami dan dapat menggunakan memori lebih efisien. Jika tidak, panggilan Nucleus RTOS API hampir dapat ditransfer langsung ke panggilan Nucleus SE.

Penangan sinyal


Dalam Nucleus SE, penangan sinyal tidak diterapkan untuk menyederhanakan struktur keseluruhan.

Ketersediaan dan kuantitas sinyal


Dalam Nucleus RTOS, tugas dapat memiliki 32 tanda sinyal. Di Nucleus SE, saya memutuskan untuk mengurangi jumlah mereka menjadi delapan, karena ini akan cukup untuk aplikasi yang lebih sederhana dan akan menghemat sumber daya RAM. Jika perlu, sinyal dapat dimatikan sepenuhnya.

Panggilan API yang belum direalisasi


Nucleus RTOS mendukung empat panggilan layanan pensinyalan. Dari jumlah tersebut, dua tidak diimplementasikan dalam Nucleus SE. Deskripsi mereka dapat ditemukan di atas di bagian "Panggilan API Tidak Direalisasikan".

Tentang Pengarang: Colin Walls telah bekerja di industri elektronik selama lebih dari tiga puluh tahun, mencurahkan sebagian besar waktunya untuk firmware. Dia sekarang 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/id427439/


All Articles