Seluruh kebenaran tentang RTOS. Artikel # 13. Struktur data tugas dan panggilan API yang tidak didukung



Dalam artikel tugas ketiga dan terakhir ini, saya akan melihat struktur data Nucleus SE dan menjelaskan panggilan RTOS API yang tidak diterapkan di Nucleus SE, serta masalah kompatibilitas lainnya.

Artikel sebelumnya dalam seri:
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.

Struktur data


Tugas menggunakan berbagai struktur data (baik dalam RAM dan ROM), yang, seperti objek Nucleus SE lainnya, adalah seperangkat tabel yang ukurannya sesuai dengan jumlah tugas dan parameter yang dipilih.

Saya sangat merekomendasikan kode aplikasi mengakses struktur data ini menggunakan fungsi API, dan tidak secara langsung. Ini menghindari efek samping yang tidak diinginkan, ketidakcocokan dengan versi Nucleus SE yang akan datang, dan juga menyederhanakan porting aplikasi ke Nucleus RTOS. Untuk pemahaman yang lebih baik tentang pengoperasian kode panggilan layanan dan proses debugging, deskripsi terperinci dari struktur data diberikan di bawah ini.

Struktur Data Kernel Hosted dalam RAM


Struktur data ini meliputi:

NUSE_Task_Context [] [] - array dua dimensi dari tipe ADDR , memiliki satu baris untuk setiap tugas. Jumlah kolom tergantung pada arsitektur controller dan ditentukan oleh simbol NUSE_REGISTERS , yang didefinisikan dalam nuse_types.h . Array ini digunakan oleh penjadwal untuk menyimpan konteks setiap tugas dan telah dijelaskan secara rinci di bagian "Menyimpan Konteks" artikel # 10. Tidak dibuat jika penjadwal RTC digunakan.
NUSE_Task_Signal_Flags [] - larik tipe U8 , dibuat jika sinyal diaktifkan, dan berisi 8 flag sinyal untuk setiap tugas. Sinyal akan dibahas dalam salah satu artikel berikut.
NUSE_Task_Timeout_Counter [] adalah larik tipe U16 , terdiri dari pengurangan penghitung untuk setiap tugas dan dibuat jika panggilan ke API NUSE_Task_Sleep () diaktifkan.
NUSE_Task_Status [] - larik tipe U8, berisi status setiap tugas - NUSE_READY atau menangguhkan status. Dibuat hanya jika penangguhan tugas diaktifkan.
NUSE_Task_Blocking_Return [] - larik tipe U8, dibuat jika pemblokiran panggilan API diaktifkan. Ini berisi kode kembali yang akan digunakan setelah memblokir panggilan API. Biasanya berisi NUSE_SUCCESS atau kode yang menunjukkan bahwa objek telah disetel ulang (misalnya, NUSE_MAILBOX_WAS_RESET ).
NUSE_Task_Schedule_Count [] - larik tipe U16 , berisi penghitung untuk setiap tugas dan dibuat hanya jika jumlah penjadwal telah diaktifkan.

NUSE_Task_Context [] [] diinisialisasi terutama oleh nol, kecuali untuk entri yang berkaitan dengan register status (register status, SR), penghitung program (penghitung program, PC) dan penunjuk tumpukan (penunjuk tumpukan, SP), yang diberi nilai awal (lihat "Data dalam ROM "di bawah), dan semua struktur data lainnya NUSE_Init_Task () ditugaskan nol ketika memulai Nucleus SE. Salah satu artikel berikut akan berisi daftar lengkap prosedur awal Nucleus SE dengan uraiannya.

Berikut ini adalah definisi dari struktur data yang terkandung dalam file nuse_init.c.



Data pengguna RAM


Pengguna harus menentukan tumpukan untuk setiap tugas (jika penjadwal RTC tidak digunakan). Ini haruslah array ADDR , yang biasanya didefinisikan dalam nuse_config.c . Alamat dan ukuran tumpukan harus ditempatkan dalam entri tugas NUSE_Task_Stack_Base [] dan NUSE_Task_Stack_Size [], masing-masing (lihat Data dalam ROM).

Data ROM


ROM menyimpan dari satu hingga empat struktur data yang terkait dengan tugas. Jumlah pasti tergantung pada parameter yang dipilih:

NUSE_Task_Start_Address [] adalah larik jenis ADDR yang memiliki satu entri untuk setiap tugas, yang merupakan penunjuk ke titik entri kode untuk tugas tersebut.
NUSE_Task_Stack_Base [] adalah larik tipe ADDR yang memiliki satu entri untuk setiap tugas, yang merupakan penunjuk ke alamat dasar tumpukan untuk tugas tersebut. Array ini dibuat jika ada penjadwal selain RTC yang digunakan.
NUSE_Task_Stack_Size [] adalah larik tipe U16 yang memiliki satu entri untuk setiap tugas, yang menunjukkan ukuran tumpukan untuk tugas tersebut (dalam kata-kata). Array ini dibuat jika ada penjadwal selain RTC yang digunakan.
NUSE_Task_Initial_State [] adalah larik tipe U8 , memiliki satu entri untuk setiap tugas, yang menunjukkan status awal tugas. Ini dapat berupa NUSE_READY atau NUSE_PURE_SUSPEND . Array ini dibuat jika dukungan untuk keadaan awal tugas dipilih.

Struktur data ini dideklarasikan dan diinisialisasi (secara statis) di nuse_config.c :



Jumlah memori untuk menyimpan data tugas (Footprint Data Tugas)


Seperti semua objek inti Nucleus SE, jumlah memori yang diperlukan untuk menyimpan data dapat diprediksi.

Ukuran ROM (dalam byte) diperlukan untuk semua tugas aplikasi:
NUSE_TASK_NUMBER * sizeof (ADDR)

Plus, jika ada penjadwal selain RTC dipilih:
NUSE_TASK_NUMBER * (sizeof (ADDR) +2)

Plus, jika dukungan untuk keadaan awal tugas dipilih:
NUSE_TASK_NUMBER

Untuk menyimpan data dalam RAM, jumlah memori (dalam byte) ditentukan oleh parameter yang dipilih, dan dapat memiliki nilai nol jika tidak ada parameter yang dipilih.
Jika penjadwal selain RTC dipilih:
NUSE_TASK_NUMBER * NUSE REGISTERS * sizeof (ADDR)

Plus, jika dukungan sinyal dipilih:
NUSE_TASK_NUMBER

Plus, jika panggilan ke NUSE_Task_Sleep () API diaktifkan:
NUSE_TASK_NUMBER * 2

Plus, jika penangguhan tugas diaktifkan:
NUSE_TASK_NUMBER

Plus, jika pemblokiran panggilan API diaktifkan:
NUSE_TASK_NUMBER

Plus, jika penghitung penjadwal diaktifkan:
NUSE_TASK_NUMBER * 2

Panggilan API tidak diterapkan di Nucleus SE


Di bawah ini adalah tujuh panggilan API yang tersedia di Nucleus RTOS yang tidak diterapkan di Nucleus SE.

Buat Tugas


Panggilan API ini menciptakan tugas aplikasi. Nucleus SE tidak memerlukan fitur ini karena tugas dibuat secara statis.

Prototipe panggilan:

STATUS NU_Create_Task (NU_TASK * tugas, CHAR * nama, VOID (* task_entry) (TIDAK DITANDATANGANI, VOID *), argc TIDAK TANDA, VOID * stack_address, stack_address yang TIDAK DITANDATANGANI, prioritas TAMBAHAN, ukuran OPSI, prioritas OPSI, prioritas waktu TANDA, prioritas OPTION, OPTION prioritas

Parameter:

task - pointer ke blok kontrol tugas pengguna, dapat digunakan sebagai pegangan / tautan ("handle") dari tugas dalam panggilan API lainnya;
name - pointer ke nama tugas, string 7-karakter dengan nol penghentian;
task_entry - menunjukkan fungsi input untuk tugas;
argc - Elemen data yang tidak ditandai yang dapat digunakan untuk meneruskan informasi awal ke tugas;
argv - pointer yang dapat digunakan untuk mengirimkan informasi ke tugas;
stack_address - mengatur sektor awal memori untuk tumpukan tugas;
stack_size - menunjukkan jumlah byte di stack;
priority - menunjukkan nilai prioritas tugas: dari 0 hingga 255, di mana angka yang lebih rendah sesuai dengan prioritas tertinggi;
time_slice - menunjukkan jumlah irisan waktu maksimum yang dapat dilewati selama tugas ini. Nilai "0" menonaktifkan pengiris waktu untuk tugas ini;
preempt - menunjukkan apakah tugas digantikan atau tidak. Mungkin memiliki nilai NU_PREEMPT dan NU_NO_PREEMPT ;
auto_start - menunjukkan status awal tugas. NU_START berarti bahwa tugas tersebut siap untuk dieksekusi, dan NU_NO_START berarti bahwa tugas tersebut ditangguhkan.

Nilai pengembalian:

NU_SUCCESS - menunjukkan keberhasilan penyelesaian layanan;
NU_INVALID_TASK - menunjukkan bahwa penunjuk ke unit kontrol tugas adalah NULL ;
NU_INVALID_ENTRY - menunjukkan bahwa penunjuk ke fungsi input tugas adalah NULL ;
NU_INVALID_MEMORY - menunjukkan bahwa sektor memori yang ditetapkan oleh parameter stack_address adalah nol ( NULL );
NU_INVALID_SIZE - menunjukkan bahwa ukuran tumpukan yang ditentukan tidak cukup;
NU_INVALID_PREEMPT - menunjukkan bahwa parameter preempt diatur secara tidak benar;
NU_INVALID_START - menunjukkan bahwa parameter auto_start diatur secara tidak benar.

Hapus Tugas


Panggilan API ini menghapus tugas aplikasi yang dibuat sebelumnya yang harus Selesai atau Dihentikan . Panggilan ini juga tidak perlu untuk Nucleus SE, karena tugas dibuat secara statis dan tidak dapat dihapus.

Prototipe panggilan:

STATUS NU_Delete_Task (tugas NU_TASK *);

Parameter:

penunjuk tugas ke blok kontrol tugas

Nilai pengembalian:

NU_SUCCESS - menunjukkan keberhasilan penyelesaian layanan;
NU_INVALID_TASK - menunjukkan bahwa penunjuk ke tugas diatur secara tidak benar;
NU_INVALID_DELETE - Menunjukkan bahwa tugas tidak dalam status Selesai atau Dihentikan.

Dapatkan Penunjuk Tugas


Panggilan API ini membuat daftar petunjuk berurutan untuk semua tugas dalam sistem. Tidak diperlukan dalam Nucleus SE, karena tugas diidentifikasi menggunakan indeks sederhana, bukan pointer.

Prototipe panggilan:

NU_Task_Pointers TIDAK DITANDATANGANI (NU_TASK ** pointer_list, maksimum_pointers UNSIGNED);

Parameter:

pointer_list - pointer ke array pointer NU_TASK . Array ini akan diisi dengan pointer ke tugas-tugas yang diinstal dalam sistem;
maximum_pointers - jumlah maksimum pointer yang dapat ditempatkan dalam array.

Nilai pengembalian:

Jumlah pointer NU_TASK ditempatkan dalam array.

Ubah Prioritas Tugas


Panggilan API ini memberi tugas prioritas baru. Dalam Nucleus SE, itu tidak diperlukan, karena prioritas tugas adalah konstan.

Prototipe panggilan:

OPTION NU_Change_Priority (tugas NU_TASK *, OPTION new_priority);

Parameter:

tugas - pointer ke blok kontrol tugas;
new_priority - menetapkan prioritas dari 0 hingga 255.

Nilai pengembalian:
Nilai prioritas tugas sebelumnya.

Ubah Algoritma Preemption Tugas


Panggilan API ini mengubah urutan penyelesaian tugas yang sedang berlangsung. Nucleus SE tidak membutuhkannya karena menggunakan algoritma penjadwalan yang lebih sederhana.

Prototipe panggilan:
OPTION NU_Change_Preemption (preempt OPTION);

Parameter:
preempt - algoritma preemptive baru, menerima NU_PREEMPT atau NU_NO_PREEMPT

Nilai pengembalian:
Algoritma sebelumnya untuk crowding out tugas.

Ubah Irisan Waktu Tugas


Panggilan API ini mengubah irisan waktu tugas tertentu. Nucleus SE tidak membutuhkannya, karena irisan waktu tugas sudah diperbaiki.

Prototipe panggilan:
NU_Change_Time_Slice UNSIGNED (tugas NU_TASK *, UNSIGNED time_slice);

Parameter:
tugas - pointer ke blok kontrol tugas;
time_slice - jumlah maksimum irisan waktu yang dapat berlalu selama tugas ini, nilai nol bidang ini menonaktifkan kuantisasi waktu untuk tugas ini.

Nilai pengembalian:
Nilai sebelumnya dari kuantum waktu tugas.

Hentikan Tugas


Panggilan API ini menyelesaikan tugas tertentu. Nucleus SE tidak memerlukan ini karena keadaan Dihentikan tidak didukung.

Prototipe panggilan:
STATUS NU_Terminate_Task (tugas NU_TASK *);

Parameter:
task - pointer ke blok kontrol tugas.

Nilai pengembalian:
NU_SUCCESS - menunjukkan keberhasilan penyelesaian layanan;
NU_INVALID_TASK - Menunjukkan bahwa penunjuk tugas salah.

Kompatibel dengan RTOS Inti


Ketika mengembangkan Nucleus SE, salah satu tujuan utama adalah untuk memastikan tingkat kompatibilitas kode yang tinggi dengan Nucleus RTOS. Tugas tidak terkecuali dan, dari sudut pandang pengguna, mereka diimplementasikan dalam banyak cara yang sama seperti pada Nucleus RTOS. Ada beberapa area yang tidak kompatibel di mana saya sampai pada kesimpulan bahwa ketidakcocokan seperti itu akan dapat diterima, mengingat bahwa kode akhir lebih mudah dipahami dan dapat menggunakan memori lebih efisien. Namun, selain ketidakcocokan ini, sisa panggilan Nucleus RTOS API dapat digunakan hampir secara langsung sebagai panggilan Nucleus SE. Salah satu artikel berikut akan memberikan rincian lebih lanjut tentang transisi dari Nucleus RTOS ke Nucleus SE

Pengidentifikasi Objek


Dalam Nucleus RTOS, semua objek dijelaskan oleh struktur data (unit kontrol) yang dari tipe tertentu. Penunjuk ke unit kontrol ini berfungsi sebagai pengidentifikasi untuk tugas tersebut. Di Nucleus SE, saya memutuskan bahwa diperlukan pendekatan yang berbeda untuk penggunaan memori yang efisien. Semua objek kernel dijelaskan oleh satu set tabel dalam RAM dan / atau ROM. Ukuran tabel ini ditentukan oleh jumlah jenis objek. Pengidentifikasi objek tertentu adalah indeks dalam tabel ini. Jadi saya mendefinisikan NUSE_TASK sebagai setara dengan U8 . Variabel jenis ini (bukan penunjuk) berfungsi sebagai pengidentifikasi untuk tugas. Ini adalah ketidakcocokan kecil yang mudah diketahui jika kode porting ke atau dari Nucleus RTOS. Pengidentifikasi objek biasanya disimpan dan dikirim tidak berubah.

Nucleus RTOS juga mendukung penamaan tugas. Nama-nama ini hanya digunakan untuk debugging. Saya mengecualikan mereka dari Nucleus SE untuk menghemat memori.

Status tugas


Dalam Nucleus RTOS, tugas bisa di salah satu dari beberapa negara: Eksekusi , Siap , Ditangguhkan (yang mengarah ke ketidakpastian: tugas dalam keadaan siaga atau diblokir oleh panggilan API), Dihentikan, atau Selesai.

Nucleus SE juga mendukung status Eksekusi dan Siap . Ketiga opsi Penangguhan didukung secara opsional. Dihentikan dan Selesai tidak didukung. Tidak ada panggilan API untuk menyelesaikan tugas. Fungsi tugas eksternal seharusnya tidak pernah mengembalikan nilai baik secara eksplisit maupun implisit (ini akan menghasilkan status jadi dalam Nucleus RTOS).

Panggilan API yang belum direalisasi


Nucleus RTOS mendukung 16 panggilan kantor untuk bekerja dengan tugas. Dari jumlah tersebut, 7 tidak diimplementasikan dalam Nucleus SE. Deskripsi mereka, serta alasan pengecualian mereka dijelaskan di atas.

Pada artikel selanjutnya, kita akan mulai melihat manajemen memori 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/id425353/


All Articles