Sedikit lagi tentang multitasking dalam mikrokontroler

Dalam artikel sebelumnya, saya berbicara tentang bagaimana, menurut penulis, adalah mungkin untuk memprogram tindakan mikrokontroler yang biasa secara real time, membaginya menjadi beberapa tugas yang independen (atau hampir independen) satu sama lain.


Sebuah mikrokontroler dipilih, dengan inti dari keluarga ARM Cortex M. yang sangat luas. Dari yang akrab bagi banyak orang, dan tidak hanya penulis, opsi dengan angka 0,3,4 dan 7, M4 dipilih, karena sudah dekat.


Dua pertimbangan yang mendorong kami untuk memulai jalan yang licin dan goyah dari “menciptakan sepeda,” seperti yang dikatakan oleh beberapa pembaca, sebenarnya sederhana. Yang pertama adalah kita masih harus hidup dan hidup dengan "korteks" ini. Dan yang kedua adalah mencoba untuk tidak melakukan sesuatu yang universal (mendapatkan ketenaran dan kekayaan), tetapi untuk melakukan sesuatu yang lebih sempit, berharap untuk mencapai efisiensi dan kesederhanaan. Mereka yang terkadang melakukan sesuatu dengan tangan mereka akan dengan mudah mengingat bahwa, sebagai suatu peraturan, obeng yang dipilih secara khusus lebih baik daripada yang diambil dari perangkat universal yang brilian.


Contoh assembler diberikan untuk menunjukkan bahwa tidak lebih dari 80 siklus clock dihabiskan untuk beralih. Dan pada kecepatan clock 72 megahertz ternyata sedikit lebih dari 1 mikrodetik. Jadi kutu, berukuran 50 mikrodetik, tidak akan semahal itu. Hanya 2 persen dari biaya overhead. Karena itu, seperti yang dikatakan salah satu karakter favorit penulis, "disarankan untuk menderita".


Jadi, kami memiliki tugas N, yang masing-masing dijamin menjalankan sepotong (centang T) waktu dan dijamin untuk mengulangi segmen ini selambat-lambatnya setelah (N-1) kutu T, ditambah penundaan yang tidak melebihi D. Penundaan yang mengganggu ini, untungnya , dibatasi oleh ukuran maksimum yang dimungkinkan dalam waktu, yang sama dengan jumlah durasi operasi semua interupsi yang diizinkan. Dengan kata lain, tugas yang memiliki gangguan paling potensial untuk periode tertentu sebelum kutu berikutnya adalah yang paling sial. Untuk waktu yang lebih lama, tugas tidak dapat ditunda. Dia pasti akan menerima slot waktunya selambat-lambatnya dalam (N-1) mikrodetik T + D. Menurut pendapat saya, ini disebut real-time yang sulit.


