Watchdog adalah perangkat yang dirancang untuk mendeteksi dan memecahkan masalah perangkat keras. Biasanya, timer digunakan untuk ini, restart secara berkala yang mencegah sinyal dikirim ke reboot.
Server utama di Gentoo digunakan oleh saya terutama untuk percobaan, namun, ia menjalankan sejumlah layanan yang, jika mungkin, harus tersedia tanpa gangguan. Sayangnya, konsekuensi dari beberapa percobaan menyebabkan panik kernel, beban CPU 100% dan masalah lainnya pada saat yang paling tidak tepat. Jadi ide menambahkan anjing pengawas telah lama membutuhkan perhatian dan akhirnya terwujud dalam perangkat ini.Setelah pemeriksaan cermat atas apa yang tersedia dan penilaian waktu yang tersedia, pengawas berkumpul berdasarkan Arduino Nano adalah pilihan terbaik. Daftar persyaratan muncul hampir sama:- Memulai dan menghentikan daemon agar berfungsi dengan timer, alat OS biasa (OpenRC).
- Watchdog sendiri di perangkat, di ATmega itu, Anda harus menggunakannya.
- Log peristiwa pada perangkat untuk memperbaiki reboot dan timer.
- Sinkronkan waktu perangkat dengan host untuk mencatat waktu yang benar dalam log.
- Menerima dan menampilkan status perangkat dan entri log-nya.
- Menghapus log dan mengatur ulang perangkat ke kondisi semula.
Dengan demikian, "mikroskop" ditemukan, "kuku" ditandai ... Anda dapat palu.Perangkat keras
Dasar perangkat itu adalah klon Cina, Arduino Nano, yang dibuat atas dasar chip CH340. Kernel Linux segar (diuji sejak 3.16) memiliki driver yang sesuai, sehingga perangkat ini mudah dideteksi sebagai port serial USB.Arduino Unwanted Reboot
Setiap kali terminal terhubung, Arduino reboot. Alasannya adalah bahwa terminal mengirimkan sinyal DTR (Data Terminal Ready), yang menyebabkan perangkat melakukan reboot. Dengan demikian, IDE Arduino menempatkan perangkat ke mode untuk memuat sketsa.Ada beberapa opsi untuk menyelesaikan masalah, tetapi hanya satu yang ternyata berfungsi - perlu untuk menginstal elektrolit 10ΞΌF (C1 pada diagram di bawah) antara kontak RST dan GND. Sayangnya, ini juga memblokir unduhan sketsa ke perangkat.Akibatnya - skema adalah sebagai berikut:
Diambil menggunakan KiCadPenjelasan untuk skema- R1 β , PC817: (5V β 1.2V / 0.02A) = 190Ξ©, 180Ξ©.
- U2 β Arduino PC. , ( USB ), .
- JP1 β , . .
- 1 β , DTR.
- MB_RST, MB_GND β RESET , RST (GND). , .
- BTN_RST, BTN_GND β , , , , .
Boot-loop (cyclic reboot) saat bekerja dengan WDT
Mikrokontroler ATmega memiliki mekanisme reset WDT (TimerDog Timer) bawaan. Namun, semua upaya untuk menggunakan fungsi ini menyebabkan boot-loop, yang hanya dapat keluar dengan mematikan daya.Pencarian yang tidak lama mengungkapkan bahwa bootloader dari sebagian besar klon Arduino tidak mendukung WDT. Untungnya, masalah ini telah diatasi dalam bootloader alternatif Optiboot .Untuk mem-flash bootloader, Anda memerlukan seorang programmer yang dapat bekerja pada protokol SPI, juga diharapkan bahwa Arduino IDE mengetahui perangkat ini βsecara langsungβ. Dalam hal ini, Arduino lain ideal.Jika kita mengambil Arduino UNO, sebagai programmer, dan versi terbaru Arduino IDE v1.6.5, maka algoritmenya adalah sebagai berikut:- boards-1.6.txt optiboot hardware/arduino/avr/boards.txt Arduino IDE.
- Arduino Uno, File β Examples β ArduinoISP.
- Arduino Nano :
Arduino Uno () | Arduino Nano (ICSP ) |
---|
5V β Vcc | GND β GND | D11 β MOSI | D12 β MISO | D13 β SCK | D10 β Reset |
| Pin1 (MISO) β D12 | Pin2 (Vcc) β 5V | Pin3 (SCK) β D13 | Pin4 (MOSI) β D11 | Pin5 (Reset) β D10 | Pin6 (GND) β GND |
|
- Di Arduino IDE, di menu Tools, atur pengaturan seperti pada tangkapan layar:

