
Selamat siang Saya ingin berbicara tentang arsitektur aplikasi yang disematkan. Sayangnya, ada sangat sedikit buku tentang topik ini, dan karena fakta bahwa, baru-baru ini, minat untuk menanamkan dan IoT meningkat, saya ingin memperhatikan masalah ini. Dalam artikel ini, saya ingin menjelaskan salah satu opsi yang memungkinkan untuk bagaimana aplikasi tersebut dapat dirancang.
Ini pertanyaan yang bisa diperdebatkan! Karena itu, mereka menawarkan untuk membagikan visi mereka dalam komentar!
Untuk memulainya, kami akan menentukan area: dalam kerangka artikel ini, dengan pengembangan yang disematkan yang kami maksudkan pengembangan perangkat lunak untuk mikrokontroler (selanjutnya MK, misalnya STM32) dalam bahasa C / Asm.
Proyek-proyek untuk sistem berbasis MK secara kondisional dapat dibagi menjadi proyek-proyek
yang tidak memerlukan dan
memerlukan multitasking. Adapun solusi dari tipe pertama, mereka biasanya tidak terlalu kompleks (dari sudut pandang struktural). Sebagai contoh, sebuah proyek sederhana, di mana perlu membaca data dari sensor dan menampilkannya di layar, tidak memerlukan multitasking, di sini cukup untuk mengimplementasikan eksekusi berurutan dari operasi di atas.

Jika aplikasi lebih kompleks: dalam kerangka yang diperlukan untuk membaca data dari sensor digital dan analog, simpan nilai yang diperoleh ke memori (misalnya, ke kartu SD), pertahankan antarmuka pengguna (tampilan + keyboard), dan berikan akses ke data melalui antarmuka digital (misalnya, RS-485 / Modbus atau Ethernet / TCP / IP) dan bereaksi secepat mungkin terhadap peristiwa tertentu dalam sistem (menekan tombol darurat, dll.), maka dalam hal ini akan sulit dilakukan tanpa multitasking. Ada dua cara untuk memecahkan masalah multitasking: untuk mengimplementasikannya sendiri, atau menggunakan beberapa jenis sistem operasi (selanjutnya disebut sebagai OS). Saat ini, salah satu sistem operasi real-time paling populer untuk sistem embedded adalah FreeRTOS.
Mari kita coba bayangkan bagaimana arsitektur aplikasi yang "rumit" tertanam yang melakukan sejumlah besar operasi heterogen akan terlihat seperti. Saya akui bahwa ada kemungkinan untuk mengusulkan opsi yang lebih rumit, yang melibatkan penyelesaian masalah pemrosesan suara, kriptografi, dll., Tetapi kita akan memikirkan opsi yang dijelaskan di atas.
Kami menetapkan tugas lebih jelas, bahkan jika dalam kerangka aplikasi kami perlu:
- Baca data dari sensor pada RS-485 / Modbus.
- Baca data dari sensor pada bus I2C.
- Baca data dari input digital.
- Kontrol output relai.
- Pertahankan antarmuka pengguna (tampilan + keyboard).
- Berikan akses ke data melalui RS-485 / Modbus.
- Simpan data ke media eksternal.
Karena kita perlu menerapkan sejumlah besar subtugas yang berbeda, kita akan menggunakan sistem operasi waktu-nyata (misalnya, FreeRTOS yang telah disebutkan) sebagai basis. Utas dalam OS terkadang akan disebut tugas - mirip dengan FreeRTOS. Saya ingin memperingatkan Anda segera: tidak akan ada kode sumber dalam artikel, itu adalah aspek arsitektur dari masalah ini yang menarik.
Jika kita menganalisis tugas, kita dapat melihat bahwa berbagai komponen sistem menggunakan data yang sama. Misalnya: data dari sensor harus diperoleh, ditampilkan di layar, ditulis ke media dan disediakan untuk sistem eksternal untuk dibaca. Ini menunjukkan bahwa beberapa jenis database waktu nyata (RTDB) diperlukan untuk menyimpan dan menyediakan data yang paling relevan untuk berbagai subsistem.
Tugas yang dilakukan dalam sistem (membaca data, menulis, menampilkan, dll.) Dapat memiliki persyaratan berbeda untuk frekuensi panggilannya. Tidak masuk akal untuk memperbarui data pada tampilan dengan frekuensi 1 kali per 100 ms, karena ini tidak penting untuk seseorang, tetapi sering kali perlu untuk membaca data dari sensor (terutama jika perlu untuk memberikan tindakan kontrol pada mereka) (walaupun mungkin tidak mungkin tergantung pada TK). Poin penting lainnya terkait dengan penyelesaian masalah akses ke data yang sama untuk membaca dan menulis. Misalnya: sensor interogasi aliran menulis nilai yang diterima ke RTDB, dan saat ini aliran yang bertanggung jawab untuk memperbarui informasi pada layar membacanya. Di sini, mekanisme sinkronisasi yang disediakan sistem operasi akan membantu kami.
Ayo mulai merancang arsitektur aplikasi kita!
Database waktu nyata

