Watchdog est un appareil conçu pour dĂ©tecter et rĂ©soudre les problĂšmes matĂ©riels. Habituellement, un temporisateur est utilisĂ© pour cela, dont un redĂ©marrage pĂ©riodique empĂȘche l'envoi d'un signal au redĂ©marrage.
Le serveur principal sur Gentoo est utilisĂ© par moi principalement pour des expĂ©riences, cependant, il exĂ©cute un certain nombre de services qui, si possible, devraient ĂȘtre disponibles sans interruption. Malheureusement, les consĂ©quences de certaines expĂ©riences conduisent Ă la panique du noyau, Ă 100% de charge CPU et Ă d'autres problĂšmes au moment le plus inopportun. L'idĂ©e d'ajouter un chien de garde a donc longtemps retenu l'attention et s'est finalement concrĂ©tisĂ©e dans cet appareil.AprĂšs une inspection minutieuse de ce qui Ă©tait disponible et une Ă©valuation du temps disponible, le chien de garde assemblĂ© sur la base de l'Arduino Nano Ă©tait la meilleure option. Une liste d'exigences est apparue autour de la mĂȘme:- DĂ©marrage et arrĂȘt du dĂ©mon pour travailler avec une minuterie, un outil de systĂšme d'exploitation normal (OpenRC).
- Propre chien de garde sur l'appareil, dans ATmega, vous devez l'utiliser.
- Le journal des événements sur l'appareil pour fixer le redémarrage et la minuterie.
- Synchronisez l'heure de l'appareil avec l'hĂŽte pour enregistrer l'heure correcte dans le journal.
- Recevoir et afficher l'état de l'appareil et ses entrées de journal.
- Effacer le journal et réinitialiser l'appareil à son état d'origine.
Ainsi, le «microscope» a été retrouvé, le «clou» est marqué⊠on peut marteler.Matériel
La base de l'appareil était le clone chinois Arduino Nano, fabriqué sur la base de la puce CH340. Les nouveaux noyaux Linux (testés depuis la 3.16) ont un pilote approprié, donc le périphérique est facilement détecté comme un port série USB.Redémarrage indésirable Arduino
Chaque fois que le terminal est connecté, l'Arduino redémarre. La raison en est que le terminal envoie un signal DTR (Data Terminal Ready), ce qui provoque le redémarrage de l'appareil. Ainsi, l'IDE Arduino met l'appareil en mode de chargement des croquis.Il existe plusieurs options pour résoudre le problÚme, mais une seule s'est avérée fonctionner - il est nécessaire d'installer un électrolyte de 10”F (C1 dans le diagramme ci-dessous) entre les contacts RST et GND. Malheureusement, cela bloque également le téléchargement de croquis sur l'appareil.En conséquence - le schéma est le suivant:
DessinĂ© Ă l'aide de KiCadExplications du schĂ©ma- 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 â , , , , .
Boucle de démarrage (redémarrage cyclique) lors de l'utilisation de WDT
Les microcontrĂŽleurs ATmega ont un mĂ©canisme de rĂ©initialisation WDT (WatchDog Timer) intĂ©grĂ©. Cependant, toutes les tentatives d'utilisation de cette fonction ont conduit Ă une boucle de dĂ©marrage, qui ne pouvait ĂȘtre interrompue qu'en coupant l'alimentation.Peu de recherches ont rĂ©vĂ©lĂ© que les chargeurs de dĂ©marrage de la plupart des clones Arduino ne prennent pas en charge WDT. Heureusement, ce problĂšme a Ă©tĂ© rĂ©solu dans le chargeur de dĂ©marrage alternatif Optiboot .Afin de flasher le chargeur de dĂ©marrage, vous avez besoin d'un programmeur qui peut fonctionner en utilisant le protocole SPI, il est Ă©galement souhaitable que l'IDE Arduino connaisse cet appareil «en personne». Dans ce cas, un autre Arduino est idĂ©al.Si nous prenons Arduino UNO, en tant que programmeur, et la derniĂšre version d'Arduino IDE v1.6.5, alors l'algorithme sera le suivant:- 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 |
|
- Dans l'IDE Arduino, dans le menu Outils, définissez les paramÚtres comme dans la capture d'écran:

- SĂ©lectionnez l'Ă©lĂ©ment de menu Outils â Graver Bootloader et assurez-vous que le processus s'est terminĂ© sans erreur.
AprĂšs cette procĂ©dure, vous devez tĂ©lĂ©charger des croquis Ă Arduino Nano en choisissant les mĂȘmes paramĂštres - Conseil : Optiboot sur 32 broches CPUs, Processeur : ATMEGA328P, CPU Speed : 16MHz.Soudure
Ensuite, vous devez tout souder pour qu'il ressemble Ă une seule piĂšce.
Ici, une prise USB Ă©tait nĂ©cessaire en raison du fait que j'ai une carte mĂšre mini-ITX avec un seul connecteur pour une paire d'USB2.0, qui sont nĂ©cessaires sur le panneau avant, et il n'y avait rien Ă connecter au pad USB3.0. Si possible, ces appareils doivent ĂȘtre connectĂ©s directement Ă la carte mĂšre afin que les fils ne dĂ©passent pas.La soudure, en rĂšgle gĂ©nĂ©rale, ne pose pas de problĂšme, mais dans ce cas, une planche Ă pain est utilisĂ©e, et cela a ses propres spĂ©cificitĂ©s.Comment souder des pistes sur une planche Ă pain( , ). .
:

Résultat:
il peut sembler que certains contacts sont mal soudĂ©s, mais ce n'est qu'un flux. La consommation de soudure sur la planche Ă pain est assez importante, donc tout ce qui est possible est enduit d'un flux ici. En fait, c'est un bon exemple de la façon dont vous n'avez pas besoin de quitter le produit aprĂšs le soudage. Le flux doit ĂȘtre lavĂ©, sinon il peut y avoir des problĂšmes de corrosion des composĂ©s. Je vais ajouter et aller me laver ... C'est mieux:
Partie logiciel
Objectivement parlant, le code de ce projet n'a pas un intĂ©rĂȘt particulier. Les introductions sont loin d'ĂȘtre extrĂȘmes, et l'architecture est dĂ©crite en une phrase: envoyer une commande - attendre une rĂ©ponse. Par souci d'ordre, je dĂ©crirai ici les fonctionnalitĂ©s principales et m'attarderai briĂšvement sur les points les plus intĂ©ressants, de mon point de vue.Tout le code est publiĂ© sur GitHub, donc si vous ĂȘtes familier avec Bash et C / C ++ (dans le contexte des croquis Arduino), la lecture Ă ce stade peut ĂȘtre terminĂ©e. Si vous ĂȘtes intĂ©ressĂ©, le rĂ©sultat final peut ĂȘtre trouvĂ© ici .Connexion chien de garde
Lorsque vous connectez le chien de garde, un fichier de périphérique est créé contenant le numéro de série. Si le systÚme possÚde d'autres périphériques ttyUSB (dans mon cas, un modem), il y a un problÚme de numérotation. Pour identifier de maniÚre unique le périphérique, vous devez créer un lien symbolique avec un nom unique. Pour cela, udev est conçu, qui existe probablement déjà dans le systÚme.Vous devez d'abord trouver visuellement le chien de garde connecté, par exemple, en consultant le fichier journal du systÚme. Ensuite, en remplaçant / dev / ttyUSB0 par le périphérique souhaité, écrivez dans le terminal:udevadm info -a -p "$(udevadm info -q path -n /dev/ttyUSB0)"
Exemple de sortie 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"
...
Dans ce cas, la rĂšgle ressemblera Ă ceci:ACTION=="add", KERNEL=="ttyUSB[0-9]*", SUBSYSTEM=="tty", SUBSYSTEMS=="usb", ATTRS{idVendor}=="1a86", ATTRS{idProduct}=="7523", SYMLINK+="ttyrst-watchdog"
Vous devez le placer dans un fichier séparé dans le répertoire /etc/udev/rules.d , par exemple, 51-ttyrst-watchdog.rules et dire à udev de recharger les rÚgles:udevadm control --reload-rules
à partir de ce moment, lors de la connexion du chien de garde, un lien / dev / ttyrst- watchdog sera créé sur le périphérique souhaité, qui sera utilisé plus tard.Script bash (ttyrst-watchdog.sh)
La communication avec le chien de garde s'effectue à une vitesse de 9600 bauds. Arduino fonctionne sans problÚme avec les terminaux à haute vitesse, mais les commandes pour travailler avec du texte (chat, écho, etc.) ne reçoivent et n'envoient que des ordures. Il est possible que ce soit une caractéristique de ma seule copie de l'Arduino Nano.Pour le cycle de redémarrage du minuteur principal et pour les fonctions de ligne de commande, un script est utilisé. La raison en est que les deux composants utilisent une ressource commune - le fichier de périphérique, et il est nécessaire de lui fournir un accÚs synchrone.La synchronisation consiste essentiellement en une boucle d'attente:while fuser ${DEVICE} >/dev/null 2>&1; do true; done
et capturer l'appareil pendant le temps requis:cat <${DEVICE}
De toute Ă©vidence, un tel rĂ©gime est soumis Ă une condition de concurrence. Vous pouvez gĂ©rer cela de maniĂšre adulte (par exemple, pour organiser une file d'attente de messages), mais dans ce cas, il suffit de dĂ©finir correctement les dĂ©lais afin de garantir un rĂ©sultat dans un dĂ©lai acceptable. En fait, l'ensemble du script fonctionne avec des dĂ©lais d'attente.La diabolisation (exĂ©cutĂ©e en arriĂšre-plan) est effectuĂ©e Ă l'aide du package OpenRC. Il est supposĂ© que ce script se trouve dans le fichier /usr/local/bin/ttyrst-watchdog.sh et que le script OpenRC se trouve dans /etc/init.d/ttyrst-watchdog .Lorsque le dĂ©mon s'arrĂȘte, la dĂ©sactivation correcte du chien de garde est requise. Pour ce faire, le script dĂ©finit le gestionnaire de signal qui doit ĂȘtre terminĂ©:trap deactivate SIGINT SIGTERM
Et ici, un problĂšme surgit - OpenRC ne peut pas arrĂȘter le dĂ©mon, ou plutĂŽt, mais pas souvent.Le fait est que la commande kill envoie un signal au script et que le programme sleep, qui est utilisĂ© pour suspendre le script, est exĂ©cutĂ© dans un autre processus et ne reçoit pas le signal. Par consĂ©quent, la fonction de dĂ©sactivation n'est lancĂ©e qu'aprĂšs la fin du sommeil, ce qui est trop long.La solution consiste Ă dĂ©marrer le sommeil en arriĂšre-plan et Ă attendre la fin du processus dans le script:sleep ${SLEEP_TIME} & wait $!
Constantes de base:WATCHDOG_ACTIVE - YES ou NO, respectivement, envoient un signal pour redĂ©marrer lorsque le temporisateur est dĂ©clenchĂ© ou non.WATCHDOG_TIMER - temps en secondes pour lequel la minuterie est rĂ©glĂ©e.SLEEP_TIME - temps en secondes aprĂšs lequel le temporisateur doit ĂȘtre redĂ©marrĂ©. Il doit ĂȘtre beaucoup plus petit que WATCHDOG_TIMER, mais pas trĂšs petit, afin de ne pas crĂ©er de charge excessive sur le systĂšme et l'appareil. Aux dĂ©lais d'attente actuels, un minimum raisonnable est d'environ 5 secondes.DEFAULT_LOG_LINES - le nombre d'entrĂ©es de journal de pĂ©riphĂ©rique rĂ©centes retournĂ©es par la commande de journal par dĂ©faut.Commandes de script:dĂ©marrer- dĂ©but du cycle de redĂ©marrage de la minuterie principale. Vous pouvez ajouter un code de vĂ©rification supplĂ©mentaire Ă la fonction is_alive, par exemple, pour vĂ©rifier la possibilitĂ© de se connecter via ssh.Ă©tat - affiche l'Ă©tat de l'appareil.reset - rĂ©initialisation de l'EEPROM (donnĂ©es de journal) et redĂ©marrage de l'appareil pour restaurer le chien de garde Ă son Ă©tat d'origine.log <nombre d'entrĂ©es> - affiche le nombre spĂ©cifiĂ© d'entrĂ©es de journal rĂ©centes.Croquis Arduino (ttyrst-watchdog.ino)
Pour compiler avec succĂšs l'esquisse, vous avez besoin d'une bibliothĂšque de temps tierce , nĂ©cessaire Ă la synchronisation de l'heure.Un croquis se compose de deux fichiers. Cela est dĂ» au fait que l'IDE Arduino n'accepte pas les structures (struct) dĂ©clarĂ©es dans le fichier principal, elles doivent ĂȘtre dĂ©placĂ©es vers un fichier d'en-tĂȘte externe. De plus, pour dĂ©clarer une structure, le mot-clĂ© typedef n'est pas nĂ©cessaire, il est probablement mĂȘme dangereux ... aprĂšs avoir vĂ©rifiĂ© les options standard, je n'ai pas trouvĂ© la syntaxe appropriĂ©e. Le reste est du C ++ plus ou moins standard.Les fonctions wdt_enable et wdt_reset fonctionnent avec le chien de garde intĂ©grĂ© dans le microcontrĂŽleur. AprĂšs avoir initialisĂ© le WDT, la principale chose Ă retenir est de le rĂ©initialiser dans la boucle principale et Ă l'intĂ©rieur des boucles de toutes les opĂ©rations longues.Les entrĂ©es de journal sont Ă©crites dans la mĂ©moire EEPROM non volatile, sa taille disponible peut ĂȘtre spĂ©cifiĂ©e dans logrecord.h, dans ce cas, il est 1024. Le journal est fait sous forme d'anneau, le sĂ©parateur est une structure avec des valeurs nulles. Le nombre maximum d'entrĂ©es pour 1 Kio EEPROM est de 203.Un enregistrement sur le chargement de l'appareil ne parvient au journal qu'aprĂšs synchronisation de l'heure. La synchronisation est effectuĂ©e en mĂȘme temps que le temporisateur est redĂ©marrĂ© et avant l'exĂ©cution de toute commande lors de l'initialisation du pĂ©riphĂ©rique. Sinon, il ne sera pas possible de comparer l'heure correcte avec cet Ă©vĂ©nement, et les informations sur les redĂ©marrages des pĂ©riphĂ©riques, isolĂ©ment du dĂ©mon de travail, ne sont pas trĂšs intĂ©ressantes.
C'est tout, merci d'avoir regardé!Les fichiers source du projet sont situés sur GitHub