Bien réussir la gestion d’une carte micro-SD dans les systèmes embarqués : le logiciel
Cet article fait partie d’une série. Vous pouvez trouver le premier ici.
Implémentation du pilote
De nombreux SDKs contiennent déjà un pilote pour les cartes SD, en SPI ou en SDIO selon les fabricants et les modèles. Mais ce n’est pas une règle générale, et l’étape d’écriture de pilote de carte SD est un défi en soi.
Avec le temps, de nombreuses variantes de cartes SD sont apparues (SDSC v1, SDSC v2, SDHC, SDXC, SDUC). Ce sont autant de spécificités à prendre en compte lors de l’implémentation du pilote de la carte. En particulier, une section critique devra retenir toute votre attention : l’initialisation de la carte. Elle a la double fonction d’initialiser son contrôleur interne (bus de communication, tension d’alimentation, vitesse de transfert), mais aussi de vous indiquer le type de carte qui a été insérée dans le connecteur, et donc sa capacité en termes de transfert. Sachez d’autre part que les cartes MMC et puces eMMC suivent le même mode d’emploi, ce qui fait qu’un driver suffisamment complet vous permettra d’interfacer ce type de mémoire par la même occasion (par exemple une puce flash eMMC embarquée sur votre système). Si vous avez opté pour un bus SPI, vous ne pourrez pas accéder aux cartes de type SDUC. Toute reproduction de la spécification étant formellement interdite, nous vous invitons à vous référer à ce document directement dans lequel vous trouverez le diagramme d’initialisation des cartes pour chacun des deux types de bus.
La mise en œuvre des commandes SD et des types de réponses possibles à ces commandes peut paraître complexe au premier abord, mais leur compréhension est absolument nécessaire pour une implémentation fiable. Sans rentrer dans les détails des processus d’initialisation et de transfert, voici quelques astuces qui vous permettront, à nouveau, d’élargir l’éventail des modèles supportés par votre système, et qui pour certaines sortent des recommandations de la spécification :
- L’émission de 80 cycles d’horloge seule avant toute communication avec une carte au démarrage : la ligne CS doit rester à l’état haut pendant cette séquence. Par exemple, envoyer 10 fois un octet 0xFF à la carte sans activer la ligne CS.
- L’émission de 8 cycles d’horloges après toute communication avec la carte, permettant ainsi au contrôleur interne de la carte de retourner dans un état de veille (à nouveau avec la ligne CS à l’état haut). Cette étape peut s’avérer obligatoire pour le bon fonctionnement de certains modèles, et intervient aussi dans le cadre de la réduction de la consommation de la carte.
- Optionnellement, vous pouvez envoyer 8 cycles d’horloge avec les lignes de données à l’état haut (envoyez un octet 0xFF sur le bus SPI) au début et à la fin des communications avec la carte (juste après l’activation de la ligne CS et juste avant son relâchement).
Encore une fois, de nombreuses propositions d’implémentations sont disponibles sur des dépôts de code publics, bien que souvent sans couche d’abstraction facilitant la portabilité du code sur votre propre plateforme de développement. Néanmoins la variété des structures de code est formative (gestion des commandes, des réponses et des transferts de données).
Intégration d’un système de fichier
Si vous souhaitez lire ou écrire sur la carte depuis un ordinateur fonctionnant sous Windows ou Linux, la dernière étape consiste à interfacer votre pilote avec une librairie de gestion de fichiers.
Nous ne pouvons que vous conseiller de vous tourner vers la librairie FatFS écrite par ChaN. Open-source, vous pouvez l’utiliser, la modifier et la distribuer librement (elle est compatible avec la plupart des licences open-source par ailleurs). Cette librairie prend en charge les systèmes de gestion de fichiers FAT, FAT32 et exFAT, qui sont les plus répandus pour les cartes SD et micro-SD. Vous retrouverez des fonctions de formatage, de création de dossiers et de fichiers, d’écriture et de lecture. Par défaut, les cartes de taille inférieure ou égale à 2 Go (SDSC) seront formatées en FAT, celles inférieure ou égale à 32 Go en FAT32 (SDHC). Enfin pour les cartes de très grande capacité vous pourrez bénéficier du système exFAT. La librairie est capable de gérer plusieurs volumes physiques et logiques simultanément et en facilite même l’accès grâce à une nomenclature simple et personnalisable (proche de celle de Windows « C:/ ») : Vous avez en effet la liberté d’adresser les volumes par un numéro (par défaut) sous la forme « 0 :/fichier1.txt » ou « 0:fichier1.txt » ou bien par une chaîne de caractère « SD:/fichier1.txt ». A vrai dire, cette librairie regorge d’options personnalisables qui permettent, d’une part, d’adapter les accès au média de stockage à votre goût, mais surtout de choisir les fonctionnalités à utiliser, très pratique lorsque vous cherchez à limiter l’empreinte de cette librairie dans votre code (prise en charge des noms de fichiers de plus 12 charactères, etc.). L’ensemble de ces options de configuration sont ajustables dans le fichier ffconf.h.
Sa mise en œuvre est assez simple, car elle demande l’implémentation de quelques fonctions dont les prototypes sont définis dans le fichier diskio.h (à vous d’écrire votre propre fichier diskio.c qui implémente ces fonctions). Une implémentation minimaliste consiste à écrire les fonctions disk_initialize(), disk_read() et disk_write(). Les autres peuvent, encore une fois, dans une version allégée ne retourner que des valeurs par défaut. Les trois fonctions mentionnées n’auront qu’à faire appel à votre pilote de carte SD. Attention toutefois à ne pas lier directement la fonction disk_initialize() à l’ensemble de l’initialisation de votre carte SD qui ne doit pas être répétée de multiples fois (et s’avérer assez longue car elle s’effectue à vitesse réduite). Il est aussi utile de vérifier la taille des blocs à lire ou à écrire lors des appels à disk_read() et disk_write() pour bénéficier de la plus grande rapidité de lecture et écriture à l’aide des commandes SD WRITE MULTI BLOCK ou READ MULTI BLOCK lorsque la taille dépasse celle d’un bloc de carte SD (512 octets).
Bien que très pratique, l’empreinte dans la mémoire programme de votre microcontrôleur de cette librairie, même avec le minimum de fonctions actives, n’est pas négligeable (entre 4 ko et 10 ko pour une implémentation minimale en lecture/écriture selon le compilateur). Certains microcontrôleurs, les plus petits du marché en termes de mémoire, ne peuvent pas accueillir une telle librairie. Il existe donc une version encore plus petite, dénommée PetitFatFS, dénuée de fonctions de formatage et de création de dossiers (les noms de fichiers longs ne sont pas non plus supportés), mais dont la consommation de mémoire programme est comprise entre 2 ko et 4 ko tandis que l’utilisation de la RAM se limite à 44 octets (plus une petite partie de la stack).