Struktur biasa yang berisi kumpulan bidang atau array yang diperlukan dapat berfungsi sebagai basis seperti itu. Untuk mengakses "RTDB" kami akan menggunakan API, yang akan memungkinkan kami untuk menulis dan membaca data dari database. Sinkronisasi akses data di dalam fungsi API dapat dibangun di atas mutex yang disediakan oleh OS (atau menggunakan beberapa mekanisme lain).

Bekerja dengan sensor pada ban
Bekerja dengan sensor melibatkan hal-hal berikut:
- membaca data;
- pemrosesan data (jika perlu), yang meliputi:
- pemeriksaan validasi;
- scaling
- penyaringan
- validasi nilai yang valid;
- merekam data yang diterima dalam RTDB.
Semua pekerjaan ini dapat dilakukan dalam satu tugas.

"Port" - pelabuhan asli MK;
"Driver protokol" - driver protokol (misalnya, Modbus). Untuk driver seperti itu, disarankan untuk membuat antarmuka Anda dan bekerja melaluinya. Dalam kerangka antarmuka seperti itu, dimungkinkan untuk menerapkan kontrol akses ke sumber daya melalui mutex, seperti yang dilakukan untuk "RTDB". Beberapa pengembang mengusulkan untuk melakukan ini di tingkat port, untuk memastikan bahwa tidak ada orang lain yang akan menulis apa pun ke port ini saat kami mengirimkan paket Modbus kami melaluinya.
"Pembaca Sensor" - tugas (tugas), yang melakukan polling sensor, merapikan informasi yang diterima dan menulisnya ke "RTDB".
"RTDB" adalah database real-time yang dijelaskan di atas pada bagian yang sesuai.
Tulisan "Pr: 1" di atas tugas berarti prioritas, intinya adalah bahwa setiap tugas dapat memiliki prioritas jika dua tugas menunggu waktu prosesor memiliki prioritas yang berbeda, sumber daya akan menerima yang dengan prioritas lebih tinggi. Jika tugas memiliki prioritas yang sama, maka tugas dengan waktu tunggu yang lebih lama akan diluncurkan.
Bekerja dengan input diskrit
Secara umum, bekerja dengan input digital dapat diatur dengan cara yang sama seperti dengan sensor digital. Tetapi mungkin perlu untuk merespon perubahan status input dengan cepat. Misalnya, dengan satu sentuhan tombol, tutup output relai secepat mungkin. Dalam hal ini, lebih baik menggunakan pendekatan berikut: untuk memproses output relai, kami membuat tugas terpisah khusus dengan prioritas lebih tinggi daripada yang lain. Di dalam tugas ini adalah semafor yang ingin ditangkap. Interupsi dipicu untuk memicu input digital tertentu, di mana semaphore yang disebutkan di atas diatur ulang. Karena prioritas interupsi maksimum, maka fungsi yang terkait dengannya akan dieksekusi hampir seketika, dalam kasus kami, itu akan mengatur ulang semaphore, dan, setelah itu, tugas berikutnya dalam antrian eksekusi akan menjadi salah satu di mana relay dikendalikan (karena memiliki prioritas lebih tinggi daripada tugas lain dan kunci menunggu semaphore dihapus).
Beginilah tampilan skema subsistem ini.

