Ketika menulis untuk kode MK lebih rumit daripada "berkedip cahaya", pengembang dihadapkan pada keterbatasan yang melekat dalam pemrograman linier dalam gaya "supercycle plus interrupts". Pemrosesan interupsi membutuhkan kecepatan dan keringkasan, yang mengarah pada penambahan flag pada kode dan menjadikan gaya proyek “super cycle dengan interupsi dan flag”.
Jika kompleksitas sistem bertambah, maka jumlah flag yang saling tergantung tumbuh secara eksponensial, dan proyek dengan cepat berubah menjadi “kode pasta” yang sulit dibaca dan dikelola.
Penggunaan sistem operasi real-time membantu untuk menyingkirkan "kode pasta" dan mengembalikan fleksibilitas dan pengelolaan ke proyek MK yang kompleks.
Beberapa sistem operasi real-time koperasi telah dikembangkan dan cukup populer untuk mikrokontroler AVR. Namun, semuanya ditulis dalam C atau Assembler dan tidak cocok untuk mereka yang memprogram MK di lingkungan BASCOM AVR, merampas mereka dari alat yang berguna untuk menulis aplikasi serius.
Untuk memperbaiki kekurangan ini, saya mengembangkan RTOS sederhana untuk lingkungan pemrograman BASCOM AVR, yang saya bawa ke perhatian pembaca.