- Pilih item menu Tools β Burn Bootloader dan pastikan prosesnya selesai tanpa kesalahan.
Setelah prosedur ini, Anda perlu mengunggah sketsa ke Arduino Nano dengan memilih pengaturan yang sama - Papan : Optiboot pada cpus 32 pin, Prosesor : ATmega328p, Kecepatan CPU : 16MHz.Pematerian
Selanjutnya, Anda perlu menyolder semuanya, sehingga terlihat seperti satu bagian.
Di sini saya memerlukan colokan USB karena saya memiliki motherboard mini-ITX dengan hanya satu konektor untuk sepasang USB2.0, yang diperlukan di panel depan, dan tidak ada yang terhubung ke pad USB3.0. Jika memungkinkan, perangkat tersebut harus terhubung langsung ke motherboard sehingga kabel tidak menonjol.Solder, sebagai suatu peraturan, tidak menyebabkan masalah, tetapi dalam hal ini papan tempat memotong roti digunakan, dan ini memiliki spesifikasi sendiri.Cara menyolder trek di papan tempat memotong roti( , ). .
:

Hasil:
Kelihatannya beberapa kontak disolder dengan buruk, tetapi ini hanya fluks. Konsumsi solder di papan tempat memotong roti cukup besar, jadi segala sesuatu yang mungkin ditutupi dengan fluks di sini. Sebenarnya, ini adalah contoh yang baik tentang bagaimana Anda tidak perlu meninggalkan produk setelah menyolder. Fluks harus dicuci, kalau tidak mungkin ada masalah dengan korosi senyawa. Saya akan menambahkan dan pergi mencuci ... Itu lebih baik:
Bagian perangkat lunak
Secara obyektif, kode proyek ini tidak menarik. Kata pengantar jauh dari ekstrim, dan arsitekturnya dijelaskan dalam satu frasa: kirim perintah - tunggu jawaban. Demi ketertiban, saya akan menjelaskan fungsi utama di sini dan secara singkat membahas poin yang paling menarik, dari sudut pandang saya.Semua kode diterbitkan di GitHub, jadi jika Anda terbiasa dengan Bash dan C / C ++ (dalam konteks sketsa Arduino), membaca pada titik ini dapat diselesaikan. Jika Anda tertarik, hasil akhirnya dapat ditemukan di sini .Koneksi anjing penjaga
Saat Anda menyambungkan watchdog, file perangkat dibuat berisi nomor seri. Jika sistem memiliki perangkat ttyUSB lainnya (dalam kasus saya, modem), maka ada masalah dengan penomoran. Untuk mengidentifikasi perangkat secara unik, Anda perlu membuat symlink dengan nama yang unik. Untuk ini, udev dirancang, yang mungkin sudah ada dalam sistem.Pertama, Anda perlu menemukan pengawas yang terhubung secara visual, misalnya, dengan melihat file log sistem. Kemudian, ganti / dev / ttyUSB0 dengan perangkat yang diinginkan, tulis di terminal:udevadm info -a -p "$(udevadm info -q path -n /dev/ttyUSB0)"
Contoh keluaran looking at device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0/tty/ttyUSB0':
KERNEL=="ttyUSB0"
SUBSYSTEM=="tty"
...
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.4/1-1.4:1.0/ttyUSB0':
KERNELS=="ttyUSB0"
SUBSYSTEMS=="usb-serial"
DRIVERS=="ch341-uart"
...
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.4/1-1.4:1.0':
...
looking at parent device '/devices/pci0000:00/0000:00:14.0/usb1/1-1/1-1.4':
SUBSYSTEMS=="usb"
DRIVERS=="usb"
ATTRS{idVendor}=="1a86"
ATTRS{idProduct}=="7523"
ATTRS{product}=="USB2.0-Serial"
...
Dalam hal ini, aturannya akan terlihat seperti ini:ACTION=="add", KERNEL=="ttyUSB[0-9]*", SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="ttyrst-watchdog"
Anda harus meletakkannya di file terpisah di direktori /etc/udev/rules.d , misalnya 51-ttyrst-watchdog.rules dan beri tahu udev untuk memuat ulang aturan:udevadm control --reload-rules
Mulai saat ini, saat menghubungkan watchdog, link / dev / ttyrst- watchdog akan dibuat pada perangkat yang diinginkan, yang akan digunakan nanti.Skrip Bash (ttyrst-watchdog.sh)
Komunikasi dengan pengawas dilakukan pada kecepatan 9600 baud. Arduino bekerja tanpa masalah dengan terminal dengan kecepatan tinggi, tetapi perintah untuk bekerja dengan teks (cat, echo, dll.) Hanya menerima dan mengirim sampah. Mungkin saja ini hanya fitur salinan Arduino Nano saya.Untuk siklus restart timer utama dan untuk fungsi baris perintah, satu skrip digunakan. Alasannya adalah bahwa kedua komponen menggunakan sumber daya umum - file perangkat, dan perlu untuk menyediakan akses sinkron ke sana.Sinkronisasi pada dasarnya terdiri dari satu lingkaran tunggu:while fuser ${DEVICE} >/dev/null 2>&1; do true; done
dan tangkap perangkat untuk waktu yang diperlukan:cat <${DEVICE}
Jelas, skema semacam itu tunduk pada kondisi balapan. Anda dapat menangani hal ini dengan cara dewasa (misalnya, untuk mengatur antrian pesan), tetapi dalam hal ini, cukup untuk mengatur batas waktu dengan benar untuk menjamin hasil dalam waktu yang dapat diterima. Bahkan, seluruh skrip bekerja dengan batas waktu.Demonisasi (berjalan di latar belakang) dilakukan dengan menggunakan paket OpenRC. Diasumsikan bahwa skrip ini ada di file /usr/local/bin/ttyrst-watchdog.sh , dan skrip OpenRC ada di /etc/init.d/ttyrst-watchdog .Ketika daemon berhenti, penonaktifan pengawas yang benar diperlukan. Untuk melakukan ini, skrip mengatur penangan sinyal yang membutuhkan penyelesaian:trap deactivate SIGINT SIGTERM
Dan di sini muncul masalah - OpenRC tidak dapat menghentikan daemon, atau lebih tepatnya, tetapi tidak sering.Faktanya adalah bahwa perintah kill mengirim sinyal ke skrip, dan program sleep, yang digunakan untuk menjeda skrip, dieksekusi dalam proses lain dan tidak menerima sinyal. Akibatnya, fungsi nonaktifkan diluncurkan hanya setelah tidur selesai, yang terlalu lama.Solusinya adalah mulai tidur di latar belakang dan menunggu proses untuk menyelesaikan dalam skrip:sleep ${SLEEP_TIME} & wait $!
Konstanta dasar:WATCHDOG_ACTIVE - YA atau TIDAK, masing-masing, mengirim sinyal untuk memulai kembali ketika timer dipicu atau tidak.WATCHDOG_TIMER - waktu dalam detik untuk mana timer diatur.SLEEP_TIME - waktu dalam detik setelah mana timer harus dihidupkan ulang. Seharusnya lebih kecil dari WATCHDOG_TIMER, tetapi tidak terlalu kecil, sehingga tidak membuat beban berlebihan pada sistem dan perangkat. Pada batas waktu saat ini, minimum yang masuk akal adalah sekitar 5 detik.DEFAULT_LOG_LINES - jumlah entri log perangkat terbaru yang dikembalikan oleh perintah log default.Perintah Skrip:mulai- mulai dari siklus restart timer utama. Anda dapat menambahkan kode verifikasi tambahan ke fungsi is_alive, misalnya, untuk memeriksa kemungkinan menghubungkan melalui ssh.status - menampilkan status perangkat.reset - mengatur ulang EEPROM (data log) dan me-reboot perangkat untuk mengembalikan anjing penjaga ke keadaan semula.log <jumlah entri> - menampilkan jumlah tertentu dari entri log terbaru.Sketsa Arduino (ttyrst-watchdog.ino)
Untuk berhasil menyusun sketsa, Anda memerlukan perpustakaan waktu pihak ketiga , yang diperlukan untuk sinkronisasi waktu.Sketsa terdiri dari dua file. Ini disebabkan oleh fakta bahwa IDE Arduino tidak menerima struktur (struct) yang dinyatakan dalam file utama, mereka harus dipindahkan ke file header eksternal. Selain itu, kata kunci typedef tidak diperlukan untuk mendeklarasikan struktur, bahkan mungkin berbahaya ... setelah memeriksa opsi standar, saya tidak dapat menemukan sintaksis yang sesuai. Sisanya kurang lebih standar C ++.Fungsi wdt_enable dan wdt_reset bekerja dengan pengawas yang terintegrasi dalam mikrokontroler. Setelah menginisialisasi WDT, hal utama yang harus diingat adalah mengatur ulang di loop utama dan di dalam loop semua operasi yang panjang.Entri log ditulis ke memori EEPROM non-volatil, ukuran yang tersedia dapat ditentukan dalam logrecord.h, dalam hal ini 1024. Log dibuat dalam bentuk cincin, pemisah adalah struktur dengan nilai nol. Jumlah entri maksimum untuk 1 KiB EEPROM adalah 203.Catatan tentang memuat perangkat sampai ke log hanya setelah sinkronisasi waktu. Sinkronisasi dilakukan pada saat yang sama dengan timer dihidupkan ulang dan sebelum perintah apa pun dijalankan selama inisialisasi perangkat. Kalau tidak, tidak mungkin membandingkan waktu yang tepat dengan kejadian ini, dan informasi tentang reboot perangkat, terpisah dari daemon yang berfungsi, tidak terlalu menarik.
Itu saja, terima kasih sudah menonton!File sumber proyek terletak di GitHub