Selain respons cepat untuk mengubah status input tertentu, Anda juga dapat mengatur tugas "pembaca DI" untuk membaca status input diskrit. Tugas ini dapat berupa independen atau dipanggil oleh timer.
Karya "Interrupt handler" dan "Relay controller" dalam bentuk diagram disajikan di bawah ini.

Menulis data ke media eksternal
Menulis data ke media eksternal secara ideologis sangat mirip dengan membaca data dari sensor digital, hanya pergerakan data yang dilakukan dalam arah yang berlawanan.

Kami membaca dari "RTDB" dan menulis melalui "Driver Store" ke media eksternal - bisa berupa kartu SD, USB flash drive atau yang lainnya. Sekali lagi, jangan lupa untuk menempatkan pembungkus mutex (atau alat lain untuk mengatur akses ke sumber daya) dalam fungsi antarmuka!
Memberikan akses ke data waktu-nyata
Poin penting adalah penyediaan data dari "RTDB" ke sistem eksternal. Ini bisa berupa hampir semua antarmuka dan protokol. Tidak seperti sejumlah subsistem yang dipertimbangkan, perbedaan utama dari ini adalah bahwa beberapa protokol yang banyak digunakan dalam sistem otomasi memiliki persyaratan khusus untuk waktu respons terhadap permintaan, jika jawabannya tidak tiba dalam waktu tertentu, maka dianggap tidak ada komunikasi, bahkan jika dia (jawabannya) akan datang setelah beberapa saat. Dan sejak itu akses ke "RTDB" dalam contoh kami mungkin diblokir sementara (oleh mutex), perlu untuk memberikan perlindungan bagi perangkat master eksternal (master adalah perangkat yang mencoba membaca data dari kami) dari pemblokiran tersebut. Perlu juga mempertimbangkan perlindungan perangkat itu sendiri dari kenyataan bahwa master akan menginterogasinya dengan frekuensi tinggi, sehingga menghambat pengoperasian sistem dengan membaca terus-menerus dari "RTDB". Salah satu solusinya adalah dengan menggunakan buffer perantara.

"Pembaru Data" membaca data dari "RTDB" pada frekuensi tertentu dan menambahkan apa yang dibaca dalam "cache Protokol", dari mana "Penangan protokol" akan mengambil data. Dalam hal ini, ada masalah pemblokiran pada tingkat cache protokol, untuk menyelesaikannya, Anda dapat membuat cache lain di mana "Protocol handler" akan menyimpan data jika tidak bisa membaca dari "cache protokol" yang diblokir, Anda juga dapat:
- jadikan "Handler protokol" prioritas yang lebih tinggi;
- menambah periode membaca dari "RTDB" untuk "Pembaru data" (yang merupakan solusi biasa-biasa saja).
Bekerja dengan antarmuka pengguna
Bekerja dengan antarmuka pengguna melibatkan memperbarui data di layar dan bekerja dengan keyboard. Arsitektur subsistem ini mungkin terlihat seperti ini.

Pekerja UI bertanggung jawab untuk membaca penekanan tombol, mengambil data dari "RTDB" dan memperbarui tampilan yang dilihat pengguna.
Struktur sistem umum
Sekarang lihat apa yang terjadi pada akhirnya.

Untuk menyeimbangkan beban, Anda dapat mengatur cache tambahan, seperti yang kami lakukan di subsistem yang bertanggung jawab untuk menyediakan akses ke sistem eksternal ini. Beberapa tugas transfer data dapat diselesaikan dengan menggunakan antrian, karena biasanya didukung oleh sistem operasi real-time (pasti, di FreeRTOS).
Itu saja, saya harap itu menarik.
PSSebagai literatur, saya akan merekomendasikan "Membuat Sistem Tertanam: Pola Desain untuk Perangkat Lunak Hebat" Elecia White dan artikel oleh
Andrey Kournits "FreeRTOS - sistem operasi untuk mikrokontroler"