30 votes

Comment concevoir un protocole de commande série pour un système embarqué ?

J'ai un système embarqué avec lequel je communique en série. La structure de commande actuelle est conçue pour être utilisée de manière interactive : elle affiche une invite, accepte quelques commandes et affiche les résultats sous une forme lisible par l'homme.

J'envisage de modifier ce format pour qu'il soit plus facilement utilisable par une machine, afin de pouvoir lui parler sans trop de problèmes à travers une interface graphique MATLAB (pour l'instant, les invites interactives et la variation de la longueur des messages posent problème).

Existe-t-il donc un document ou une norme quelque part qui décrit comment concevoir un bon protocole de commande série pour votre système embarqué ?

41voto

Bruce McGee Points 12225

J'ai quelques préférences (et bêtes noires) en ce qui concerne l'écriture d'un logiciel pour contrôler les médias et les dispositifs d'affichage à l'aide de RS232. En fonction de votre matériel, certaines de ces préférences peuvent ne pas s'appliquer :

  • Je pense que c'est une bonne idée de rendre votre protocole plus convivial pour l'automatisation. Si vous avez besoin d'une interface interactive (ligne de commande ou autre), construisez-la séparément et faites-la utiliser le protocole d'automatisation. Je ne m'inquiéterais pas trop de le rendre lisible par l'homme, mais c'est à vous de voir.

  • Retournez toujours une réponse, même (surtout) si vous obtenez une commande invalide. Quelque chose de simple comme $06 pour ACK et $15 pour NAK. Ou écrivez-le en toutes lettres si vous voulez que ce soit un peu plus lisible pour les humains.

  • Si vous pouvez définir n'importe quelle valeur, assurez-vous qu'il existe un moyen d'interroger cette même valeur. Si vous avez beaucoup de valeurs, cela peut prendre un certain temps pour les interroger toutes. Envisagez d'avoir une ou quelques méta-requêtes qui renvoient plusieurs valeurs à la fois.

  • Si vous disposez d'informations qui ne peuvent pas être définies, mais qui sont importantes (numéro de modèle, numéro de série, version, copyright, etc.), assurez-vous qu'elles peuvent être interrogées au lieu de les afficher une seule fois au démarrage ou à la réinitialisation.

  • Ne répondez jamais par une erreur pour une commande valide. On pourrait penser que celle-ci est évidente...

  • En parlant d'évidence, documentez les paramètres de série que votre matériel prend en charge. Surtout s'il est destiné à être utilisé par quelqu'un d'autre que vous et que vous ne voulez pas qu'il passe les 30 premières minutes à essayer de comprendre s'il ne peut pas parler à l'appareil à cause du port série, des connexions, du câble ou de son logiciel. Non pas que je sois amer...

  • Utilisez des commandes absolues au lieu de valeurs basculantes. Par exemple, utilisez des commandes distinctes pour la mise sous tension et la mise hors tension au lieu d'envoyer la même commande et de faire basculer la mise sous tension et hors tension.

  • Les réponses doivent inclure des informations sur la commande à laquelle elles répondent. Ainsi, un programme n'a pas besoin de se souvenir de la dernière chose qu'il a demandée pour traiter la réponse (voir l'option de crédit supplémentaire ci-dessous).

  • Si votre appareil supporte un mode veille (éteint, mais pas vraiment éteint), assurez-vous que les requêtes fonctionnent toujours lorsque vous êtes dans cet état.

Cela dépend de votre degré de paranoïa concernant l'exhaustivité des données :

  • Emballez votre message dans une enveloppe. L'en-tête peut comprendre un caractère de départ, la longueur du message et un caractère de fin. Juste au cas où vous recevriez des messages partiels ou malformés. Peut-être $02 pour le début et $03 pour la fin.

  • Si vous êtes vraiment paranoïaque quant à l'intégrité du message, incluez une somme de contrôle. Mais cela peut être un peu pénible.

Pour un crédit supplémentaire :

  • Si vos paramètres matériels peuvent être modifiés manuellement, vous pouvez peut-être envoyer cette modification par le port série comme si l'utilisateur l'avait demandée. Par exemple, vous ne souhaitez peut-être pas que l'utilisateur puisse modifier la source d'entrée d'un écran d'affichage public.

J'espère que cela vous aidera.

Mise à jour :

J'ai oublié quelque chose d'important. Avant de l'utiliser sérieusement et surtout avant de le donner à quelqu'un d'autre, essayez-le sur quelque chose de trivial pour vous assurer qu'il fonctionne comme vous l'attendez et (plus important) pour vous assurer que vous n'avez rien oublié. Il vous faudra plus de temps et d'efforts pour corriger les choses si vous découvrez un problème au milieu d'un projet plus important.

Il s'agit d'une bonne règle de base, que vous conceviez un protocole de commande, un service Web, un schéma de base de données ou une classe, etc.

8voto

Marcelo MD Points 812

Ici est un excellent article d'Eli Benderski sur le cadrage du protocole série. Quel que soit le format de paquet que vous choisissez, veillez à utiliser des caractères d'échappement. Cela vous permet d'avoir de tels caractères à l'intérieur des données réelles et facilite la resynchronisation en cas de corruption du paquet.

5voto

Michael Kohne Points 8233

À moins que la bande passante ou la latence ne soit un problème majeur, utilisez l'ASCII lorsque vous le pouvez - cela facilite grandement le débogage.

J'aime les protocoles qui envoient un message suivi d'un caractère clair de fin de message (comme le retour chariot). En général, je ne trouve pas les signaux de début de paquet très utiles (qu'y a-t-il d'autre sur ce fil ?). L'utilisation de CR pour la fin du message facilite également les tests via un programme de terminal.

Mise à jour : Bruce a fait remarquer (dans les commentaires) qu'un caractère de début de paquet vous permet de retrouver les paquets un peu plus rapidement en cas de corruption. Sans le caractère de début de paquet, il faudrait attendre la fin du paquet suivant pour savoir où l'on se trouve et à ce moment-là, on jetterait deux paquets au lieu d'un.

4voto

J'aime les réponses de Bruce McGee. Ayant travaillé avec des interfaces similaires, je peux offrir plusieurs autres conseils :

  • Lorsque vous renvoyez des types numériques dans un paquet de données, essayez, s'il vous plaît, s'il vous plaît, de faire en sorte que tout ait le même format. N'ayez pas simple pour certains nombres et double pour les autres. Et ne faites pas de l'arbitraire !

  • Donnez des exemples de paquets de données dans votre DCI. Il est terriblement frustrant de devoir deviner l'ordre des octets ou même l'ordre des bits (l'octet MSB est-il le premier ou le dernier ? Qu'est-ce qui est premier et dernier ?). Fournissez un diagramme qui montre les paquets en fonction du temps (par exemple, 0x02 est envoyé en premier, puis l'octet d'adresse, puis l'identifiant du message, etc.)

  • Dans la mesure du possible, ne passez pas d'un format de données à un autre. J'ai travaillé dans des systèmes qui utilisent des "nombres codés ASCII" pour certains messages où il faut enlever le "3" de tête des octets, puis les rassembler pour obtenir le vrai nombre. (En général, le codage ASCII est utilisé lorsque vous avez une séquence d'octets à éviter, comme 0x02, 0x04, etc. Encodés, les chiffres seraient 0x30, 0x32, 0x30, 0x34. Utilisez un champ de longueur si possible pour éviter cela, ou au moins faites-le tout le temps).

  • Il faut absolument documenter le débit en bauds, la parité, etc. Si vous utilisez le RS-485, documentez le mode de bus (2 fils ? 4 fils ?) ou les paramètres qui apparaîtront sur la machine sur laquelle vous souhaitez l'utiliser. Faites des captures d'écran si nécessaire.

Cette interface sera probablement très utile pour le débogage. J'ai travaillé avec des systèmes qui avaient des fonctionnalités de débogage telles que :

  • Un système dans lequel le programmeur établit une liste de "paramètres enregistrés" (variables internes). Vous indiquiez au système ceux que vous vouliez voir rapportés (jusqu'à 8) et ensuite, lorsque vous demandiez au système les paramètres enregistrés, il les retournait en un seul paquet de données. J'ai aimé cette méthode, mais selon la complexité du système, vous pouvez ou non être en mesure de les spécifier au moment de l'exécution (ou vous pouvez faire quelque chose de simple et envoyer au système un masque qui sélectionnera ceux que vous voulez renvoyer).

  • Paquets de données qui "cassent" le comportement et permettent aux parties du système d'être testées indépendamment (par exemple, sur un convertisseur numérique/analogique, cette tension est émise, sur un port d'entrée/sortie, cet octet est stimulé, etc.)

Bonne chance !

2voto

Michael Burr Points 181287

FTP est un exemple de protocole qui fonctionne raisonnablement bien à la fois de manière interactive et avec l'automatisation. L'une des clés est que les réponses commencent par un code qui indique si un client automatisé doit prêter attention ou non. Il en va de même pour POP3.

Une chose intéressante à propos de ces protocoles est que lorsque vous développez/déboguez, vous pouvez raisonnablement piloter la communication à partir d'un terminal ordinaire ou script la communication en utilisant des script/ fichiers batch/quelque chose.

Cependant, ils n'assurent pas la fiabilité, qui est assurée par une couche inférieure de la pile de communication. C'est un élément qui doit être pris en compte dans la plupart des systèmes de communication embarqués.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X