L’USB hôte, la clé USB et les fichiers

11 juillet 2025

Alors, oui, nous avons une piste pour régler nos problèmes de communication, surtout que l’USB nous avait été chaudement recommandé à la coupe.
Mais nous avions un autre souhait pour notre robot, avoir des logs. Mais pas juste une LED qui s’allume en cas de soucis, des vrais logs, des gros fichiers avec plein de données dedans !

Nous voyons que notre code de démonstration supporte la classe "Mass Storage", nous sommes donc sur la bonne voie. Mais que se passe-t-il lorsque nous connectons une clé USB ? Eh bien, pas grand-chose :

A device with address 1 is mounted
A device with address 1 is unmounted 

Alors comment aller plus loin ?

La bibliothèque TinyUSB propose une liste de fonctions pour gérer les périphériques "Mass Storage", accessible dans le fichier msc_host.h. Mais en observant ces fonctions, il n’y a rien qui ressemble à ouvrir ou fermer un fichier.

Du MSC au fichier : le système de fichier

Les fonctions USB vont permettre de lire ou d’écrire une plage d’octet sur le périphérique, comme si nous accédions à une mémoire — ce qui est le cas. C’est très bien pour écrire une donnée brute, mais pour créer des fichiers qui seront lisibles sur un ordinateur, il manque toute une couche logicielle. Ces fonctions USB sont inspirées du protocole SCSI dont nous avons la liste compréhensible des commandes. Et rien là-dedans ne permet d’ouvrir, lire ou écrire des fichiers. Il s’agit plutôt de fonctions pour copier des morceaux de mémoire.

Pour gérer des fichiers, il faut un système de fichier. Un système de fichier est une organisation de la mémoire qui contient :

  • d’une part une table de partition qui indique le nom des fichiers, leur arborescence dans les répertoires, leur taille et où trouver leur contenu
  • d’autre part, le contenu des fichiers aux endroits indiqués par la table de partition.

Sur microcontrôleur, il n’y a pas beaucoup de systèmes de fichier qui seraient à la fois simples et reconnus par un ordinateur. Le principal candidat est FAT/exFAT. Il s’agit en réalité d’une famille de système de fichiers (FAT12, FAT16, FAT32, exFAT). FAT12, le plus ancien date de 1980 et était utilisé sous QDOS, l’ancêtre de MS-DOS tandis que exFAT est encore couramment utilisé sur les cartes SD. Ces systèmes de fichier regroupent la mémoire par blocs pour faciliter sa gestion.

Si nous parlons d’une famille de système de fichier, c’est qu’au lieu d’implémenter la spécification, nous utilisons une bibliothèque qui gère toute cette famille. Cette bibliothèque, c’est FsFAT !

Interface entre TinyUSB et FsFAT

L’interface en TinyUSB et FsFAT se résume à quelques fonctions. Chacune de ces fonctions prend en argument le numéro du "disque" sur lequel effectuer les opérations.

  • disk_initialize : rien à faire, la connexion à la clé est gérée par l’USB
  • disk_status : renvoyer 0 si la clé correspondant à ce disque est branché, 1 sinon.
  • disk_read : appeler la fonction tuh_msc_read10 avec les bons paramètres, attendre que les tâches USB se soient bien exécutées
  • disk_write : appeler la fonction tuh_msc_write10 avec les bons paramètres, attendre que les tâches USB se soient bien exécutées
  • disk_ioctl : obtenir la taille et le nombre de blocs contenus sur la clé

Le code à étudier est certainement l’explorateur de fichier fourni dans les exemples de TinyUSB.

C’est un détail, mais FsFAT demande une fonction qui renvoie la date actuelle. Si vous n’avez pas d’horloge à l’heure sur votre microcontrôleur, Vous pouvez renvoyer n’importe quelle date, mais c’est cette date qui apparaîtra comme date de création ou de modification du fichier.

Côté architecture logicielle, nous avons "juste" rajouté la couche FsFAT à notre projet précédent :


Architecture logicielle - USB + FsFAT

Écrire dans un fichier

Nous étions un peu là pour ça, non ?

Pour écrire dans un fichier, la procédure est la suivante :

  1. f_mount : monter le système de fichier ;
  2. f_open : ouvrir le fichier ;
  3. f_write : écrire dans le fichier ;
  4. f_sync : forcer les écritures qui pourraient avoir été mises en attente ;
  5. f_close : fermer le ficher - une bonne pratique, pas forcément utile ici.

Rien de sorcier, mais il y a une petite subtilité. Les chemins sont sous cette forme :

[disque#:][/]répertoire/fichier

Les crochets [...] indiquent des éléments facultatifs. Si vous n’indiquez pas de disque, FsFAT supposera que vous cherchez à écrire sur le disque 0. Dans notre cas, ceci nous a joué un tour. Si nous connections la clé USB directement sur le Raspberry Pi Pico, elle obtenait l’adresse 1. Nous avions codé en dur l’adresse du disque dans nos fonctions disk_*. Mais en ajoutant un hub, l’adresse de la clé passait à 2 et plus rien ne marchait. C’est embêtant au début, mais très flexible par la suite. Vous pouvez gérer plusieurs clés USB par exemple. Imaginez en garder une en permanence sur le robot et une qui reçoit automatiquement les derniers logs lorsque vous la branchée.

Pour plus de détails, lisez la bonne documentation.

Alors, nous y sommes ?

Les performances ? Pas terribles, nous ne dépassons pas les 64 ko/s, ce qui est aussi la limite trouvée par rppicomidi dans son projet pico-usb-host-msc-demo... D’après le projet de rppicomidi, c’est la conception de l’USB sur le Raspberry Pi Pico qui n’est pas faite pour obtenir de bonnes performances en mode "hôte". De notre côté, nous n’avons pas les compétences pour nous prononcer sur la cause, mais nous réalisons le même constat...

Alors 64 ko/s, ça paraîtrait OK pour du log, mais ça veut dire que nous utilisons un cœur complet pour écrire sur la clé, et que notre ressource USB ne fait qu’écrire les logs, Or nous comptons sur l’USB pour la communication intra-robot, pas question de partir sur une solution qui semble déjà montrer ses limites...

Vous trouverez notre code en ligne ici !

Commentaires

Il n'y a pas de commentaires

Ajouter un commentaire

Pseudo :
Mail :

Texte :

Copyright "POIVRON" 2011-2023, tous droits réservés
Administration du site