Tugas harus menyelesaikan tugasnya dan melaporkan implementasinya. Kepada siapa saya harus melapor? Rupanya, seseorang yang bertanggung jawab, dan itu terjadi, sebagai suatu peraturan, mereka jauh lebih kecil daripada bawahan (sebenarnya, penulis juga bertemu pengecualian ketika ada empat bos untuk tiga pekerja dengan kedua tangan kiri, yang hanya satu yang tahu dan menghormati kata " kecukupan ”).


Dan jika "Anda banyak, tetapi saya adalah satu", maka ini berarti antrian. Banyak yang akan mulai mendorong dan mencoba untuk lolos. Dan seseorang harus menunggu, lalu terlambat dan menjelaskan. Terlepas dari kenyataan bahwa ini semua tampak mengerikan, itu disebut indah: perjuangan untuk sumber daya. Antrian adalah solusi terkenal untuk semua. Saya tahu banyak orang yang tidak memberi makan roti - biarkan saya mengantre.


Tapi kita tidak bisa menunggu! Dalam arti, tugas. Mereka berasal dari real time yang sulit. Misalkan dua tugas membaca bacaan sekali setiap detik, dan yang ketiga harus mengukur sesuatu setiap 10 milidetik, menaruhnya di tumpukan, dan melaporkan ke atas. Dan mereka berkata kepadanya, "Katakan, kami belum selesai dengan koki."


Rupanya, Anda harus mengubah, untuk membuatnya lebih halus, untuk waktu yang tidak terlalu nyata (waktu nyata lunak).


Mari kita memiliki tugas khusus yang tahu bagaimana menunggu dan senang melakukannya. Sumber daya yang akan dilayani akan menjadi saluran komunikasi. Seperti yang Anda tahu, Anda tidak akan mendorong semuanya sekaligus.
Namun, Anda dapat segera mengetahui kecepatan saluran yang seharusnya sehingga tidak ada yang hilang. Untuk melakukan ini, Anda perlu mengetahui kinerja semua tugas graphomaniacs, pah, kami. Jelas, Anda juga harus menghitung ukuran buffer atau buffer dari mana semua paket akan dikirim (atau ke kanan).


Jika salurannya bukan satu, maka esensinya tidak berubah. Untuk setiap saluran, tugas terpisah hanya ditambahkan, yang dirancang untuk menunggu (dan, tentu saja, harapan dan kepercayaan).


Beberapa kata tentang saluran komunikasi dengan operator, atau lebih sederhana, dengan orang tersebut. Di sini salurannya adalah dua arah, tetapi arah luarnya paling menarik. Segera melakukan reservasi, ada satu keadaan yang, bahkan dengan keinginan kuat, tidak mungkin untuk dikecualikan. Ini kelebihan saluran. Selama pengujian, kita harus mencapainya dan harus memiliki mekanisme untuk melihat permulaannya. Saya tidak berpendapat, itu tidak baik untuk menipu, tetapi sedikit bisa ditinggalkan. Vaughn, Gerasim, menyalahgunakannya sama sekali.


Oleh karena itu, kami segera berasumsi bahwa pesan ke operator dari tugas mungkin hilang. Dan agar seseorang tahu tentang ini, kami akan memberi nomor mereka. Ini akan menentukan di mana dan berapa kali operator kami tidak memiliki apa-apa. Pada akhirnya, Anda selalu dapat melakukan sesuatu dalam kode, atau menambahkan dalam perhitungan, atau bahkan memasangnya dalam rangkaian listrik untuk memperbaiki situasi. Tampaknya, untuk saat ini, akan lebih mudah. Tapi, tentu saja, ini tidak perlu untuk aplikasi militer. Sejujurnya, kehilangan pesan tidak tampak seperti aib hanya saat debugging.


Sebagai contoh, mari kita memiliki antarmuka serial dupleks tanpa pengakuan pada 115200 baud. Misalnya, RS422 dalam konfigurasi "ekonomi" dua kabel - di sana, dua - kembali. Kemampuannya sekitar 10.000 byte per detik. Mari kita ambil ukuran pesan rata-rata untuk seseorang yang setara dengan 50 byte. Kami mendapatkan 200 pesan per detik atau satu pesan dalam 5 milidetik. Jika kita memiliki tiga tugas yang ingin mengkomunikasikan sesuatu, maka biarkan mereka melakukannya setiap 15 milidetik masing-masing. Rata-rata, tentu saja. Dan jika tidak rata-rata, maka perhitungan statistik serius atau percobaan skala penuh akan diperlukan. Pilih yang terakhir. Bagaimanapun, kita telah belajar mendeteksi pesan yang hilang dan akan melihat semuanya di layar emulator terminal.
Jadi, biarkan tiga tugas membuat pesan individual. Biarkan pesan berbeda dalam kepentingan atau urgensi konten dan tugas kami menempatkannya dalam buffer yang sesuai. Alokasikan ketiga buffer cincin ini untuk tiga tingkat urgensi seperti yang ditunjukkan pada Gambar 1.



Tugas keempat memilih dari buffer ini pesan sesuai dengan rencana kami yang disetujui dan mencoba untuk mengirimkannya. Jika pengiriman belum memungkinkan, maka tugas keempat memperkirakan seberapa banyak ia bisa tidur dan melakukannya. Setelah tidur, dia sudah memiliki ruang yang diperlukan di buffer cincin untuk dikirim.


Buffer berbagai urgensi, tentu saja, tidak menyimpan pesan sendiri, tetapi alamat mereka (tautan). Pada saat yang sama, tugas-tugas itu sendiri tidak perlu menunggu sama sekali. Ok Tidak, tidak juga. Itu tidak berhasil, dan inilah sebabnya. Masing-masing dari ketiga buffer cincin ini adalah sumber daya bersama. Bayangkan tugas 1 hendak meletakkan alamat di buffer tengah. Dia membaca kata itu, memeriksa apakah tempat itu kosong, artinya nilainya nol dan (saat ini dia digantikan oleh tugas lain 2, yang ingin melakukan hal yang persis sama dan dia berhasil), tugas pertama, kembali, meletakkan kata di sana, menimpa semua yang berhasil kedua. Ini adalah rekan kerja yang meminta kata-kata. Saya sepertinya tahu apa yang akan dia katakan.
-Ya, semuanya sangat sederhana, Anda dapat melarang gangguan selama tes dan tidak ada hal buruk yang akan terjadi, itu tidak lama.
- Benar, tidak lama, tapi berapa kali? Berapa banyak waktu yang akan kita ambil dari tugas itu? Dan yang mana dari mereka? Saya lupa untuk memperingatkan, kami tidak pernah melarang interupsi, sekte keras kami waktu nyata melarang kami untuk melakukan ini.
-Dan jika Anda tidak melarang interupsi, maka Anda dapat meminta saklar tugas kami untuk meletakkan alamat pesan di sana. Dia bisa melakukannya secara atom.
- Ya, mungkin, tapi kemudian saya ingin bertanya sesuatu yang lain, lalu yang lain. Lalu mengapa kita mencapai 72 derajat, kemudian mencairkan semuanya dengan air? Maaf, maksud saya 72 siklus untuk beralih konteks.
Mari kita coba melakukannya dengan lebih mudah, seperti pada Gambar 2.



Dalam hal ini, setiap tugas memiliki buffer sendiri atau set buffer sendiri, jika Anda menginginkan urgensi, keangkuhan dan kepentingan yang berbeda. Secara pribadi, saya, sebagai operator sederhana, masih memiliki kepentingan yang sama untuk semua orang.


Skema seperti itu tidak membuat Anda memperjuangkan sumber daya. Sekarang kami memiliki opsi yang sangat berfungsi. Hanya saja, tidak menyukainya. Tetapi bagaimana jika tugas-tugas di sebelah kiri dalam gambar tidak ada yang mengirim? Maka akan lebih bijaksana untuk meminta tugas di sebelah kanan untuk dibangunkan ketika alasan muncul, dan tidak bangun hanya untuk mengatur alarm lagi. Tugas di sebelah kiri lebih mudah dilakukan. Selain itu, fungsi yang membantu membangunkan teman disebutkan di pos sebelumnya.


Saya memperkirakan proposal rasionalisasi: "Biarkan interupsi dari port serial (UART) itu sendiri terlibat dalam tugas apa yang sedang dilakukan sekarang, akan ada penghematan." Anda dapat melakukan ini, tetapi saya rasa itu tidak baik. Saya akan mencoba mengklarifikasi. Tugas-tugas di sebelah kiri, memang, dapat dengan sendirinya mengaktifkan prosedur interupsi UART, dan itu akan mulai bekerja dan tidak akan berhenti sampai ia melakukan segalanya. Prosedur interupsi sekarang harus melakukan semua hal yang sebelumnya dilakukan oleh tugas 4. Waktu yang dibutuhkan untuk memproses interupsi akan membengkak, tidak ada satu tugas pun yang dapat dinyalakan sampai “spool” berikutnya selesai. Dan apa yang kita katakan kepada kawan-kawan kita dari lingkaran real-time yang gigih? Tetapi kami diberitahu bahwa respons terhadap gangguan eksternal harus sesingkat mungkin. Ini hanya nada yang bagus. Atau, dengan kata lain: perlu melakukan yang baik, buruk dan tanpa Anda itu akan berhasil.


Gambar 3 menjelaskan apa prosesnya dan tantangan apa yang ada.



Sekarang kita beralih ke situasi, bisa dikatakan, cermin. Inilah saatnya informasi datang dari luar. Jadikan itu saluran SPI dengan beberapa pendayung gondola dengan gondola dan orkestra string amatir kecil. Tidak, terlalu dini untuk berpikir tentang istirahat. Sisakan hanya antarmuka SPI dan beberapa chip. Misalnya, sensor tekanan atmosfer, akselerometer, dan memori yang tersimpan.


Saya harus mengatakan segera - contoh bodoh. Bukan karena gondoliero dengan keabadian mereka, "Aku harus menambahkan, Tuan-tuan." Tidak, itu bodoh, pada kenyataannya, untuk mencampurkan satu antarmuka data input yang begitu penting. Memang, jika Anda perlu mengetahui akselerasi, maka, tentu saja, untuk mengetahui dengan cepat kapan harus melepas pedal gas, atau memutar tutup, atau tutup mata Anda, akhirnya. Informasi ini sering dibutuhkan. Tapi tekanannya berubah perlahan-lahan dan harus terbang turun sekitar tiga meter, sehingga di peringkat bawah kehidupan akan menjadi lebih hangat.


Sedangkan untuk memori yang tersimpan, dan siapa yang umumnya menaruhnya di SPI ini? Apakah ada SPI kedua? Dan tidak diharapkan? Tidak ada tempat untuk pergi, sesuatu harus dilakukan. Arahkan panah ke arah yang berlawanan pada Gambar 2 dan mulailah berpikir.


Tugas 4 sekarang melayani SPI dan bangun hanya dengan sinyalnya. Koneksinya dengan tugas 1, yang ingin memasukkan sesuatu ke dalam memori yang tersimpan, diarahkan keluar dan dijalankan melalui antrian. Juga diperlukan untuk menyediakan mekanisme untuk memantau limpahan buffer cincin. Produksi nilai akselerasi dan tekanan tugas 4 harus menyediakan tanpa partisipasi dari dua tugas yang memakan. Anda hanya perlu berputar dan mengikuti. Sekarang kita dapat membuat sketsa gambar penjelasan dan menulis catatan penjelasan. Dalam Gambar 4, ini
tindakan ditampilkan secara skematis (atau blok diagram).



Underflow check - tindakan ini membantu Anda mengetahui apakah nilai percepatan punya waktu untuk berubah sebelum dibaca lagi oleh tugas yang menghabiskan. Pemeriksaan ini ditunjukkan oleh tindakan terpisah pada Gambar 4 hanya untuk menarik perhatian padanya. Bahkan, langkah ini terjadi bersamaan dengan membaca nilai accelerometer sesuai dengan skema, seperti yang ditunjukkan pada Gambar 5.



Perlu dicatat bahwa ada sumber daya bersama, karena tempat penyimpanan hasilnya juga merupakan indikator tindakan (semaphore). Ras dimungkinkan di sini, berbicara dalam bahasa sirkuit, tetapi bagi kami ini bukan penghilangan. Lagi pula, tergelincir ke pintu penutup kendaraan hanya dalam hidup dapat dianggap sebagai keberuntungan. Di sini kami dengan yakin akan menganggapnya sebagai penundaan.


Akses memori terjadi dalam porsi untuk membatasi waktu setiap langkah tersebut. Dengan demikian, kami akan memastikan pembacaan yang seragam dari nilai percepatan yang berubah dengan cepat, dan di antaranya kami akan mengurus sisanya.


Nah, sekarang tinggal mencari sesuatu yang cocok dari besi dan bereksperimen sebagaimana mestinya. Ini, saya pikir, akan menjadi cerita selanjutnya.

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


All Articles