Halo teman-teman!Nikolay bersama Anda lagi, dalam artikel terakhir "
DevBoy - bagaimana saya membuat proyek perangkat sumber terbuka dan meluncurkan proyek di Kickstarter ", penekanannya lebih pada penampilan dan perangkat keras, hari ini kita akan berbicara tentang bagaimana hal ini dilakukan "
di dalam " dan menganalisis bagian perangkat lunak.

Siapa yang peduli - saya minta kucing.
Seperti disebutkan sebelumnya, proyek ini didasarkan pada mikrokontroler
STM32F415RG dari STMicroelectronics pada inti ARM Cortex-M4. Ada beberapa IDE berbeda untuk mengembangkan mikrokontroler untuk mikrokontroler ini, namun, untuk proyek open source Anda memerlukan setidaknya IDE gratis, dan lebih disukai Open Source. Selain itu, IDE harus tetap didukung di
STM32CubeMX . Pada saat saya mulai mengerjakan proyek ini, hanya ada satu IDE yang memenuhi semua persyaratan ini -
System Workbench for STM32 .
Saat ini, ada Atollic TrueStudio, yang menjadi gratis setelah STMicroelectronics membelinya.
Program selanjutnya yang digunakan adalah
STM32CubeMX . Program ini adalah utilitas untuk mengkonfigurasi periferal mikrokontroler menggunakan antarmuka grafis.

