Antrian di Nucleus SE: Pengantar dan Panggilan Layanan Inti
Lihat seri RTOS Revealed
Antrian diperkenalkan dalam artikel sebelumnya. Mereka menyediakan cara yang lebih fleksibel untuk meneruskan pesan sederhana antar-tugas dibandingkan kotak surat.
Menggunakan Antrian
Di Nucleus SE, antrian dikonfigurasi pada waktu build. Maksimal 16 antrian dapat didefinisikan untuk sebuah aplikasi. Jika tidak ada antrian yang dikonfigurasi, RTOS menghilangkan semua struktur data dan kode API terkait antrian, menjaga biner tetap ramping.
Antrian hanyalah array slot penyimpanan, masing-masing cukup besar untuk menahan satu item data ADDR. Akses disinkronkan sehingga beberapa tugas dapat dengan aman menambahkan dan mengeluarkan pesan. Tugas dapat menulis ke antrian sampai semua slot penuh, dan membaca dari antrian dalam urutan first-in, first-out (FIFO). Upaya untuk mengirim ke antrian penuh atau menerima dari antrian kosong memicu kesalahan atau penangguhan tugas, tergantung pada opsi API yang dipilih dan konfigurasi Nucleus SE.
Antrian vs. Pipa
Nucleus SE juga mendukung pipa, yang terutama berbeda dalam ukuran pesan. Sementara antrian mengirimkan satu ADDR (biasanya pointer), pipa membawa blok byte berukuran variabel; ukuran blok tetap pada waktu konfigurasi. Pipa dibahas secara mendalam dalam artikel mendatang.
Mengonfigurasi Antrian
Jumlah Antrian
Konfigurasi antrian dikendalikan oleh pernyataan #define dalam nuse_config.h. Pengaturan kunci adalah NUSE_QUEUE_NUMBER, yang menentukan berapa banyak antrian yang diaktifkan. Default-nya 0 (tanpa antrian). Anda dapat menyetelnya ke nilai apa pun dari 0 hingga 16; nilai di luar jangkauan memicu #error waktu kompilasi yang dihasilkan oleh nuse_config_check.h.
Mengatur NUSE_QUEUE_NUMBER ke nilai non-nol mengaktifkan subsistem antrian, mengalokasikan struktur data yang diperlukan dan mengaktifkan panggilan API yang terkait.
API Enables
Setiap fungsi API antrian memiliki simbol #define enable dalam nuse_config.h:
Secara default semuanya diatur ke FALSE, menonaktifkan panggilan layanan yang sesuai. Untuk menggunakan API tertentu, setel simbolnya ke TRUE. Mengaktifkan API sementara tidak ada antrian yang dikonfigurasi (kecuali NUSE_Queue_Count(), yang selalu diizinkan) menghasilkan kesalahan waktu kompilasi. Jika API dipanggil dalam kode yang tidak diaktifkan, kesalahan waktu link terjadi karena implementasi dihilangkan.
#define NUSE_QUEUE_NUMBER 0 /* Jumlah antrian dalam sistem – 0-16 */ /* Enabler panggilan layanan */ #define NUSE_QUEUE_SEND FALSE #define NUSE_QUEUE_RECEIVE FALSE #define NUSE_QUEUE_JAM FALSE #define NUSE_QUEUE_RESET FALSE #define NUSE_QUEUE_INFORMATION FALSE #define NUSE_QUEUE_COUNT FALSE
Panggilan Layanan Antrian
Nucleus RTOS menawarkan sepuluh panggilan layanan terkait antrian, dari mana enam diimplementasikan di Nucleus SE. Mereka menyediakan fungsionalitas berikut:
Mengirim pesan – NUSE_Queue_Send()
Menerima pesan – NUSE_Queue_Receive()
Memasukkan pesan ke depan – NUSE_Queue_Jam()
Mengatur ulang antrian – NUSE_Queue_Reset()
Mengkueri informasi antrian – NUSE_Queue_Information()
Memperoleh jumlah antrian yang dikonfigurasi – NUSE_Queue_Count()
Panggilan lainnya (buat, hapus, enumerasi, siaran) tidak tersedia di Nucleus SE.
Implementasi setiap API dibahas secara rinci dalam bagian-bagian berikutnya.
Layanan Tulis dan Baca
Operasi inti pada antrian adalah menulis (mengirim) dan membaca (menerima). Menulis ke depan antrian disebut jamming. Nucleus RTOS dan Nucleus SE masing-masing mengekspos tiga panggilan API dasar untuk tindakan ini.
Menulis ke Antrian
API RTOS NU_Send_To_Queue() sangat fleksibel, memungkinkan penangguhan tak terbatas atau timeout jika antrian penuh. Nucleus SE menawarkan fungsi yang sama tetapi penangguhan opsional dan timeout tidak didukung. RTOS juga mendukung operasi siaran, yang tidak tersedia di SE.
API RTOS: NU_Send_To_Queue()
Prototipe:
STATUS NU_Send_To_Queue(NU_QUEUE *queue, VOID *message, UNSIGNED size, UNSIGNED suspend);
Parameter:
queue – pointer ke blok kontrol antrian yang disediakan pengguna
message – pointer ke data yang akan dikirim
size – jumlah elemen UNSIGNED; harus cocok dengan ukuran pesan antrian
suspend – NU_NO_SUSPEND, NU_SUSPEND, atau nilai timeout
Kode pengembalian termasuk NU_SUCCESS, NU_QUEUE_FULL, NU_TIMEOUT, dan berbagai kode kesalahan untuk pointer atau status antrian yang tidak valid.
API SE: NUSE_Queue_Send()
Prototipe:
STATUS NUSE_Queue_Send(NUSE_QUEUE queue, ADDR *message, U8 suspend);
Parameter:
queue – indeks (ID) antrian
message – pointer ke nilai ADDR yang akan dimasukkan
suspend – NUSE_NO_SUSPEND atau NUSE_SUSPEND
Nilai pengembalian mencerminkan fungsi RTOS tetapi mencerminkan perilaku pemblokiran terbatas SE.
Ringkasan Implementasi
Ketika pemblokiran dinonaktifkan, rutin hanya memeriksa ruang dan atau menulis nilai atau mengembalikan NUSE_QUEUE_FULL. Dengan pemblokiran diaktifkan, fungsi berulang, menangguhkan tugas jika antrian penuh sampai ruang tersedia atau reset terjadi. Implementasi menggunakan NUSE_Queue_Blocking_Count untuk melacak tugas yang diblokir dan NUSE_Task_Blocking_Return untuk melanjutkannya ketika slot terbuka.
do { if (NUSE_Queue_Items[queue] == NUSE_Queue_Size[queue]) { if (suspend == NUSE_NO_SUSPEND) { return_value = NUSE_QUEUE_FULL; } else { NUSE_Queue_Blocking_Count[queue]++; NUSE_Suspend_Task(NUSE_Task_Active, (queue << 4) | NUSE_QUEUE_SUSPEND); return_value = NUSE_Task_Blocking_Return[NUSE_Task_Active]; if (return_value != NUSE_SUCCESS) suspend = NUSE_NO_SUSPEND; } } else { NUSE_Queue_Data[queue][NUSE_Queue_Head[queue]++] = *message; if (NUSE_Queue_Head[queue] == NUSE_Queue_Size[queue]) NUSE_Queue_Head[queue] = 0; NUSE_Queue_Items[queue]++; if (NUSE_Queue_Blocking_Count[queue] != 0) { U8 index; NUSE_Queue_Blocking_Count[queue]--; for (index = 0; index < NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_QUEUE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == queue)) { NUSE_Task_Blocking_Return[index] = NUSE_SUCCESS; NUSE_Wake_Task(index); break; } } } return_value = NUSE_SUCCESS; suspend = NUSE_NO_SUSPEND; } } while (suspend == NUSE_SUSPEND);
Loop berlanjut sampai pesan berhasil dimasukkan atau tugas diblokir oleh reset. Implementasi memastikan akses thread-safe dan pembangkitan konsumen yang diblokir secara efisien.