
Artikel ini melanjutkan review dari semaphores.
Layanan semafor pembantu
Nucleus RTOS memiliki empat panggilan API yang menyediakan fungsionalitas terkait semaphore: mengatur ulang semaphore, mengambil informasi semaphore, mengambil jumlah semaphore dalam suatu aplikasi, dan mengambil pointer ke semua semaphore dalam suatu aplikasi. Tiga yang pertama diimplementasikan dalam Nucleus SE.
Artikel sebelumnya dalam seri:
Artikel # 19. Semaphores: pengantar dan layanan dasarArtikel # 18. Grup Bendera Acara: Layanan Pembantu dan Struktur DataArtikel # 17. Grup Bendera Acara: Pengantar dan Layanan DasarArtikel # 16. SinyalArtikel # 15. Partisi Memori: Layanan dan Struktur DataArtikel # 14. Bagian memori: pengantar dan layanan dasarArtikel # 13. Struktur data tugas dan panggilan API yang tidak didukungArtikel # 12. Layanan untuk bekerja dengan tugasArtikel # 11. Tugas: konfigurasi dan pengantar APIArtikel # 10. Penjadwal: fitur canggih dan pelestarian konteksArtikel # 9. Penjadwal: implementasiArtikel # 8. Nucleus SE: Desain dan Penyebaran InternalArtikel # 7. Nucleus SE: PendahuluanArtikel # 6. Layanan RTOS lainnyaArtikel # 5. Interaksi tugas dan sinkronisasiArtikel # 4. Tugas, pengalihan konteks, dan interupsiArtikel # 3. Tugas dan PerencanaanArtikel # 2. RTOS: Struktur dan mode waktu-nyata
Artikel # 1. RTOS: pengantar.
Setel ulang semaphore
Panggilan API ini mengatur ulang semaphore ke kondisi awal, yang tidak digunakan. Fungsi API ini tidak biasa dibandingkan dengan fungsi-fungsi objek kernel lainnya, karena meskipun faktanya melakukan reset, ia tidak hanya menetapkan penghitung ke nilai awal, tetapi nilai penghitung awal baru diteruskan dalam panggilan. Tugas apa pun yang telah dijeda pada semaphore dilanjutkan dan mengembalikan kode
NUSE_SEMAPHORE_WAS_RESET di Nucleus SE, dan di Nucleus RTOS,
NU_SEMAPHORE_RESET .
Panggilan untuk mengatur ulang semaphore di Nucleus RTOSPrototipe panggilan layanan:
STATUS NU_Reset_Semaphore (NU_SEMAPHORE * semaphore, UNSIGNED initial_count);Parameter:
semaphore - penunjuk ke blok kontrol semaphore yang disediakan oleh pengguna;
initial_count - nilai yang akan ditetapkan semaphore.
Nilai pengembalian:
NU_SUCCESS - panggilan berhasil diselesaikan;
NU_INVALID_SEMAPHORE - Pointer semaphore
tidak valid .
Panggilan untuk mengatur ulang semafor di Nucleus SEPanggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.
Prototipe panggilan layanan:
STATUS NUSE_Semaphore_Reset (NUSE_SEMAPHORE semaphore, U8 initial_count);Parameter:
semaphore - index (ID) dari semaphore yang dibuang;
initial_count - nilai yang akan ditetapkan semaphore.
Nilai pengembalian:
NUSE_SUCCESS - panggilan berhasil diselesaikan;
NUSE_INVALID_SEMAPHORE - indeks semaphore tidak valid.
Menerapkan reset semaphore di Nucleus SETugas utama dari fungsi API
NUSE_Semaphore_Reset () adalah untuk mengatur elemen
NUSE_Semaphore_Counter [] yang sesuai ke nilai yang ditentukan (setelah memeriksa parameter).
Jika penguncian tugas diaktifkan, kode berikut diperlukan untuk membuka kunci tugas:
while (NUSE_Semaphore_Blocking_Count[semaphore] != 0) { U8 index; /* check whether any tasks are blocked */ /* on this semaphore */ for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_SEMAPHORE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == semaphore)) { NUSE_Task_Blocking_Return[index] = NUSE_SEMAPHORE_WAS_RESET; NUSE_Task_Status[index] = NUSE_READY; break; } } NUSE_Semaphore_Blocking_Count[semaphore]--; } #if NUSE_SCHEDULER_TYPE == NUSE_PRIORITY_SCHEDULER NUSE_Reschedule(NUSE_NO_TASK); #endif
Setiap tugas yang ditangguhkan pada semafor ditandai sebagai "selesai", dan kode penangguhan tugas mengembalikan
NUSE_SEMAPHORE_WAS_RESET . Setelah proses ini selesai, jika penjadwal Prioritas digunakan, panggilan akan menginisialisasi
NUSE_Reschedule () , karena satu atau lebih tugas dengan prioritas yang lebih tinggi dapat masuk ke status siap dan sedang menunggu untuk melanjutkan.
Informasi semaphore
Panggilan utilitas ini mengembalikan informasi semafor. Implementasi panggilan ini dalam Nucleus SE berbeda dari Nucleus RTOS karena lebih sedikit informasi yang dikembalikan, karena penamaan objek dan urutan jeda tidak didukung, dan penangguhan tugas itu sendiri dapat dinonaktifkan.
Panggil untuk informasi semaphore di Nucleus RTOSPrototipe panggilan layanan:
STATUS NU_Semaphore_Information (NU_SEMAPHORE * semaphore, CHAR * name, UNSIGNED * current_count, OPTION * suspend_type, UNSIGNED * task_waiting, NU_TASK ** first_task);Parameter:
semaphore - pointer ke blok kontrol semaphore tentang informasi mana yang diperlukan;
name - pointer ke nama 8-karakter semaphore, dengan nol terminasi byte termasuk dalam area ini;
current_count - pointer ke variabel yang akan mengambil nilai saat ini dari penghitung semaphore;
suspend_type - pointer ke variabel yang akan menerima jenis tugas yang ditangguhkan, dapat mengambil nilai
NU_FIFO dan
NU_PRIORITY ;
task_waiting - pointer ke variabel yang akan mengambil jumlah tugas yang ditangguhkan di semaphore;
first_task - pointer ke variabel tipe
NU_TASK , yang akan membawa pointer ke unit kontrol tugas yang ditangguhkan pertama.
Nilai pengembalian:
NU_SUCCESS - panggilan berhasil diselesaikan;
NU_INVALID_SEMAPHORE - Pointer semaphore
tidak valid .
Panggilan untuk informasi semafor di Nucleus SEPanggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.
Prototipe panggilan layanan:
STATUS NUSE_Semaphore_Information (NUSE_SEMAPHORE semaphore, U8 * current_count, U8 * task_waiting, NUSE_TASK * first_task);Parameter:
semaphore - indeks semaphore yang dibutuhkan untuk memberikan informasi;
current_count - pointer ke variabel yang akan mengambil nilai saat ini dari penghitung semaphore;
task_waiting - pointer ke variabel yang akan mengambil jumlah tugas yang ditangguhkan pada semaphore ini (tidak ada yang dikembalikan jika dukungan untuk tugas yang ditangguhkan dinonaktifkan);
first_task - pointer ke variabel tipe
NUSE_TASK , yang akan mengambil indeks tugas yang dijeda pertama (tidak ada yang dikembalikan jika dukungan untuk tugas jeda dinonaktifkan).
Nilai pengembalian:
NUSE_SUCCESS - panggilan berhasil diselesaikan;
NUSE_INVALID_SEMAPHORE - indeks semaphore tidak valid;
NUSE_INVALID_POINTER - satu atau beberapa parameter pointer salah.
Menerapkan informasi semaphore di Nucleus SEMenerapkan panggilan API ini cukup sederhana:
NUSE_CS_Enter(); *current_count = NUSE_Semaphore_Counter[semaphore]; #if NUSE_BLOCKING_ENABLE *tasks_waiting = NUSE_Semaphore_Blocking_Count[semaphore]; if (NUSE_Semaphore_Blocking_Count[semaphore] != 0) { U8 index; for (index=0; index<NUSE_TASK_NUMBER; index++) { if ((LONIB(NUSE_Task_Status[index]) == NUSE_SEMAPHORE_SUSPEND) && (HINIB(NUSE_Task_Status[index]) == semaphore)) { *first_task = index; break; } } } else { *first_task = 0; } #else *tasks_waiting = 0; *first_task = 0; #endif NUSE_CS_Exit(); return NUSE_SUCCESS;
Fungsi mengembalikan status semaphore. Kemudian, jika fungsionalitas pemblokiran panggilan API diaktifkan, jumlah tugas yang tertunda dan indeks yang pertama dikembalikan (jika tidak, parameter ini diatur ke 0).
Mendapatkan jumlah semaphores
Panggilan utilitas ini mengembalikan jumlah semafor dalam aplikasi. Dalam Nucleus RTOS, nilai ini berubah seiring waktu dan nilai kembali sesuai dengan jumlah semafor saat ini, dan dalam Nucleus SE, nilai kembali diatur pada tahap perakitan dan tidak berubah lagi.
Memanggil penghitung semafor di Nucleus RTOSPrototipe panggilan layanan:
NU_Established_Semaphores (VOID) TIDAK DITANDATANGANI;Parameter:
Tidak ada.
Nilai pengembalian:
Jumlah semaphore yang dibuat dalam aplikasi.
Memanggil penghitung semafor di Nucleus SEPanggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.
Prototipe panggilan layanan:
U8 NUSE_Semaphore_Count (batal);Parameter:
Tidak ada.
Nilai pengembalian:
Jumlah semafor yang dikonfigurasi dalam aplikasi.
Menerapkan penghitung semafor di Nucleus SEImplementasi panggilan API ini cukup sederhana: nilai simbol
#define NUSE_SEMAPHORE_NUMBER dikembalikan .
Struktur data
Semaphore menggunakan dua atau tiga larik struktur data (dalam RAM dan ROM), yang, seperti semua objek SE Nucleus lainnya, adalah seperangkat tabel yang ukurannya tergantung pada jumlah semaphore dalam aplikasi dan parameter yang dipilih.
Saya sangat merekomendasikan bahwa kode aplikasi tidak menggunakan akses langsung ke struktur data ini, tetapi merujuknya melalui fungsi API yang disediakan. Ini akan menghindari ketidakcocokan dengan versi Nucleus SE di masa depan dan efek samping yang tidak diinginkan, serta menyederhanakan porting aplikasi ke Nucleus RTOS. Untuk pemahaman yang lebih baik tentang cara kerja kode panggilan layanan dan untuk debugging, gambaran umum terperinci dari struktur data diberikan di bawah ini.
Data RAM
Data ini memiliki struktur sebagai berikut:
NUSE_Semaphore_Counter [] - larik tipe
U8 yang memiliki satu entri untuk setiap semafor yang dikonfigurasi, ia menyimpan nilai penghitung.
NUSE_Semaphore_Blocking_Count [] - larik tipe
U8 , berisi penghitung tugas yang diblokir pada setiap semafor. Array ini hanya ada jika fungsionalitas pemblokiran panggilan API diaktifkan.
NUSE_Semaphore_Counter [] diinisialisasi ke nilai awal (lihat "Data dalam ROM" di bawah), dan
NUSE_Semaphore_Blocking_Count [] diatur ulang menggunakan
NUSE_Init_Semaphore () ketika Nucleus SE dimulai. Salah satu artikel berikut akan memberikan deskripsi lengkap tentang prosedur startup Nucleus SE.
Berikut ini adalah definisi dari struktur data ini dalam file
nuse_init.c .
RAM U8 NUSE_Semaphore_Counter[NUSE_SEMAPHORE_NUMBER]; #if NUSE_BLOCKING_ENABLE RAM U8 NUSE_Semaphore_Blocking_Count[NUSE_SEMAPHORE_NUMBER]; #endif
Data ROM
Struktur data:
NUSE_Semaphore_Initial_Value [] - larik tipe
U8 , memiliki satu catatan untuk setiap semaphore, ini adalah nilai awal dari semaphore.
Struktur data ini dideklarasikan dan diinisialisasi (secara statis) di
nuse_config.c :
ROM U8 NUSE_Semaphore_Initial_Value[NUSE_SEMAPHORE_NUMBER] = { /* semaphore initial count values */ };
Jumlah memori untuk semaphores
Seperti semua objek kernel Nucleus SE, jumlah data yang diperlukan untuk semaphores dapat diprediksi.
Jumlah memori dalam ROM (dalam byte) untuk semua semafor dalam aplikasi adalah
NUSE_SEMAPHORE_NUMBER .
Jumlah memori dalam RAM (dalam byte) untuk semua semafor dalam aplikasi dengan panggilan yang diaktifkan ke API kunci dapat dihitung sebagai berikut:
NUSE_SEMAPHORE_NUMBER * 2
Kalau tidak, itu adalah
NUSE_SEMAPHORE_NUMBER .
Panggilan API yang belum direalisasi
Tiga panggilan API untuk semafor yang hadir di Nucleus RTOS tidak diterapkan di Nucleus SE.
Membuat semafor
Panggilan API ini menciptakan semafor. Tidak perlu untuk Nucleus SE karena semaphores dibuat secara statis.
Prototipe panggilan layanan:
STATUS NU_Create_Semaphore (NU_SEMAPHORE * semaphore, CHAR * nama, initial_count UNSIGNED, OPTION suspend_type);Parameter:
semaphore - pointer ke blok kontrol semaphore yang disediakan oleh pengguna, digunakan untuk mengontrol semaphores dalam panggilan API lainnya;
name - pointer ke nama semaphore 8-karakter, dengan terminasi null byte dihidupkan;
initial_count - nilai awal semaphore;
suspend_type - Menunjukkan prinsip menjeda tugas pada semafor. Ini dapat mengambil nilai
NU_FIFO dan
NU_PRIORITY , sesuai dengan prinsip FIFO (First-in-First-Out) dan urutan prioritas penangguhan tugas.
Nilai pengembalian:
NU_SUCCESS - panggilan berhasil diselesaikan;
NU_INVALID_SEMAPHORE - Mengatakan bahwa penunjuk ke blok kontrol semaphore adalah
NULL atau sudah digunakan;
NU_INVALID_SUSPEND - parameter
suspend_type tidak valid.
Penghapusan semaphore
Panggilan API ini menghapus semafor yang dibuat sebelumnya. Nucleus SE tidak diperlukan karena semaphore dibuat secara statis dan tidak dapat dihapus.
Prototipe panggilan layanan:
STATUS NU_Delete_Semaphore (NU_SEMAPHORE * semaphore);Parameter:
semaphore - penunjuk ke blok kontrol semaphore.
Nilai pengembalian:
NU_SUCCESS - panggilan berhasil diselesaikan;
NU_INVALID_SEMAPHORE - Pointer semaphore
tidak valid .
Pointer ke semaphores
Panggilan API ini membentuk daftar pointer berurutan untuk semua semafor dalam sistem. Tidak perlu Nucleus SE, karena semaphores diidentifikasi oleh indeks sederhana, bukan pointer.
Prototipe panggilan layanan:
NU_Semaphore_Pointers TIDAK DITANDATANGANI (NU_SEMAPHORE ** pointer_list, maksimum_pointers UNSIGNED);Parameter:
pointer_list - pointer ke array pointer
NU_SEMAPHORE , array ini diisi dengan pointer ke semaphores;
maximum_pointers - jumlah maksimum pointer dalam array.
Nilai pengembalian:
Jumlah
NU_SEMAPHORE pointer dalam array.
Kompatibel dengan RTOS Inti
Seperti semua objek Nucleus SE lainnya, tujuannya adalah untuk memaksimalkan kompatibilitas kode aplikasi dengan Nucleus RTOS. Semaphore tidak terkecuali dan, dari sudut pandang pengguna, mereka diimplementasikan dengan cara yang sama seperti pada Nucleus RTOS. Ada juga ketidakcocokan tertentu, yang saya anggap dapat diterima mengingat fakta bahwa kode akhir akan menjadi lebih dimengerti dan lebih efisien dalam hal jumlah memori yang diperlukan. Jika tidak, panggilan Nucleus RTOS API dapat digunakan hampir secara langsung sebagai panggilan Nucleus SE.
Pengidentifikasi Objek
Dalam Nucleus RTOS, semua objek dijelaskan oleh struktur data (unit kontrol) dari tipe tertentu. Penunjuk ke unit kontrol ini berfungsi sebagai pengidentifikasi untuk semaphore. Saya memutuskan bahwa dalam Nucleus SE, diperlukan pendekatan yang berbeda untuk penggunaan memori yang efisien: semua objek kernel dijelaskan oleh seperangkat tabel dalam RAM dan / atau ROM. Ukuran tabel ini ditentukan oleh jumlah objek yang dikonfigurasi dari setiap jenis. Pengidentifikasi objek tertentu adalah indeks dalam tabel ini. Jadi saya mendefinisikan
NUSE_SEMAPHORE sebagai setara dengan
U8 , variabel (bukan pointer) dari tipe ini berfungsi sebagai pengidentifikasi untuk semaphore. Ketidakcocokan sedikit ini mudah ditangani jika kode porting dari Nucleus SE ke Nucleus RTOS dan sebaliknya. Biasanya, tidak ada operasi yang dilakukan pada pengidentifikasi objek selain memindahkan dan menyimpan.
Nucleus RTOS juga mendukung penamaan semaphores. Nama-nama ini hanya digunakan untuk debugging. Saya mengecualikan mereka dari Nucleus SE untuk menghemat memori.
Ukuran penghitung
Pada Nucleus RTOS, penghitung semaphore bertipe
unsigned , yang biasanya merupakan variabel 32-bit. Nucleus SE memiliki penghitung 8-bit, tetapi ini dapat dengan mudah diubah. Biasanya, Nucleus RTOS tidak memeriksa untuk semaphore overflow. Memanggil Nucleus SE API tidak akan mengizinkan penghitung untuk diberi nilai di atas 255.
Panggilan API yang belum direalisasi
Nucleus RTOS mendukung delapan panggilan utilitas untuk bekerja dengan semaphores. Dari jumlah tersebut, tiga tidak diimplementasikan dalam Nucleus SE. Rincian tantangan ini, serta keputusan untuk mengeluarkannya dari Nucleus SE, telah dijelaskan di atas.
Artikel berikut akan memeriksa kotak surat.
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.