Beralih ke RTOS di RP2040
(blog.brixit.nl)- Karena pengontrol peralatan video berbasis Raspberry Pi Pico membutuhkan banyak pekerjaan bersamaan, struktur perangkat lunaknya menjadi sulit ditangani hanya dengan pico-sdk dan pemisahan dual-core
- Pengontrol ini menangani RS-485 VISCA, Ethernet, 9 tombol RGB, joystick, dan layar sekaligus, serta perlu memproses DHCP, mDNS, dan protokol ATEM berbasis UDP
- FreeRTOS memungkinkan sebagian implementasi melalui scheduler dan komunikasi antartask, tetapi debugging dan penggunaan ulang kode sulit karena masalah printf yang berhenti dan kurangnya abstraksi perangkat keras
- Apache NuttX menyediakan shell, filesystem, abstraksi perangkat seperti
/dev/i2c0, dan konfigurasi Kconfig, tetapi masalah I2C belakangan dikoreksi sebagai kesalahan konfigurasi sehingga sebagian besar evaluasi saat itu mungkin tidak valid - Zephyr terhambat oleh repositori dan SDK berukuran 5GB, definisi board, serta kompleksitas build; akhirnya pilihan condong untuk terus mencoba FreeRTOS karena paling sederhana ditempelkan ke lingkungan yang sudah ada
Mengapa RTOS menjadi diperlukan
- Beberapa proyek mikrokontroler kecil sedang dibuat dengan berpusat pada board Raspberry Pi Pico
- Pico mudah diintegrasikan dengan IDE berkat SDK yang memadai, perangkat keras murah, serta dukungan debugging gdb/openocd
- Proyek saat ini adalah pengontrol perangkat keras untuk mengendalikan beberapa peralatan video
- Perangkat yang dikendalikan adalah 2 kamera PTZ bermotor, 1 kamera tetap, dan peralatan video switching yang terhubung
- Pengontrol kamera PTZ yang ada adalah panel tanpa merek yang mirip Marshall VS-PTC-200
- Beberapa tahun lalu harganya €650, tetapi rasa tombol dan kualitas joystick analognya kurang baik
- Banyak tombol tidak berfungsi pada kamera yang sedang digunakan, dan tampaknya dioptimalkan untuk kamera keamanan
- Terhubung ke kamera melalui bus RS-485
- Kontrol video switcher ATEM saat ini hanya dilakukan lewat panel perangkat lunak di komputer
- Panel perangkat keras dari Blackmagic Design sangat mahal
Konfigurasi perangkat keras pengontrol
- Desain minimum ditetapkan berupa 9 tombol, joystick, dan layar untuk antarmuka pengguna
- Setelah mengulang desain perangkat keras beberapa kali selama 1 tahun, PCB akhirnya tersedia
- 9 tombol RGB
- Joystick seharga $10 yang juga ada di panel tiruan Marshall
- TP8485E untuk berkomunikasi dengan kamera PTZ melalui RS-485
- Modul Wiznet W5500 untuk berkomunikasi dengan video switcher melalui Ethernet
- Setelah berbagai revisi board, semua komponen perangkat keras akhirnya berfungsi, tetapi bagian yang lebih sulit adalah perangkat lunaknya
Perangkat lunak mulai kewalahan hanya dengan pico-sdk
- Seperti proyek RP2040 sebelumnya, proyek dimulai dengan cara mengambil pico-sdk dari proyek cmake
- Untuk membuatnya berjalan pada tingkat yang bisa digunakan, core kedua Pico dialokasikan untuk menangani modul Wiznet, sementara core pertama menangani I/O antarmuka pengguna
- Kedipan LED dan implementasi klien DHCP yang berjalan di core kedua masih bisa dilakukan
- Implementasi sisa sistem menjadi jauh lebih rumit
- Pekerjaan yang harus diproses secara bersamaan meningkat cepat
- Menggambar antarmuka pengguna yang cukup mulus di layar
- Mengirim perintah VISCA melalui antarmuka RS-485
- Merespons input tombol
- Menjaga network stack yang mencakup beberapa koneksi
- Sisi jaringan membutuhkan pekerjaan background tersendiri
- Dukungan DHCP yang sesuai standar harus melacak waktu kedaluwarsa dan sesekali berkomunikasi dengan server DHCP untuk mempertahankan status lease
- mDNS diperlukan untuk menemukan otomatis IP video switcher ATEM, dan akan bagus jika keberadaan panel kontrol juga bisa diumumkan
- Protokol ATEM sederhana, tetapi terkadang menerima data yang melebihi ukuran buffer modul Wiznet, dan jika pengiriman datagram UDP berhenti, timeout pemutusan koneksinya sangat singkat
- Dalam kondisi seperti ini, membagi pekerjaan dengan RTOS tampak lebih tepat daripada terus menumpuk loop sendiri
FreeRTOS: sederhana tetapi kurang abstraksi
- FreeRTOS secara teknis disertakan di dalam pico-sdk, tetapi tutorial memakai cara mengunduh salinan baru, jadi cara itu diikuti apa adanya
- Di antara RTOS yang ditinjau, FreeRTOS tampak paling sederhana, dan terutama menyediakan scheduler serta komunikasi antartask
- Strukturnya membuat task dengan
xTaskCreatelalu memulai scheduler denganvTaskStartScheduler - IPC dapat digunakan dalam bentuk mengirim status tombol ke task LED menggunakan queue
- Strukturnya membuat task dengan
- Setelah digunakan beberapa hari, codebase terbagi ke banyak task meskipun fitur nyata masih sedikit
buttonsTask: melakukan polling GPIO expander I2C untuk memeriksa input tombol dan memasukkan pesan ke queue tombolledTask: mengatur warna RGB tombol tertentu berdasarkan pesanledQueuemainTask: menjalankan loop utama yang memperbarui status proyek sesuai input tombolnetworkTask: berkomunikasi dengan modul WiznetdhcpTask: dibuat olehnetworkTasksaat kabel jaringan terhubungmdnsTask: dibuat olehdhcpTasksetelah mendapatkan alamat IPatemTask: dibuat saat mDNS menerima respons perangkat ATEMviscaTask: belum melakukan apa pun, tetapi harus mengirim data melalui port RS-485
- Jumlah task menjadi banyak meskipun perangkat keras belum melakukan apa pun selain muncul di jaringan
- Masalah paling merepotkan adalah printf selalu menyebabkan berhenti
- Debugger gdb berfungsi, tetapi tidak cocok untuk cara memeriksa dengan mencetak lalu lintas DHCP
- FreeRTOS tidak menyediakan abstraksi perangkat keras, sehingga kode yang ditulis untuk berkomunikasi dengan beberapa chip sulit digunakan ulang dengan mudah
- Setelah itu dicoba membuat proyek FreeRTOS bersih dan memindahkan fitur, tetapi karena tidak nyamannya debugging buta tanpa output serial, opsi lain pun dilihat
Apache NuttX: struktur ala Unix dan kesalahan konfigurasi
- Apache NuttX terlihat lebih dekat ke sistem operasi umum, dan memperlakukan mikrokontroler seperti sistem Unix
- Tutorial mengarahkan untuk mengambil pico-sdk dan mengatur environment variable
- SDK sudah ada di
/usr/sharedan environment variable juga sudah tersedia, tetapi build gagal karena masalah izin ketika NuttX mencoba menimpa fileversion.hmilik pico-sdk
- SDK sudah ada di
- Setelah membuild firmware NuttX minimal dan menghubungkan ke port serial, shell sungguhan muncul
- Perintah seperti
uptime,uname, danuname -aberfungsi - Versi yang ditampilkan adalah
NuttX 12.5.1dan targetnyaarm raspberrypi-pico
- Perintah seperti
- Karena mengikuti cara Unix, tampaknya aplikasi bisa ditulis dan dijalankan otomatis saat boot
- Ada filesystem, dan perangkat keras diekspos sebagai abstraksi seperti
/dev/i2c0dan/dev/adc0
- Ada filesystem, dan perangkat keras diekspos sebagai abstraksi seperti
- Bagian yang disukai adalah konfigurasi berbasis menuconfig/Kconfig
- Ini cara yang familier dari pengembangan Linux
- Ada sistem driver perangkat keras sungguhan, dan driver chip GPIO expander yang digunakan untuk tombol juga sudah tersedia
- Pengaturan mux pin RP2040 juga bisa ditentukan di menuconfig, sehingga tidak perlu memelihara konstanta nomor pin terpisah atau banyak menulis kode inisialisasi bus I2C
- Utilitas pengujian I2C juga bisa disertakan ke firmware
- Awalnya operasi dasar I2C tampak tidak berfungsi
- Dalam pembaruan berikutnya, hal ini dikoreksi bahwa sebenarnya I2C berfungsi baik, dan bus I2C rusak karena kesalahan konfigurasi
- Disebutkan bahwa sebagian besar evaluasi lain di bagian NuttX tersebut kemungkinan tidak valid
- Saat itu belum jelas bagaimana memberi tahu NuttX bahwa tombol GPIO berada di balik GPIO expander, maupun bagaimana menghubungkan GPIO expander ke bus I2C
- Setelah
configure.shgagal, repositori berada dalam keadaan tidak konsisten sehingga repositori NuttX harus dikloning ulang beberapa kali- Ada situasi ketika
distcleanjuga tidak bekerja dengan benar karena alasan yang sama
- Ada situasi ketika
- Pendekatan Unix-like awalnya terlihat bagus, tetapi tidak ingin menangani path filesystem palsu di mikrokontroler
- Sistem produksi juga tidak membutuhkan shell; cukup kode yang berjalan
Zephyr: SDK besar dan hambatan definisi board
- Pilihan berikutnya adalah Zephyr, yang menyediakan utilitas Python untuk pengaturan proyek
- Pada langkah pertama, repositori Git sekitar 5GB diambil
- Di dalamnya termasuk library HAL untuk banyak chip
- Ini juga memengaruhi konfigurasi cmake global pengguna
- Tutorial mengharuskan instalasi Zephyr SDK
- Zephyr SDK mencakup toolchain, compiler, assembler, linker, dan alat build untuk tiap arsitektur yang didukung
- Tool host seperti QEMU dan OpenOCD juga disertakan
- Karena sudah ada beberapa toolchain ARM, tidak ingin membuild compiler untuk semua arsitektur atau mengambil yang sudah dibuild
- Untuk build tanpa Zephyr SDK, opsi cross compile disetel
ZEPHYR_TOOLCHAIN_VARIANT=cross-compileCROSS_COMPILE=/usr/bin/arm-none-eabi-west build -p always -b sparkfun_pro_micro_rp2040 samples/basic/blinky
- Raspberry Pi Pico sebenarnya tidak didukung, hanya board lain yang memakai SoC yang sama yang didukung
- Karena SoC-nya sama, proses dilanjutkan dengan menganggapnya sebagai board yang secara praktis mirip
- Segera muncul masalah bahwa demo
blinkytidak bisa dibuild- Demo tersebut membutuhkan definisi
led0sebagai target yang akan berkedip - Sparkfun Pro Micro RP2040 tidak memiliki LED GPIO sederhana, melainkan LED addressable WS2812B
- Demo tersebut membutuhkan definisi
- Mengikuti manual board kustom, proses dilanjutkan dengan menyalin definisi board lain, tetapi bahkan setelah memperbaiki error dan warning build, build untuk board target tetap tidak berhasil
Akhirnya kembali ke FreeRTOS
- Dari tiga RTOS tersebut, hanya FreeRTOS yang berhasil membuild sebagian aplikasi nyata
- Masalah printf kemungkinan harus diselesaikan seperti panduan online, yaitu menggantinya dengan implementasi printf lain dan memanggil fungsi lain di tempat yang diperlukan
- Ke depannya, rencananya adalah terus mencoba FreeRTOS
- Karena dibandingkan RTOS lain, ini satu-satunya pilihan yang bisa diintegrasikan relatif sederhana ke lingkungan yang sudah ada
1 komentar
Komentar Hacker News
Penulis ini tampaknya memandang RTOS seperti lingkungan Arduino, atau sesuatu yang boleh diharapkan akan berjalan setelah sekadar dicoba-coba. Kebanyakan tidak begitu.
Saat ini cukup banyak Arduino yang di dalamnya sudah memakai mbed atau FreeRTOS, dan ada juga cara untuk mengeksposnya, jadi untuk gaya penulis mungkin pilihan itu lebih cocok.
Zephyr mudah digunakan dan dukungan CLion-nya juga bagus, tetapi kita tidak bisa berharap semuanya bekerja tanpa memasang toolchain. Pi Pico juga jelas didukung, dan saat saya mencobanya sendiri tidak ada masalah.
Ringkasnya, FreeRTOS didukung hampir di mana-mana, tetapi drivernya umumnya spesifik SoC/perangkat sehingga merepotkan, dan API-nya juga tidak ramah, meski bisa dibiasakan. Jika ingin memakai Bluetooth, harus mencari stack-nya sendiri.
Zephyr mendukung abstraksi perangkat keras sungguhan dan mendukung sebagian besar SoC, tetapi mungkin perlu sedikit pekerjaan untuk board. Stack Bluetooth disediakan, dan mungkin perlu sedikit menambahkan dukungan HCI.
NuttX dukungannya tidak luar biasa, tetapi kalau bisa membuatnya berjalan, itu pilihan yang cukup keren. Dukungan industri masih belum kuat. Ada juga mbed, tetapi saya lewatkan di sini.
Di dunia RTOS sebenarnya, biasanya orang memilih yang didukung oleh vendor SoC. Kalau Nordic berarti Zephyr, kalau NXP berarti FreeRTOS, dan seterusnya, supaya bisa mendapat dukungan yang baik.
Saya belum pernah melihat proyek firmware perangkat OEM yang para developernya tidak kesulitan dengan Zephyr. Saya juga belum pernah bertemu developer yang membuat firmware nyata untuk produk rilis dan merasa abstraksi perangkat keras Zephyr membantu.
Bukan berarti orang seperti itu tidak ada, tetapi selama kira-kira 5 tahun terakhir saya belum menjumpainya.
Menurut saya, materi pemasaran Zephyr sangat cantik. Namun di balik kemewahan itu ada kegemukan berlebihan, kompilasi yang sangat lambat, dan lingkungan yang sulit untuk mulai digunakan.
Memasang toolchain secara sistem-wide seperti cara UNIX tradisional itu menyakitkan, dan jujur saja bukan pendekatan yang terlalu cerdas.
Kalau bekerja sendiri mungkin baik-baik saja, tetapi ketika banyak developer menangani banyak proyek dengan target berbeda, banyak waktu habis untuk mencari tahu masalah build dan konfigurasi.
Terus memakai Python untuk tooling juga tidak membantu. Saya tidak mengerti kenapa harus memakai bahasa yang membawa masalah versinya sendiri dan berperilaku berbeda di tiap komputer developer.
Saya sudah sekitar 10 tahun melakukan embedded development sebagai hobi dan pekerjaan, dan saya tidak paham sikap yang menganggap bukan masalah ketika satu minggu habis hanya untuk menyamakan environment semua orang dalam sebuah proyek.
Ini masalah nyata, menyebalkan, membuang waktu, dan tidak perlu.
Tool seharusnya berupa binary yang ditautkan statis. Mau ditulis dengan Rust, Go, C, atau C++ tidak masalah, tetapi saya berharap prioritasnya adalah tool yang kokoh dan bisa dipercaya akan berjalan dengan cara yang sama terlepas dari apa yang terpasang di komputer, bukan pengembangan tambal sulam.
Python tidak memberikan itu, dan marah serta bersikap defensif alih-alih menanggapi masalah ini lebih serius juga tidak membantu.
Meski begitu, hal seperti PlatformIO berada di arah yang benar. Saya tahu itu proyek Python dan kadang menjadi masalah, tetapi lebih jarang dibanding tool lain, dan gagasannya benar.
Toolchain, SDK, dan library harus dikelola, konfigurasi proyek harus sederhana, dan build harus dapat direproduksi di mana pun dan kapan pun.
Saya berharap industri embedded lebih menyadari nilai upaya terstruktur bersama. Saya mengenal banyak orang yang bekerja di produsen MCU besar, dan saya selalu kecewa karena mereka umumnya sibuk menyelesaikan masalah langsung mereka sendiri sehingga tampak berpandangan sempit terhadap kebutuhan developer.
Saya punya proyek keyboard yang berjalan di RP2040 dan firmwarenya ditulis dengan Rust. Dengan hanya repositori dan tanpa toolchain Rust, prosedur untuk melakukan flash adalah sebagai berikut.
(instal rustup)
$ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh$ rustup target add thumbv6m-none-eabi$ cargo install elf2uf2-rs* alihkan keyboard ke mode bootloader *$ cargo run --releaseDi sini rustup dan Cargo menangani sebagian besar manajemen toolchain dan build, dan keduanya benar-benar luar biasa. Proyek Python bahkan tidak mendekati.
Cukup jalankan satu perintah, maka baik di lokal maupun CI semuanya tersetel dan berjalan dengan cara yang sepenuhnya sama, memakai versi build tool dan library yang sama.
Karena itu, setiap kali harus kembali berurusan dengan CMake dan Make sambil bergulat memasang library, rasanya menyiksa. Sangat berbeda dari pendekatan seperti
compile 'library-name-here'.Sebaliknya, mereka memilihnya karena ekosistem library. Untuk analisis data, visualisasi, dan komputasi ilmiah, tidak ada opsi yang sebanding dalam bahasa lain.
Ini adalah area yang tidak ingin kita implementasikan ulang dari awal. Bug mudah masuk di bagian seperti stabilitas numerik, sehingga 99% hasilnya benar, tetapi 1% bisa tampak masuk akal namun sepenuhnya salah.
Secara pribadi, saya mulai memindahkan proyek RP2040 ke Rust dan Embassy
Rust memang butuh sedikit adaptasi, tetapi saya cukup menyukainya. Ini bukan RTOS, tetapi memenuhi banyak kebutuhan yang biasanya membuat kita merasa perlu memakai RTOS
Rust dan Cargo menghilangkan kerepotan build dan flashing untuk RP2040, atau STM32. Sejauh ini ini lingkungan embedded paling nyaman yang pernah saya pakai
Banyak aplikasi tidak memakai MPU. Lalu tinggal pertimbangkan keamanan memori Rust dan kompleksitas firmware keseluruhan yang berkurang tanpa RTOS
Async pada executor Embassy juga bekerja sangat baik, sehingga banyak mengurangi rasa sakit dalam proses desain RTOS
Jika ditambah antarmuka PIO untuk RP2040, kodenya menjadi sangat sederhana dan indah, serta menghasilkan konfigurasi yang sulit dicapai dengan prosesor lain
Pi Pico didukung 100% di Zephyr. https://github.com/zephyrproject-rtos/zephyr/tree/main/board... Mungkinkah dokumentasinya tidak dicek? https://docs.zephyrproject.org/latest/boards/raspberrypi/rpi...
Selain itu, dalam banyak situasi, cara penggunaan yang dimaksud bukan memakai satu instalasi “main” Zephyr, melainkan memasukkan modul eksternal yang dibutuhkan ke
west.ymlproyekBerbagi instalasi Zephyr yang sama di beberapa proyek adalah pembahasan tersendiri, tetapi memasang semua toolchain dan HAL yang mungkin bukan satu-satunya cara
ThreadX, yang sekarang open source, tidak disebut
https://github.com/eclipse-threadx/threadx/
https://github.com/RIOT-OS/RIOT
Perbandingan opsi RTOS-nya bagus
Secara pribadi, saya melihat MicroPython sebagai jalur yang lebih mudah. Multitasking kooperatif berbasis
async/awaitcocok untuk sayaDalam proyek terbaru, saya menangani 6 motor stepper, beberapa LED, dan pemindaian tombol, dan semuanya tampak real-time bagi pengguna
Masih mengejutkan bahwa banyak orang belum benar-benar memahami betapa sedikitnya sumber daya yang dulu tersedia bagi kita, namun kita tetap memakai bahasa tingkat tinggi
Saat mencoba MicroPython di ESP32, saya menyukai dukungannya terhadap interrupt handler dengan gaya yang terasa Pythonic. Saya rasa RP2040 juga didukung dengan cara serupa
Pada mikroskop saya, kontrol motor stepper yang nyaris real-time ditangani oleh board FluidNC, lalu saya mengendalikannya lewat protokol serial ringan
Namun saya sedang melihat https://pypi.org/project/micropython-stepper/, dan ini tampaknya memakai timer hardware dan kode Python
Saya ingin sekali mencoba Hubris dalam proyek sungguhan (https://hubris.oxide.computer/reference/)
Pendekatan arsitekturnya cukup sesuai dengan arah yang saya tuju di bidang embedded. Hanya saja saya melakukannya dengan cara yang lebih menyakitkan memakai C
Ini juga tidak terlalu berbeda dari cara melakukannya dengan Erlang/Elixir di lingkungan hosted
Dalam situasi memori lebih terbatas sehingga tidak mampu menampung banyak stack, Embassy tampaknya pilihan yang baik
Proyek embedded baru harus selalu, benar-benar selalu, dimulai di mesin virtual. Jangan mencampur tool di sistem yang sama
Dalam proyek komersial saya, ini adalah penyebab nomor satu masalah kualitas
Jika memulai proyek dengan chipset baru atau vendor baru, buat VM baru, pasang hanya tool vendor di VM itu, lalu build di sana
Pengembangan eksperimental boleh dilakukan di mesin lokal non-VM sendiri. Tetapi rilis harus selalu dilakukan dari VM. Dan tolong sinkronkan VM dengan workstation pengembangan
Saat ini saya sedang mengalami penderitaan besar menangani build firmware yang wajib diperbaiki ketika pengembang aslinya sedang cuti. Tidak ada yang bisa mengakses workstation orang itu, VM yang disiapkan tertinggal 6 bulan, dan pelanggan bertanya mengapa mereka harus membayar biaya seluruh tim untuk sesuatu yang di seluruh dunia hanya bisa dilakukan oleh satu programmer istimewa
Menurut saya, rilis harus dibuild oleh sistem CI. Saat tag rilis dipasang di git, setelah tes lolos, binary akan dihasilkan
Jika memilih FreeRTOS, kecil kemungkinan akan salah besar. Pada titik ini, praktis sudah menjadi standar industri
printf()berfungsi?Kelihatannya cukup merepotkan
Pernah punya pengalaman yang mirip dengan tulisan asli
Jadi saya membuat sendiri timer green thread sederhana
Memang tidak mendukung manajemen proses sungguhan seperti kernel sebenarnya dan tidak memberikan jaminan apa pun, tetapi itu memungkinkan saya melangkah lebih jauh dibanding penjadwalan bare-metal dan menghindari kekacauan bernama RTOS
Anggap saja seperti callback timer JavaScript di C yang menerima struct konteks opsional
Saya bisa menangani kueri ke berbagai sensor, memproses sinyal masuk, mengambil keputusan kontrol, dan mengirim perintah, masing-masing dengan periode yang berbeda
Sebelum merusak hidup dengan arsitektur yang lambat dan abstrak seperti ini, saya sangat menyarankan mencoba pendekatan seperti ini terlebih dahulu