Bagi banyak orang, gaya pemrograman MK yang akrab adalah yang disebut
sepeda super . Kode dalam hal ini terdiri dari serangkaian fungsi, prosedur, dan deskriptor (konstanta, variabel), mungkin yang perpustakaan, umumnya disebut "kode latar belakang", serta loop tak terbatas besar yang terlampir dalam konstruk
do-loop . Saat start up, peralatan dari MK itu sendiri dan perangkat eksternal diinisialisasi terlebih dahulu, konstanta dan nilai awal variabel diatur, dan kemudian kontrol ditransfer ke supercycle tak terbatas ini.
Kesederhanaan supercycle sudah jelas. Sebagian besar tugas dilakukan oleh MK, karena satu atau lain cara siklus. Kerugiannya juga jelas: jika beberapa perangkat atau sinyal membutuhkan reaksi segera, MK akan memberikannya tidak lebih cepat dari siklus yang berputar. Jika durasi sinyal lebih pendek dari periode siklus, sinyal seperti itu akan dilewati.
Pada contoh di bawah ini, kami ingin memeriksa apakah tombolnya
ditekan :
do
Tentunya, jika "beberapa kode" bekerja cukup lama, MK mungkin tidak memperhatikan tombol yang ditekan sebentar.
Untungnya, MK dilengkapi dengan sistem interupsi yang dapat menyelesaikan masalah ini: semua sinyal kritis dapat "digantung" pada interupsi dan pawang dapat ditulis untuk masing-masingnya. Jadi tingkat berikutnya muncul:
siklus super dengan gangguan .
Contoh di bawah ini menunjukkan struktur program dengan supercycle dan interupsi yang memproses klik tombol:
on button button_isr
Namun, menggunakan interupsi menimbulkan masalah baru: kode interrupt handler harus secepat dan sesingkat mungkin; di dalam interupsi, fungsionalitas MK terbatas. Karena AVR MK tidak memiliki sistem interupsi hierarkis, interupsi lain tidak dapat terjadi di dalam interupsi - AVR mereka dinonaktifkan pada saat ini. Jadi interupsi harus dieksekusi secepat mungkin, jika tidak interupsi lain (dan mungkin yang lebih penting) akan dilewati dan tidak diproses.
Memori interupsiBahkan, karena berada di dalam interupsi, MK dapat mencatat fakta interupsi lain dalam register khusus, yang memungkinkannya untuk diproses nanti. Namun, gangguan ini tidak dapat segera diproses.
Oleh karena itu, kita tidak dapat menulis sesuatu yang rumit dalam interrupt handler, terutama jika kode ini harus mengalami penundaan - karena sampai penundaan bekerja, MK tidak akan kembali ke program utama (supercycle) dan akan menjadi tuli terhadap gangguan lain.
Karena itu, di dalam interrupt handler Anda seringkali hanya perlu menandai fakta acara dengan bendera - milik Anda untuk setiap acara - dan kemudian memeriksa dan memproses bendera di dalam siklus super. Ini, tentu saja, memperpanjang waktu reaksi terhadap peristiwa tersebut, tetapi setidaknya kita tidak melewatkan sesuatu yang penting.
Dengan demikian, tingkat kerumitan berikutnya muncul -
supercycle dengan interupsi dan bendera .
Kode berikut ditunjukkan:
on button button_isr
Sejumlah besar program untuk MK dibatasi oleh hal ini. Namun, program semacam itu biasanya masih kurang lebih sederhana. Jika Anda menulis sesuatu yang lebih rumit, maka jumlah bendera mulai tumbuh seperti bola salju, dan kodenya menjadi semakin membingungkan dan tidak terbaca. Selain itu, dalam contoh di atas, masalah dengan keterlambatan belum terselesaikan. Tentu saja, Anda dapat "menggantung" interupsi terpisah pada timer, dan di dalamnya ... juga mengontrol berbagai flag. Tetapi ini membuat program ini benar-benar jelek, jumlah bendera yang saling bergantung tumbuh secara eksponensial, dan bahkan pengembang sendiri hampir tidak dapat menemukan "kode pasta" semacam itu dengan segera. Mencoba untuk menemukan kesalahan atau memodifikasi kode seringkali menjadi sama dalam upaya mengembangkan proyek baru.
Bagaimana mengatasi masalah "kode pasta" dan membuatnya lebih mudah dibaca dan dikelola? Sistem
operasi (OS) datang untuk menyelamatkan. Di dalamnya, fungsionalitas yang harus dilaksanakan MK dibagi menjadi tugas-tugas yang operasinya dikendalikan oleh OS.
Jenis sistem operasi untuk MK
Sistem operasi untuk MK dapat dibagi menjadi dua kelas besar: OS dengan crowding out dan OS kooperatif. Dalam salah satu dari sistem operasi ini, tugas dikontrol oleh prosedur khusus yang disebut
dispatcher . Dalam OS dengan
crowding out, operator secara independen setiap saat mengalihkan eksekusi dari satu tugas ke tugas lain, mengalokasikan masing-masing sejumlah siklus clock (mungkin berbeda, tergantung pada prioritas tugas). Pendekatan ini secara keseluruhan berfungsi dengan baik, memungkinkan Anda untuk tidak melihat konten tugas sama sekali: Anda dapat menulis setidaknya kode tugas
1: goto 1
- dan masih sisa tugas (termasuk yang ini) akan dilakukan. Namun, OS preemptive membutuhkan banyak sumber daya (memori prosesor dan siklus jam), karena setiap switch harus benar-benar menyimpan konteks tugas yang akan dinonaktifkan dan memuat konteks resume. Konteks di sini mengacu pada isi register mesin dan tumpukan (BASCOM menggunakan dua tumpukan - satu perangkat keras untuk alamat pengirim subprogram dan satu perangkat lunak untuk melewati argumen). Tidak hanya beban seperti itu yang membutuhkan banyak siklus prosesor, tetapi juga konteks dari setiap tugas perlu disimpan di suatu tempat untuk sementara waktu hingga bekerja. Dalam prosesor "besar", awalnya berorientasi pada multitasking, fungsi-fungsi ini sering didukung dalam perangkat keras, dan mereka memiliki lebih banyak sumber daya. Dalam AVR MK tidak ada dukungan perangkat keras untuk multitasking (semuanya perlu dilakukan "secara manual"), dan memori yang tersedia kecil. Oleh karena itu, mengganti OS, meskipun ada, tidak terlalu cocok untuk MK sederhana.
Hal lain adalah
OS kooperatif . Di sini tugas itu sendiri mengontrol pada titik apa untuk mentransfer kontrol ke operator, yang memungkinkannya untuk memulai tugas lain. Selain itu, tugas di sini diperlukan untuk melakukan ini - jika tidak, eksekusi kode akan macet. Di satu sisi, tampaknya pendekatan ini mengurangi keandalan keseluruhan: jika suatu tugas macet, ia tidak akan pernah memanggil operator, dan seluruh sistem akan berhenti merespons. Di sisi lain, kode linier atau supercycle tidak lebih baik dalam hal ini - karena mereka dapat membeku dengan risiko yang persis sama.
Namun, OS kooperatif memiliki keunggulan penting. Karena di sini programmer menentukan momen perpindahan dirinya, itu tidak dapat terjadi secara tiba-tiba, misalnya, ketika tugasnya bekerja dengan beberapa sumber daya atau di tengah menghitung ekspresi aritmatika. Oleh karena itu, dalam OS kooperatif, dalam banyak kasus, Anda dapat melakukannya tanpa mempertahankan konteksnya. Ini secara signifikan menghemat waktu dan memori prosesor, dan karenanya terlihat jauh lebih cocok untuk implementasi pada AVR MK.
Peralihan tugas dalam BASCOM AVR
Untuk mengimplementasikan pengalihan tugas dalam lingkungan BASCOM AVR, kode tugas, yang masing-masing diimplementasikan sebagai prosedur normal, di suatu tempat harus memanggil dispatcher - juga diimplementasikan sebagai prosedur normal.
Bayangkan bahwa kita memiliki dua tugas, yang masing-masing di beberapa tempat kodenya disebut oleh operator.
sub task1() do
Misalkan tugas 1 dieksekusi. Mari kita lihat apa yang terjadi pada stack ketika menjalankan "panggilan dispatcher":
kembalikan alamat ke kode utama (2 byte)
atas tumpukan -> kembalikan alamat ke Tugas 1 yang disebut dispatcher (2 byte)
Bagian atas tumpukan akan menunjuk ke alamat instruksi di Tugas 1, yang mengikuti panggilan dispatcher (instruksi
loop dalam contoh kita).
Tujuan dari dispatcher dalam kasus paling sederhana adalah untuk mentransfer kontrol ke Tugas 2. Pertanyaannya adalah bagaimana melakukan ini? (misalkan operator sudah tahu alamat Tugas 2).
Untuk melakukan ini, operator harus menarik alamat pengembalian ke Tugas 1 dari tumpukan (dan di suatu tempat untuk diingat), dan meletakkan alamat Tugas 2 di tempat ini di tumpukan, dan kemudian memberikan perintah kembali. Prosesor akan mengekstrak alamat yang ditempatkan di sana dari tumpukan dan, alih-alih kembali ke Tugas 1, akan melanjutkan ke pelaksanaan Tugas 2.
Pada gilirannya, ketika Tugas 2 memanggil operator, kami juga menarik tumpukan dan menyimpan alamat yang memungkinkan untuk kembali ke Tugas 2, dan memuat alamat tugas 1 yang disimpan sebelumnya ke tumpukan. Berikan perintah
kembali dan kami akan berada pada titik kelanjutan dari Tugas 1 .
Akibatnya, kami jadi berantakan:
Tugas 1 -> Dispatcher -> Tugas 2 -> Dispatcher -> Tugas 1 ....
Tidak buruk! Dan itu berhasil. Tapi, tentu saja, ini tidak cukup untuk OS yang secara praktis dapat digunakan. Lagi pula, tidak selalu dan tidak semua tugas harus bekerja - misalnya, mereka dapat
mengharapkan sesuatu (berakhirnya waktu tunda, penampilan beberapa sinyal, dll.). Jadi, tugas harus memiliki
status (KARYA, SIAP, DIHARAPKAN, dll.). Selain itu, alangkah baiknya jika tugas diberikan
prioritas . Kemudian, jika lebih dari satu tugas siap untuk dieksekusi, operator akan melanjutkan tugas yang memiliki prioritas tertinggi.
AQUA RTOS
Untuk mengimplementasikan ide yang diuraikan, koperasi OS AQUA RTOS dikembangkan, yang menyediakan layanan yang diperlukan untuk tugas-tugas dan memungkinkan penerapan multitasking koperasi dalam lingkungan AVR BASCOM.
Pemberitahuan Penting Mengenai Mode Prosedur di BASCOM AVRSebelum memulai deskripsi AUQA RTOS, harus dicatat bahwa lingkungan BASCOM AVR mendukung dua jenis prosedur pengalamatan. Ini diatur oleh submode config = new | tua
Dalam hal menentukan opsi lama, kompiler, pertama, akan mengkompilasi semua kode secara linear, terlepas dari apakah itu digunakan di suatu tempat atau tidak, dan kedua, prosedur tanpa argumen yang dirancang dalam gaya sub nama / sub akhir akan dianggap sebagai prosedur , ditata dengan gaya nama: / kembali. Ini memungkinkan kita untuk mengirimkan alamat prosedur sebagai label sebagai argumen ke prosedur lain dengan menggunakan pengubah bylabel. Ini juga berlaku untuk prosedur yang dirancang dalam gaya sub nama / gaya akhir sub (Anda harus memberikan nama prosedur sebagai label).
Pada saat yang sama, submode = mode lama memberlakukan beberapa batasan: prosedur tugas tidak boleh berisi argumen; kode file yang terhubung melalui $ include dimasukkan dalam proyek umum secara linier, oleh karena itu, bypass harus disediakan dalam file yang terhubung - mulai dari awal hingga akhir menggunakan goto dan label.
Dengan demikian, dalam AQUA RTOS, pengguna harus menggunakan hanya notasi prosedur lama dalam gaya task_name: / kembali untuk tugas, atau menggunakan sub nama / sub akhir yang lebih umum, menambahkan submode pengubah = tua pada awal kodenya, dan memotong di file yang disertakan label goto / sertakan kode file / label:.
Status tugas AQUA RTOS
Status berikut didefinisikan untuk tugas-tugas dalam AQUA RTOS:
OSTS_UNDEFINE OSTS_READY OSTS_RUN OSTS_DELAY OSTS_STOP OSTS_WAIT OSTS_PAUSE OSTS_RESTART
Jika tugas belum diinisialisasi, tugas ini diberikan status
OSTS_UNDEFINE .
Setelah inisialisasi, tugas memiliki status
OSTS_STOP .
Jika tugas
siap untuk dieksekusi , tugas itu diberikan status
OSTS_READY .
Tugas yang sedang berjalan memiliki status
OSTS_RUN .
Dari sana, ia dapat pergi ke status
OSTS_STOP, OSTS_READY, OSTS_DELAY, OSTS_WAIT, OSTS_PAUSE .
Status
OSTS_DELAY memiliki tugas yang memenuhi
penundaan .
Status
OSTS_WAIT ditugaskan untuk tugas-tugas yang
menunggu semafor, acara, atau pesan (lebih banyak tentang mereka di bawah).
Apa perbedaan antara
status OSTS_STOP dan
OSTS_PAUSED ?
Jika karena alasan tertentu tugas menerima status
OSTS_STOP , maka dimulainya kembali tugas tersebut (setelah menerima status
OSTS_READY ) akan dilakukan dari titik masuknya, yaitu. dari awal. Dari status
OSTS_PAUSE, tugas akan terus bekerja di tempat ditangguhkan.
Manajemen Status Tugas
Baik OS itu sendiri dapat secara otomatis mengelola tugas, serta pengguna, dengan memanggil layanan OS. Ada beberapa layanan manajemen tugas (nama-nama semua layanan OS dimulai dengan awalan
OS_ ):
OS_InitTask(task_label, task_prio) OS_Stop() OS_StopTask(task_label) OS_Pause() OS_PauseTask(task_label) OS_Resume() OS_ResumeTask(task_label) OS_Restart()
Masing-masing dari mereka memiliki dua opsi:
OS_service dan
OS_serviceTask (kecuali untuk layanan
OS_InitTask , yang hanya memiliki satu opsi; layanan
OS_Init menginisialisasi OS itu sendiri).
Apa perbedaan antara
OS_service dan
OS_serviceTask ? Metode pertama bertindak pada tugas itu sendiri yang menyebabkannya; yang kedua memungkinkan Anda untuk mengatur sebagai argumen penunjuk ke tugas lain dan, dengan demikian, untuk mengelola yang lain dari satu tugas.
Tentang OS_ResumeSemua layanan manajemen tugas, kecuali OS_Resume dan OS_ResumeTask, secara otomatis memanggil pengelola tugas setelah pemrosesan. Sebaliknya, layanan OS_Resume * hanya mengatur status tugas ke OSTS_READY. Status ini akan diproses hanya ketika operator secara eksplisit dipanggil.
Prioritas dan antrian tugas
Seperti disebutkan di atas, dalam sistem nyata, beberapa tugas mungkin lebih penting, sementara yang lain mungkin sekunder. Oleh karena itu, fitur yang berguna dari OS adalah kemampuan untuk menetapkan prioritas tugas. Dalam hal ini, jika ada beberapa tugas
siap pakai pada saat yang sama, OS pertama akan memilih tugas dengan prioritas tertinggi. Jika
semua tugas jadi memiliki prioritas yang sama, OS akan menjalankannya dalam lingkaran, dalam urutan yang disebut "carousel" atau round-robin.
Dalam AQUA RTOS, prioritas diberikan ke tugas ketika
diparaf melalui panggilan ke layanan
OS_InitTask , yang
menerima alamat tugas sebagai argumen pertama dan angka dari 1 hingga 15 sebagai argumen kedua.
Angka yang lebih rendah berarti prioritas yang lebih tinggi . Selama pengoperasian OS, perubahan prioritas yang ditugaskan untuk tugas tidak disediakan.
Keterlambatan
Dalam setiap tugas, penundaan diproses secara terpisah dari tugas-tugas lain.
Jadi, sementara OS sedang mengerjakan penundaan satu tugas, yang lain dapat dieksekusi.
Untuk organisasi keterlambatan disediakan layanan
OS_Delay | OS_DelayTask . Argumennya adalah jumlah milidetik yang tugasnya
ditunda . Karena dimensi argumen adalah
dword , penundaan maksimum adalah 4294967295 ms, atau sekitar 120 jam, yang tampaknya cukup untuk sebagian besar aplikasi. Setelah memanggil layanan penundaan, operator dipanggil secara otomatis, yang mentransfer kontrol ke tugas-tugas lain selama durasi penundaan.
Semafor
Semafor dalam AQUA RTOS adalah sesuatu seperti flag dan variabel yang tersedia untuk tugas. Mereka ada dua jenis - biner dan dapat dihitung. Yang pertama hanya memiliki dua status: gratis dan tertutup. Yang kedua adalah byte counter (layanan penghitungan semaphores dalam versi AQUA RTOS saat ini tidak diterapkan (saya seorang pemalas), jadi semua yang dikatakan di bawah ini hanya berlaku untuk semaphore biner).
Perbedaan antara semafor dan bendera sederhana adalah bahwa tugas dapat dibuat untuk
menunggu rilis semafor yang ditentukan. Dalam beberapa hal, penggunaan semaphore benar-benar menyerupai jalur kereta api: setelah mencapai semaphore, komposisi (tugas) akan memeriksa semaphore, dan jika tidak terbuka, itu akan menunggu sinyal yang memungkinkan untuk muncul untuk melangkah lebih jauh. Pada saat ini, kereta lain (tugas) dapat terus bergerak (lari).
Dalam hal ini, semua pekerjaan hitam ditugaskan ke operator. Segera setelah tugas disuruh menunggu semafor, kontrol secara otomatis ditransfer ke operator, dan dia dapat memulai tugas lain - tepat sampai semafor yang ditentukan dibebaskan. Segera setelah status semafor berubah menjadi
bebas , operator akan memberikan semua tugas yang menunggu semafor ini menjadi status
siap (
OSTS_READY ), dan tugas tersebut akan dieksekusi dalam urutan prioritas dan prioritas.
Secara total, AQUA RTOS menyediakan 16 semaphore biner (angka ini pada prinsipnya dapat ditingkatkan dengan mengubah dimensi variabel di unit kontrol tugas, karena di dalamnya diimplementasikan sebagai bit flags).
Semaphore biner bekerja melalui layanan berikut:
hBSem OS_CreateBSemaphore() OS_WaitBSemaphore(hBSem) OS_WaitBSemaphoreTask(task_label, hBSem) OS_BusyBSemaphore(hBSem) OS_FreeBSemaphore(hBSem)
Sebelum menggunakan semaphore harus
dibuat . Ini dilakukan dengan memanggil layanan
OS_CreateBSemaphore , yang mengembalikan pengidentifikasi byte unik (pegangan) dari semaphore
hBSem yang dibuat, atau melalui handler yang ditentukan pengguna menghasilkan kesalahan
OSERR_BSEM_MAX_REACHED , yang menunjukkan bahwa jumlah semafor biner biner maksimum yang mungkin telah dicapai.
Anda dapat bekerja dengan pengenal yang diterima dengan mengirimkannya sebagai argumen ke layanan semafor lainnya.
Layanan
OS_WaitBSemaphore | OS_WaitBSemaphoreTask menempatkan tugas (saat ini | ditentukan) dalam keadaan untuk
menunggu rilis semafor hBSem jika semafor ini sibuk, dan kemudian mentransfer kontrol ke operator sehingga dapat memulai tugas-tugas lain. Jika semaphore gratis, kontrol transfer tidak terjadi, dan tugas hanya berlanjut.
Layanan
OS_BusyBSemaphore dan
OS_FreeBSemaphore mengatur semaphore
hBSem menjadi
sibuk atau
bebas, masing-masing.
Penghancuran semaphores untuk menyederhanakan OS dan mengurangi jumlah kode tidak disediakan. Dengan demikian, semua semaphores yang dibuat bersifat statis.
Acara
Selain semafor, tugas dapat didorong oleh peristiwa. Satu tugas dapat diinstruksikan untuk
mengharapkan peristiwa tertentu , dan tugas lain (serta kode latar belakang) dapat
memberi sinyal acara ini. Pada saat yang sama, semua tugas yang menunggu acara ini akan menerima status
siap dieksekusi (
OSTS_READY ) dan akan ditetapkan oleh operator untuk dieksekusi dalam urutan prioritas dan prioritas.
Peristiwa apa yang bisa ditanggapi tugas? Nah, misalnya:
- gangguan;
- terjadinya kesalahan;
- pelepasan sumber daya (kadang-kadang lebih mudah untuk menggunakan semaphore untuk ini);
- mengubah status jalur I / O atau menekan tombol pada keyboard;
- menerima atau mengirim karakter melalui RS-232;
- transfer informasi dari satu bagian aplikasi ke yang lain (lihat juga pesan).
Sistem acara diimplementasikan melalui layanan berikut:
hEvent OS_CreateEvent() OS_WaitEvent(hEvent) OS_WaitEventTask(task_label, hEvent) OS_WaitEventTO(hEvent, dwTimeout) OS_SignalEvent(hEvent)
Sebelum menggunakan suatu acara, Anda harus
membuatnya . Ini dilakukan dengan memanggil fungsi
OS_CreateEvent , yang mengembalikan pengidentifikasi byte unik (handle) untuk acara
hEvent , atau melempar kesalahan
OSERR_EVENT_MAX_REACHED melalui handler yang ditentukan pengguna, menunjukkan bahwa batas jumlah kejadian yang dapat dihasilkan dalam OS telah tercapai (maksimum 255 peristiwa berbeda).
Untuk membuat tugas menunggu acara
hEvent , panggil
OS_WaitEvent dalam kodenya, dengan meneruskan gagang acara sebagai argumen. Setelah memanggil layanan ini, kontrol akan ditransfer secara otomatis ke operator.
Berbeda dengan layanan semaphore, layanan acara menyediakan opsi untuk menunggu acara dengan
batas waktu . Untuk melakukan ini, gunakan layanan
OS_WaitEventTO . Argumen kedua di sini Anda dapat menentukan jumlah milidetik yang tugasnya harapkan terjadi. Jika waktu yang ditentukan telah kedaluwarsa, tugas akan menerima status
siap untuk dieksekusi seolah-olah acara telah terjadi, dan akan ditetapkan oleh operator untuk melanjutkan eksekusi dalam urutan prioritas dan prioritas. Tugas tersebut dapat mempelajari tentang fakta bahwa itu bukan peristiwa, tetapi batas waktu, dengan memeriksa bendera global
OS_TIMEOUT .
OS_SignalEvent , . , ,
, .
, : , – .
:
hTopic OS_CreateMessage() OS_WaitMessage(hTopic) OS_WaitMessageTask(task_label, hTopic) OS_WaitMessageTO(hTopic, dwTimeout) OS_SendMessage(hTopic, wMessage) word_ptr OS_GetMessage(hTopic) word_ptr OS_PeekMessage(hTopic) string OS_GetMessageString(hTopic) string OS_PeekMessageString(hTopic)
,
.
OS_CreateMessage ,
hTopic ,
OSERR_TOPIC_MAX_REACHED , , , .
hTopic ,
OS_WaitMessage , . . ,
hTopic .
OS_WaitMessageTO OS_WaitEventTO .
OS_SendMessage . , , –
word . ,
, , , .
, BASCOM
varptr , , :
strMessage = "Hello, world!" OS_SendMessage hTopic, varptr (strMessage)
OS_WaitMessage , , , , — . .
word , , , .
OS_GetMessage ,
OS_PeekMessage .
, ,
OS_GetMessageString OS_PeekMessageString , , , .
AQUA RTOS
TIMER0 . , ( ) . , .. . 1 .
AQUA RTOS
, .
OS_SIM = TRUE | FALSE , .
,
OS_MAX_TASK , . , ( ), . , .
, .AQUA RTOS .
OS_Init . . , – . , , – .
( ) – , . , - .
, AQUA RTOS :
OS_Init my_err_trap
, :
OS_InitTask task_1, 1 OS_InitTask task_2 , 1
, , Arduino Nano V3. - (, test), bas-:
D4 D5 Arduino ( , - ). 100...500
GND . . 2 0,66 .
. , ( , aliases), – , – .
«», « » (, – - , , ; ).
OS_ResumeTask .
, . ? , ! . , , ,
end .
. ,
do – loop . – , , – , .
OS_Delay . , .
OS_SIM = TRUE , , , .
, , , « », . , « », .
, (,
task_1 ), (
end )
task_1 , ,
return , – ,
task_1 (
do task_1 ).
task_1 , ,
OS_delay , , , .
, ,
task_1 ( ,
OS_delay , ..
loop ), , « », ,
task_2 .
task_2 (
do task_2 )
return , – ,
task_2 .
task_2 , ,
OS_delay , , , .
, ,
task_1 ( ,
OS_delay , ..
loop ), , « », ,
task_2 . ,
task_1 , , . (
loop task_1 ), .
task_1 loop , « 1 – – 2 – » .
.
:
task 1
task 2 is waiting messages…
task 1
task 1
task 1
task 1 is sending message to task 2
task 1
message recieved: Hello, task 2!
task 2 is waiting messages…
task 1
task 1
...
, . 1
task 1 , , . 2
task 2 is waiting messages... ,
hTopic , , 1.
task 1 . , , 2 , 1
incr , .
task_1_cnt 1 , , –
loop task 1 . , , 2 , . .
:
AQUA RTOS
, . ; , , . , : , 95…97°; (, GSM-), .
« + + » , . , .
:
- – ControlHeater()
- – ShowGoods()
- / – AcceptMoney()
- – ScanKeys()
- – MakeChange()
- – ReleaseCoffee()
- – Alarm()
.
ControlHeater() , . , , . . 5.
ShowGoods() . , - . 8, .
ScanKeys() , . 3, 40 .
AcceptMoney() . ,
ScanKeys(), 20 .
MakeChange () .
ReleaseCoffee() 10.
ReleaseCoffee() , . 2.
– ,
Alarm() – 1, , .
, . , EEPROM , .
RTOS : ( , ) – .
,
ReleaseCoffee() :
sub ReleaseCoffee() do OS_WaitMessage bCoffeeSelection wItem = OS_GetMessage(bCoffeeSelection) Release wItem loop end sub
ReleaseCoffee bCoffeeSelection , ( , ). ,
ReleaseCoffee() , , ( )
wItem OS_GetMessage .
ReleaseCoffee() , :
dim bCoffeeSelection as byte bCoffeeSelection = OS_CreateMessage()
,
ShowGoods() .
ReleaseCoffee() , . :
dim bGoodsReliased as byte bGoodsReliased = OS_CreateEvent()
ReleaseCoffee() Release wItem bGoodsReliased :
OS_SignalEvent bGoodsReliased
, , , , .
OS_Init :
OS_Init Mailfuncion
– , :
sub Mailfuncion (bCoffeeErr) print "Mailfunction! Error #: "; bCoffeeErr if isErrCritical (bCoffeeErr) = 1 then CallService(bCoffeeErr) end if end sub
( - : , GSM- ..), , , .
, , .. , . ,
OS_InitTask :
OS_InitTask ControlHeater , 5 OS_InitTask ShowGoods , 8 OS_InitTask AcceptMoney , 3 OS_InitTask ScanKeys , 3 OS_InitTask MakeChange, 10 OS_InitTask ReleaseCoffee , 2 OS_InitTask Alarm , 1
, , , , . . ,
OS_ResumeTask « »:
OS_ResumeTask ControlHeater OS_ResumeTask ShowGoods OS_ResumeTask AcceptMoney OS_ResumeTask ScanKeys OS_ResumeTask MakeChange OS_ResumeTask ReleaseCoffee OS_ResumeTask Alarm
, ; «» .
OS_ResumeTask ( ), . , , , .
, . :
OS_Sheduler
end – .
:
, , .
OS_SendMessage() , /. . , , , , .
AQUA RTOS
1.05Q: AQUA?A: , , « », , . , , , , « » WiFi-. , , , EEPROM , , - . . – « », , . , . AQUA.
Q: ?A: . , , , , , . , . , , , , , , -, . , . , - ( ? – ) . .