Hasilnya adalah kode yang mencakup
H ardware
A bstraction
L ayer (HAL). Banyak programmer tidak benar-benar menyukai "
kreasi " ini, ini bukan tanpa bug, tetapi, bagaimanapun, ia sangat menyederhanakan pengembangan dan meningkatkan portabilitas program antara mikrokontroler yang berbeda dari STMicroelectronics.
Selain itu, selama konfigurasi, Anda dapat menentukan penggunaan beberapa perangkat lunak sumber terbuka pihak ketiga seperti
FreeRTOS ,
FatFS, dan beberapa lainnya.
Kami telah menyelesaikan deskripsi perangkat lunak yang digunakan, sekarang mari kita beralih ke bagian yang paling menarik -
DevCore . Nama berasal dari "
Pengembangan Inti ", mari kita mulai.
Pertama-tama, itu adalah
C ++ RTOS Wrapper (
FreeRTOS dalam hal ini ). Vrapper diperlukan karena dua alasan:
- Jauh lebih baik untuk membuat objek, dan kemudian memanggil mutex. Ambil () misalnya, daripada membuat pegangan, panggil fungsi buat, dan kemudian meneruskan pegangan ini ke semua fungsi mutex
- Jika perlu mengganti RTOS, cukup untuk mengganti pembungkus, dan tidak semua panggilan ke fungsi RTOS dari kode.
Tidak masuk akal untuk membawa kode pembungkus ke sini, siapa yang peduli -
kita melihat GitHub , dan kita melanjutkan.
Bagian selanjutnya adalah
Kerangka Aplikasi . Ini adalah kelas dasar untuk semua tugas. Karena ini hanya dua file yang relatif kecil, masuk akal untuk mendaftarkannya sepenuhnya:
Kelas yang diwariskan dapat menimpa 4 fungsi virtual:
- Setup () adalah fungsi yang dipanggil sebelum memulai tugas. Kelengkapan kode dijamin dalam semua fungsi ini dari semua tugas sebelum pelaksanaan siklus utama.
- Loop () - siklus tugas utama, di mana tugas itu sendiri mengatur apa yang diinginkan. Tidak dapat digunakan bersamaan dengan dua fungsi berikut.
- TimerExpired () - fungsi yang disebut secara berkala dengan interval yang diberikan. Nyaman untuk menerapkan polling sensor misalnya.
- ProcessMessage () - berfungsi untuk memproses pesan dari tugas lain.
Dua fungsi pertama mengimplementasikan "
Arduino-Style " untuk tugas.
Dua berikutnya menerapkan sistem "
acara " menyederhanakan interaksi tugas. Dengan pendekatan ini, tugas mengimplementasikan antarmuka eksternal dalam bentuk fungsi yang mengirim data kirim ke tugas melalui kotak surat internal. Dengan pendekatan ini, pengguna yang menggunakan antarmuka ini tidak perlu khawatir dalam konteks apa tindakan dilakukan. Benar, ini hanya mungkin untuk setter atau tim. Untuk getter, yang terbaik adalah menggunakan mutex dan menyalin data untuk mencegah penangkapan mutex untuk waktu yang lama.
Pendekatan ini terlihat ketika saya sedang mengembangkan perangkat lunak untuk peralatan medis. Mikrokontroler memiliki satu
anjing penjaga, dan dalam hal banyak tugas, Anda perlu melacak semuanya. Untuk ini, ada tugas terpisah yang melayani anjing penjaga dan menerima pesan dari tugas lain yang dikirim dari fungsi TimerExpired (). Jika selama periode waktu tugas * n tidak ada pesan, tugas mati, kami
mematikan lampu dan mengambil tindakan untuk mematikan semua kelenjar yang mempengaruhi pasien.
Semua tugas adalah tunggal, Anda tidak dapat membuatnya secara langsung, tetapi Anda bisa mendapatkan tautan ke tugas tersebut. Untuk melakukan ini, setiap tugas mengimplementasikan metode
GetInstance () statis:
Juga termasuk tugas-tugas untuk
output audio , untuk
modul input dan untuk
pemeliharaan layar.Tugas
output suara cukup sederhana - ia menerima serangkaian frekuensi dan durasi dan secara berkala mengubah pengaturan timer untuk menghasilkan pulsa persegi panjang dari frekuensi tertentu.
Tugas servis
modul air juga cukup sederhana. Dari titik-titik menarik, modul secara otomatis terdeteksi: pertama, menggunakan ADC, kami mengukur voltase, jika berada dalam kisaran 25% hingga 75% dari tegangan suplai, joystick analog dimasukkan, jika tidak tombol atau encoder. Jika ini bukan joystick, periksa baris keempat modul I / O: jika berada pada level tinggi, ini adalah tombol (
semua tombol ditarik ke daya dan, ketika tombol ditekan, ditutup ke tanah ), jika rendah, ini adalah encoder (
tombol kecil "ditarik ke atas" ke tanah dan ketika ditekan menutup ke daya ).
Tugas pemeliharaan layar adalah tugas yang paling menarik. Untuk memulainya, layarnya berukuran 320x240x16bit, jadi Anda perlu 153600 byte untuk framebuffer. Ini bukan hanya banyak, ini sangat besar - dalam mikrokontroler ini hanya ada 192k RAM, dan dalam mikrokontroler mungkin lebih mudah untuk tidak memiliki ukuran yang tepat sama sekali. Bagaimana menjadi? Jawabannya sederhana: gambarkan layar menjadi beberapa bagian! Tetapi Anda dapat menggambar sesuatu dengan cara yang berbeda ...Solusi yang saya terapkan untuk tugas ini sama seperti semua yang cerdik. Ini memiliki buffer pada dua garis layar. Kami menggambar semua yang seharusnya berada dalam satu baris, mengirimkannya ke layar melalui SPI dalam mode DMA, dan saat ini kami dapat menyiapkan baris lain.Bagaimana tugas tahu apa yang harus ada dalam barisan dan bagaimana cara menggambarnya? Tapi dia tidak tahu!Tapi dia punya daftar benda yang tahu cara menggambar dirinya sendiri. Setiap objek tersebut diwarisi dari kelas VisObject .Tugas pemeliharaan layar untuk setiap baris melewati daftar objek dan memanggil fungsi DrawInBufW (), meneruskannya dengan pointer ke buffer, jumlah titik, garis yang akan ditarik, dan posisi awal ( sampai ide menggunakan mode pengontrol layar untuk memperbarui "jendela" digunakan ). Faktanya, setiap objek menggambar dirinya sendiri di atas yang lain yang sudah digambar dan mudah untuk mengatur objek dalam urutan yang diperlukan hanya dengan menempatkannya di posisi yang diinginkan dalam daftar.Selain itu, pendekatan ini membuatnya mudah untuk mengintegrasikan pemrosesan objek aktif - setelah menerima koordinat dari pengontrol layar sentuh, tugas perawatan layar dapat melalui lembar kerja dari ujung untuk mencari objek aktif yang jatuh ke dalam koordinat penekanan. Jika objek tersebut ditemukan, fungsi virtual Action () dipanggil untuk objek yang diberikan.Saat ini, ada objek untuk garis, primitif ( garis, persegi, lingkaran ), gambar dan peta ubin ( untuk membuat game ).Juga di DevCore memasuki kode lain untuk beberapa elemen UI ( seperti menu ), antarmuka untuk driver I2C, sopir I2C dan perpustakaan untuk bekerja dengan sensor BME280 dan EEPROM 24S256, tetapi tidak begitu menarik, namun saya tidak akan menjelaskan - dan ternyata cukup besar .Kode lengkap tersedia tanpa registrasi dan SMS di GitHub : https://github.com/nickshl/devboyPS Rupanya, perusahaan pergi ke Epic Fail. Pada minggu pertama, hanya tiga tukang roti, termasuk satu dolar dari semacam " Dana Inovasi", $ 180 dari seseorang yang mungkin belajar tentang proyek ini dari sebuah artikel tentang Habré ( Terima kasih, Andrey! ) Dan sisanya dari rekan saya dari kubus tetangga.Tidak mengumpulkan uang bukanlah masalah. Masalahnya adalah kurangnya minat pada proyek ...