Seluruh kebenaran tentang RTOS. Artikel # 14. Bagian memori: pengantar dan layanan dasar



Bagian memori disebutkan sebelumnya dalam salah satu artikel sebelumnya (# 6), di mana perbandingan dibuat dengan fungsi standar bahasa C malloc () . Partisi adalah wilayah memori yang diperoleh dari kumpulan partisi (memori pool). Berbagi memori menyediakan cara yang fleksibel untuk mengalokasikan dan membebaskan memori secara andal dan deterministik.

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


Di Nucleus SE, kumpulan partisi dikonfigurasikan pada waktu pembuatan. Satu aplikasi dapat memiliki hingga 16 kumpulan partisi. Jika tidak dikonfigurasi, struktur data dan panggilan layanan yang terkait dengan kumpulan ini tidak akan dimasukkan dalam aplikasi.

Pool partisi adalah area memori yang dibagi menjadi sejumlah blok dengan ukuran tetap. Pengembang memiliki kontrol penuh atas ukuran dan jumlah partisi di setiap kumpulan. Tugas dapat meminta bagian memori yang dialokasikan dan menerima pointer ke area penyimpanan dan tidak boleh menulis data di luar bagian yang dialokasikan. Bagian dapat dibebaskan oleh tugas apa pun saat meneruskan pointer ke fungsi API. Permintaan untuk mengalokasikan partisi ketika tidak ada partisi bebas dapat menyebabkan kesalahan atau penangguhan permintaan, tergantung pada parameter panggilan API yang dipilih dan konfigurasi Nucleus SE.

Menyiapkan partisi memori


Jumlah Kolam Partisi


Seperti kebanyakan objek Nucleus SE, konfigurasi pool partisi terutama dilakukan dengan menggunakan #define directive di nuse_config.h . Parameter utama adalah NUSE_PARTITION_POOL_NUMBER , yang menentukan berapa banyak kumpulan partisi yang ditentukan dalam aplikasi. Nilai defaultnya adalah 0 (artinya, pool partisi tidak digunakan), pengembang dapat mengatur nilai apa pun dari 0 hingga 16. Nilai lainnya akan menyebabkan kesalahan kompilasi, yang terdeteksi selama verifikasi di nuse_config_check.h (ini termasuk dalam nuse_config.c , dan Oleh karena itu, kompilasi dengan modul ini), yang mengarah ke kompilasi dari #error directive.

Memilih nilai bukan nol adalah cara prioritas untuk mengaktifkan kumpulan partisi. Ini mengarah pada definisi struktur data dan penetapan ukuran yang sesuai. Struktur data dalam ROM harus diinisialisasi dengan nilai-nilai yang sesuai yang menggambarkan setiap kumpulan partisi. Rincian lebih lanjut tentang struktur data akan di artikel berikutnya. Pilihan ini juga mengaktifkan pengaturan API.

Aktifkan Panggilan API


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

NUSE_PARTITION_ALLOCATE
NUSE_PARTITION_DEALLOCATE
NUSE_PARTITION_POOL_INFORMATION
NUSE_PARTITION_POOL_COUNT

Secara default, mereka semua diatur ke FALSE , sehingga menonaktifkan setiap panggilan layanan dan mencegah dimasukkannya kode implementasi. Untuk mengonfigurasi kumpulan partisi dalam aplikasi, Anda perlu memilih panggilan API yang diperlukan dan mengatur arahan yang sesuai ke TRUE .

Berikut ini adalah kutipan dari file nuse_config.h default:



Jika fungsi Partition Pools API diaktifkan, tetapi pool tidak dikonfigurasi, kesalahan kompilasi terjadi (kecuali untuk NUSE_Partition_Pool_Count () , yang selalu diaktifkan). Jika kode Anda menggunakan panggilan API yang belum diaktifkan, kesalahan tata letak akan terjadi karena kode implementasi tidak termasuk dalam aplikasi.

Panggilan Utilitas Kolam Partisi


Nucleus RTOS mendukung tujuh panggilan utilitas yang terkait dengan kumpulan partisi, yang menyediakan fungsionalitas berikut:

Deskripsi FungsionalRTOS intiNucleus SE
Pemilihan bagianNU_Alokasi_Partisi ()NUSE_Partition_Allocate ()
Bagian RilisNU_Deallocate_Partition ()NUSE_Partition_Deallocate ()
Memberikan Informasi
tentang kumpulan partisi tertentu
NU_Partition_Pool_Information ()NUSE_Partition_Pool_Information ()
Kembalikan nilai kuantitas (saat ini) yang dikonfigurasi
kumpulan aplikasi
NU_Established_Partition_Pools ()NUSE_Partition_Pool_Count ()
Menambahkan (membuat) kumpulan partisi baru ke aplikasiNU_Create_Partition_Pool ()Tidak diterapkan.
Mengubah (menghapus) kumpulan partisi dari aplikasiNU_Delete_Partition_Pool ()Tidak diterapkan.
Mengembalikan pointer ke semua kumpulan partisi yang saat ini ada dalam aplikasiNU_Partition_Pool_Pointers ()Tidak diterapkan.

Implementasi dari setiap panggilan akan dibahas secara rinci.

Perlu dicatat bahwa baik Nucleus RTOS maupun Nucleus SE tidak memiliki fungsi reboot. Ini dilakukan dengan sengaja. Sangat sering, satu tugas mengalokasikan bagian dan meneruskan pointer ke tugas lain (yang nantinya dapat membebaskannya). Jika Anda memuat ulang kumpulan partisi, semua partisi akan ditandai sebagai tidak terpakai, namun, tidak ada mekanisme untuk memantau dan memberi tahu semua tugas yang dapat menggunakan partisi.

Layanan Partisi dan Rilis


Operasi mendasar dengan kumpulan partisi adalah alokasi partisi di kumpulan (mis. Menandai partisi sebagai digunakan dan mengembalikan alamatnya) dan melepaskan partisi (mis. Partisi ditandai sebagai tidak digunakan). Nucleus RTOS dan Nucleus SE menyediakan dua panggilan API dasar untuk operasi ini, yang dijelaskan di bawah ini.

Pemilihan bagian


Panggilan Nucleus RTOS API untuk mengalokasikan partisi sangat fleksibel, yang memungkinkan pengembang untuk menjeda tugas untuk jangka waktu yang tidak terbatas atau tanpa batas waktu jika operasi tidak dapat diselesaikan dengan segera, misalnya, ketika Anda mencoba mengalokasikan partisi dari kumpulan di mana semua partisi sudah didistribusikan. Nucleus SE menyediakan layanan yang sama, hanya menjeda tugas di dalamnya adalah opsional, dan batas waktu tidak diterapkan.

Nucleus RTOS API Call to Partition


Prototipe panggilan:

STATUS NU_Alokasi_Partisi (NU_PARTITION_POOL * kumpulan, VOID ** return_pointer, menangguhkan TANDA TANGAN);

Nilai pengembalian:

NU_SUCCESS - panggilan berhasil diselesaikan;
NU_NO_PARTITION - tidak ada bagian yang tersedia;
NU_INVALID_POOL - penunjuk kumpulan partisi tidak valid;
NU_INVALID_POINTER - meneruskan pointer nol ke data yang dikembalikan ( NULL );
NU_INVALID_SUSPEND - upaya untuk menangguhkan tugas dilakukan dari utas yang tidak terkait dengan tugas tersebut;
NU_TIMEOUT - tidak ada partisi yang tersedia, bahkan setelah penangguhan untuk periode tunggu yang ditentukan;
NU_POOL_DELETED - Kumpulan partisi telah dihapus ketika tugas ditangguhkan.

Nucleus SE API call untuk menyorot partisi


Panggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.

Prototipe panggilan:

STATUS NUSE_Partition_Allocate (NUSE_PARTITION_POOL kumpulan, ADDR * return_pointer, menangguhkan U8);

Parameter:

pool - index (ID) dari pool partisi yang digunakan;
return_pointer - penunjuk ke variabel tipe ADDR , yang mengambil alamat bagian yang dipilih;
menangguhkan - parameter untuk menjeda tugas, dapat mengambil nilai NUSE_NO_SUSPEND atau NUSE_SUSPEND .

Nilai pengembalian:

NUSE_SUCCESS - panggilan berhasil diselesaikan;
NUSE_NO_PARTITION - tidak ada bagian yang tersedia;
NUSE_INVALID_POOL - indeks kumpulan partisi tidak valid;
NUSE_INVALID_POINTER - meneruskan pointer nol ke data yang dikembalikan ( NULL );
NUSE_INVALID_SUSPEND — Upaya menangguhkan tugas dilakukan dari utas yang tidak terkait dengan tugas atau saat API penguncian dinonaktifkan.

Implementasi alokasi partisi di Nucleus SE


Kode fungsi API NUSE_Partition_Allocate dipilih menggunakan kompilasi bersyarat setelah memeriksa parameter, tergantung pada apakah panggilan API untuk memblokir (menangguhkan tugas) diaktifkan atau tidak. Di bawah ini kami akan mempertimbangkan dua opsi ini secara terpisah.

Jika pemblokiran panggilan dinonaktifkan, panggilan API cukup sederhana:



Pertama, ketersediaan partisi gratis diperiksa. Jika tidak ada partisi seperti itu, kesalahan dikembalikan ( NUSE_NO_PARTITION ). Kemudian ada penghitungan bagian, di mana byte pertama diperiksa untuk nilai nol (yang menunjukkan bahwa bagian tersebut tidak digunakan). Ketika partisi seperti itu ditemukan, itu diberi bendera "bekas", yang meliputi indeks kumpulan partisi (lihat "Lepaskan partisi" di bawah), dan mengembalikan pointer ke byte berikutnya (awal area data nyata). Penjelasan tentang struktur data dari kumpulan partisi akan disajikan pada artikel berikutnya di bagian Struktur Data.

Jika kunci diaktifkan, kode untuk panggilan API ini menjadi sedikit lebih rumit:



Kode dilampirkan dalam do ... while , yang terus berjalan selama parameter pause adalah NUSE_SUSPEND .

Jika tidak ada partisi yang tersedia dan parameter jeda adalah NUSE_NO_SUSPEND , panggilan API berhenti dan mengembalikan NUSE_NO_PARTITION . Jika parameter jeda ditetapkan ke NUSE_SUSPEND , tugas akan dijeda. Saat kembali (misalnya, ketika tugas dilanjutkan), nilai kembali NUSE_SUCCESS menunjukkan bahwa tugas dilanjutkan karena bagian memori dibebaskan dan kode kembali ke awal loop. Karena tidak ada fungsi API untuk memuat ulang kumpulan partisi, tugas tidak dapat dilanjutkan karena alasan lain, tetapi untuk stabilitas memblokir jenis objek lainnya, proses pemeriksaan NUSE_Task_Blocking_Return [] disimpan.

Bagian Rilis


Pelepasan bagian dalam Nucleus RTOS dan Nucleus SE membuatnya tersedia lagi. Sebelum dirilis, tidak memeriksa apakah bagian ini digunakan oleh tugas apa pun atau tidak, programmer aplikasi bertanggung jawab untuk ini. Hanya penunjuk ke area data yang diperlukan untuk membebaskan bagian.

Nucleus RTOS API Call to Free Partition


Prototipe panggilan:

STATUS NU_Deallocate_Partition (VOID * partisi);

Parameter:

partisi - pointer ke area data (dikembalikan oleh fungsi NU_Allocate_Partition () ) dari partisi yang akan dibebaskan;

Nilai pengembalian:

NU_SUCCESS - panggilan berhasil diselesaikan;
NU_INVALID_POINTER - NULL penunjuk bagian, atau tidak menunjukkan bagian yang valid digunakan.

Nucleus SE API call ke partisi bebas


Panggilan API ini mendukung fungsionalitas inti API Nucleus RTOS.

Prototipe panggilan:

STATUS NUSE_Partition_Deallocate (partisi ADDR);

Parameter:

partisi - pointer ke area data (dikembalikan oleh fungsi NUSE_Partition_Allocate () ) dari partisi yang akan dibebaskan

Nilai pengembalian:

NUSE_SUCCESS - panggilan berhasil diselesaikan;
NUSE_INVALID_POINTER - penunjuk bagian adalah nol ( NULL ), atau tidak menunjukkan bagian yang valid digunakan

Implementasi


Alih-alih mengimplementasikan menggunakan fungsi API yang memblokir dan yang tidak menghalangi, fungsi NUSE_Partition_Deallocate () hanya berisi bagian yang dikondisikan secara kondisional yang bertanggung jawab untuk membuka kunci tugas. Kode ini mengimplementasikan pembebasan bagian:



Pertama, indeks bagian diambil dari byte status. Kemudian, status partisi berubah menjadi "tidak terpakai", penghitung partisi yang digunakan berkurang, dan fungsinya melaporkan penyelesaian operasi yang berhasil.

Jika kunci diaktifkan, kode berikut ini digunakan untuk melanjutkan tugas menunggu kumpulan partisi yang tersedia:



Jika tugas diblokir saat mengalokasikan partisi di kumpulan ini, tabel pertama dilanjutkan.

Pada artikel berikutnya, kita akan berbicara tentang panggilan API tambahan yang terkait dengan partisi memori, serta struktur data terkait.

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.

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


All Articles