Maison > Article > Tutoriel système > Linux peut-il fonctionner sur un MCU 8 bits ?
Nous voyons souvent des débutants demander sur les forums de microcontrôleurs si leurs minuscules microcontrôleurs 8 bits peuvent exécuter Linux. Ces questions suscitent souvent des éclats de rire. Nous voyons souvent des gens sur les forums Linux demander quelle est la configuration minimale requise pour exécuter Linux. La réponse courante est que Linux nécessite une architecture 32 bits et une MMU (Memory Management Unit) et au moins 1 Mo de RAM pour satisfaire le noyau.
Cependant, ce projet vise (et a réussi) à briser ces perceptions. La carte de développement présentée dans l'image ci-dessous est basée sur l'ATmega1284P. J'ai (un étranger) également réalisé une carte de développement basée sur ATmega644a, qui a également été un succès. Cette carte de développement n'utilise pas d'autre processeur et peut démarrer le noyau Linux 2.6.34. En fait, il peut même exécuter une pile Ubuntu complète, y compris X (si vous êtes prêt à attendre qu'il démarre) et l'environnement de bureau Gnome.
▍RAM (mémoire vive)
Oui, c'est vrai, une installation complète de Linux nécessite plusieurs mégaoctets de RAM et un processeur 32 bits avec une MMU. Ce projet a tout pour plaire. Commençons par accéder à la RAM. Comme vous pouvez le voir, il y a un ancien module mémoire SIMM à 30 broches dans le circuit. C’est ce que les PC basés sur 80286 utilisaient autrefois. Il s'interface avec l'ATmega et j'écris du code pour y accéder et le rafraîchir selon les spécifications (la SDRAM a besoin d'un rafraîchissement à taux constant pour éviter de perdre des données).
À quelle vitesse est-ce ? L'interruption de rafraîchissement se produit toutes les 62 ms et prend 1,5 ms, elle occupe donc moins de 3 % du processeur. Accédez à la RAM pour faciliter la programmation, un octet à la fois. La bande passante maximale produite est d’environ 300 Ko/s.
***▍*Stockage
Pour que la RAM fonctionne en état de veille, nous devons régler deux choses. Le stockage n’est pas un problème trop difficile à résoudre. Il est très simple d'interagir avec la carte SD à l'aide de SPI, et je l'ai fait dans mon projet. Une carte SD de 1 Go fonctionnera très bien, même si 512 Mo suffisent pour ce système de fichiers particulier (Ubuntu Jaunty).
ATmega dispose d'un module SPI matériel, mais pour une raison quelconque, il n'a pas fonctionné très bien, j'ai donc supprimé l'interface. C'est encore assez gros - environ 200 Ko/s. Cela est également parfaitement logique pour le projet : il peut être implémenté sur n'importe quel microcontrôleur doté de suffisamment de broches, sans utiliser de modules matériels supplémentaires.
***▍*CPU (unité centrale de traitement)
Il ne reste plus que les exigences en matière de CPU et de MMU 32 bits. Cependant, l'AVR n'a pas de MMU et il est en 8 bits. Pour surmonter cette difficulté, j'ai écrit un émulateur ARM. ARM est l'architecture que je connais le mieux, et elle est assez simple pour que je me sente à l'aise en écrivant un émulateur pour celle-ci. Pourquoi en écrire un au lieu d'en porter un ?
Eh bien, porter le code de quelqu'un d'autre n'est pas amusant, et je ne vois aucune documentation documentée sur le portage facile d'émulateurs sur des appareils 8 bits. Une raison : l'insistance du compilateur AVR sur 16 bits pour gérer les entiers vous posera des problèmes avec le simple "(1
***▍*Autres fonctions
La carte communique avec le monde réel via un port série. Actuellement, il est connecté via un port série à un minicom fonctionnant sur mon PC, mais une connexion alternative testable serait un clavier et un écran LCD de caractères connectés au circuit, ce qui le rendrait complètement autonome. Il y a deux autres LED sur la carte. Ils indiquent l'accès à la carte SD. L’un représente l’opération de lecture et l’autre représente l’opération d’écriture. Il y a aussi un bouton sur le circuit imprimé. Lorsqu'il est enfoncé et maintenu enfoncé pendant 1 seconde, le port série sera retiré de la vitesse actuellement effective du processeur émulé. La fréquence principale de l'AVR est de 24 MHz (un léger overclock au-dessus des 20 MHz d'origine).
***▍*À quelle vitesse est-ce ?
uARM n’a certainement pas de démon de taux. Il a fallu environ 2 heures pour démarrer dans l'invite BASH (ligne de commande du noyau "init=/bin/bash"). Ensuite, il a fallu plus de 4 heures pour démarrer l'intégralité d'Ubuntu ("exec init" puis connexion). Démarrer X prendra plus de temps. La vitesse effective du processeur émulé est d'environ 6,5 kHz, ce qui correspond à ce à quoi vous vous attendez en émulant un processeur 32 bits et une MMU sur un maigre microcontrôleur 8 bits. Bizarrement, une fois démarré, le système est quelque peu utilisable. Vous pouvez saisir une commande et obtenir une réponse dans la minute. Ce qui signifie que vous pouvez réellement l'utiliser. Par exemple, je l'ai utilisé aujourd'hui pour formater ma carte SD. Ce n'est certainement pas le plus rapide, mais j'ai l'impression que c'est probablement le moins cher, le plus lent, le plus facile à assembler à la main, le plus petit nombre de pièces et le PC Linux le plus bas de gamme. Le circuit imprimé est soudé à la main à l’aide de fils, sans même avoir besoin d’un circuit imprimé (PCB).
***▍*Détails de l'émulateur ?
L'émulateur est assez modulaire, ce qui lui permet d'être étendu pour émuler à volonté d'autres configurations SoC (System on Chip) et matérielles. Le processeur simulé est ARMv5TE. Il y a quelque temps, j'ai commencé à travailler sur le support d'ARMv6, mais cela n'est pas terminé (comme le montre le code) car ce n'est pas très nécessaire. Le SoC simulé est le PXA255.
Grâce à la conception modulaire, vous pouvez remplacer le fichier SoC.c et compiler un nouveau SoC complet en utilisant le même cœur ARMv5TE, ou remplacer le cœur, ou remplacer les périphériques comme vous le souhaitez. C'est volontaire, je veux dire que ce code est également un exemple assez intéressant du fonctionnement d'un SoC ARM. Le code de l’émulateur de processeur lui-même n’est pas très soigné, donc c’est un émulateur de processeur. Cela a été écrit il y a quelques années pendant plus de 6 mois de temps libre, puis mis de côté. Il a été récemment ressuscité spécifiquement pour ce projet. L'émulateur implémente i-cache pour améliorer la vitesse. Cela donne beaucoup d'aide à l'AVR, permettant d'accéder à la mémoire interne à plus de 5 Mo par seconde contrairement à ma RAM externe. Je n'ai pas encore commencé à implémenter d-cache (mise en cache des données), mais c'est sur ma liste de choses à faire. L'accès aux périphériques de bloc n'est pas émulé en tant que périphériques SD. Cela s'est avéré trop lent. Au lieu de cela, il existe un périphérique de disque paravirtualisé (pvdisk, voir pvDisk.tar.bz2, sous licence GPL), que j'ai écrit en utilisant un opcode invalide pour charger l'émulateur et accéder au disque. Le disque virtuel (disque virtuel) de mon image charge ce pvdisk puis modifie le répertoire racine en /dev/pvd1.
ramdisk est inclus dans "rd.img". Le "type de machine" que j'utilise est PalmTE2. Pourquoi? Comme je connais très bien ce matériel, c'est le premier type de machine PXA255 que je vois.
***▍*Hyperappel ?
Il existe certains services que vous pouvez adresser à l'émulateur en utilisant un opcode spécial. Dans ARM, c'est 0xF7BBBBBB, dans Thumb, c'est 0xBBBB. Ceux-ci ont été choisis car ils se situent dans une gamme où les garanties ARM ne sont pas définies. Le numéro d'hypercall est passé dans le registre R12, les paramètres sont passés dans les registres R0-R3 et la valeur de retour est placée dans R0.
Appel :
· 0 = Arrêter la simulation
· 1 = imprimer le nombre décimal
· 2 = caractères imprimés
· 3 = Obtenez la taille de la RAM
· 4 = bloquer le fonctionnement de l'appareil (R0 = fonctionnement, R1 = numéro de secteur). Notez que ceux-ci n'écrivent pas dans la RAM émulée, ils utilisent un autre hypercall pour remplir le tampon interne de l'émulateur auquel accède l'utilisateur émulé, un mot à la fois. J'avais l'intention d'implémenter DMA, mais je n'y suis pas encore parvenu.
Fonctionnement :
· 0 = Obtenir des informations (si le numéro de secteur est 0, renvoie le nombre de secteurs ; si le numéro de secteur est 1, renvoie la taille du secteur en octets)
· 1 = lecture du secteur
· 2 = écriture secteur
· 5 = bloquer l'accès au tampon du périphérique (R0 = valeur entrée/valeur sortie, R1 = nombre de mots, R2 = 1 si écrit, 0 sinon)
***▍*Support du pouce ?
Prise en charge complète de Thumb. J'ai triché un peu et décodé chaque chaîne d'instruction Thumb (instr) en sa chaîne d'instruction ARM équivalente et je l'ai exécutée au lieu d'utiliser les fonctions de l'émulateur ARM. Ce n'est pas aussi rapide que l'original, mais c'est simple et le code est petit. Il est possible d'utiliser une table de recherche de 256 Ko, mais je pense que 256 Ko est trop volumineux pour la mémoire flash du microcontrôleur. Certaines instructions Thumb ne peuvent pas être converties en instructions ARM, elles sont traitées correctement à la place.
Je veux en construire un !
À des fins non commerciales, vous pouvez certainement le faire. La méthode de câblage est la suivante :
· Les DQ0-DQ7 de la RAM sont connectés aux C0-C7 de l'AVR ;
· Les A0-A7 de la RAM connectent les A0-A7 de l'AVR ;· Les A8-A11 de la RAM connectent les B0-B3 de l'AVR ;
· RAM nRAM nRAS nCAS nWE connecter AVR D7 B4 B5;
· Le DI SCK DO de SD connecte le B6 B7 D6 de l'AVR ;· La lecture et écriture de la LED est connectée à D2 D3 de l'AVR (les autres broches de la LED sont connectées à la masse
) ;· Le bouton est connecté au D4 de l'AVR (les autres broches sont connectées à la masse).
La RAM peut être n'importe quel SIMM à 30 broches de 16 Mo pouvant fonctionner à un taux de rafraîchissement CAS avant RAS de 4 000 cycles toutes les 64 millisecondes. Celui que j'utilise (OWC) peut être acheté en ligne pour quelques dollars. Le schéma est présenté ici, cliquez pour agrandir.***▍*
Code source ?
Ce code est un peu compliqué, mais il fonctionne (le code ne peut pas être téléchargé en Chine). Pour configurer l'émulateur sur votre PC et l'essayer, tapez "make". Pour exécuter, utilisez "./uARM DISK_IMAGE". Pour créer la version PC optimisée, utilisez "make BUILD=opt". Pour créer une version en cours d'exécution d'AVR, utilisez "make BUILD=avr". Désormais, il est compilé pour cibler ATmega1284P. Pour compiler avec ATmega644 comme cible, en plus de modifier le makefile, réduisez le nombre dans icache.h afin que l'i-cache soit suffisamment petit pour correspondre à la RAM à l'intérieur du 644. Les fichiers hexadécimaux finaux pour 1284p sont également inclus dans l'archive.
▍Processus de démarragePour préserver l'espace de code dans AVR, presque aucun code de démarrage n'existe dans l'émulateur. En fait, la "ROM" totalise 50 octets : 8 octets sont utilisés pour sélectionner le mode Thumb, et du code Thumb lit le premier secteur de la carte SD et passe en mode Thumb (voir EmbeddedBoot.c). Le MBR de la carte SD possède un autre chargeur de démarrage (écrit en mode Thumb). Ce chargeur de démarrage examine le MBR, trouve la partition active et charge son contenu jusqu'à la fin de la RAM. Ensuite, il passe à l'adresse RAM de destination +512 (voir mbrBoot.c). Le troisième et plus grand chargeur de démarrage, ELLE (voir ELLE.c), s'exécute ici. Ce chargeur de démarrage déplace le disque virtuel, configure ATAGS et appelle le noyau. Je fournis tous les binaires et le code source afin que vous puissiez créer votre propre image si vous le souhaitez. Le processus de démarrage rappelle le démarrage d'un PC. :) L'outil mkbooting.sh inclus peut être utilisé pour créer une image de travail pour la partition de démarrage.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!