Maison > Tutoriel système > Linux > le corps du texte

Simuler le processus d'initialisation automatique de Linux sur STM32

王林
Libérer: 2024-02-12 08:00:04
avant
877 Les gens l'ont consulté

Sous Linux, il existe de nombreuses idées de programmation qui valent la peine d'être apprises. De nombreux experts techniques ont appliqué ces idées et mécanismes à la programmation de microcontrôleurs, notamment en simulant le processus d'initialisation automatique du noyau Linux dans STM32.

De manière générale, nous suivons certaines routines lors de l'écriture de programmes. Nous exécuterons les fonctions les unes après les autres selon une logique séquentielle.

Simuler le processus dinitialisation automatique de Linux sur STM32

Si la logique est très complexe et implique de nombreux modules, alors le code exécuté séquentiellement sera gonflé et les modules seront très étroitement couplés. Il existe différents pilotes de périphériques dans le noyau Linux et il est presque impossible de les exécuter logiquement dans une séquence.

Et le code du kenrel peut contenir une si grande quantité de code, il est volumineux mais pas compliqué, il sépare efficacement chaque niveau et module, et une grande quantité de code est logiquement organisée ensemble, et cet appel initial joue un rôle essentiel.

En imitant cette méthode, nous effaçons enfin le code de la fonction principale dans l'image, séparons cette logique et obtenons la même fonction.

Comment implémenter une telle fonction nécessite quelques connaissances de base :

1. Organisation du code du programme

2. Connaissances liées aux scripts de liens.

3. Application des pointeurs de fonction.

Simuler le processus dinitialisation automatique de Linux sur STM32

L'organisation du code, comme l'image, vous devez connaître les variables a, b et le pointeur de fonction f, f2 sont stockés dans quelles sections du programme, vous pouvez lire cette implémentation du code de démarrage stm32 | au-dessus de a, f sont stockés dans le segment bss, b, f2 sont stockés dans le segment de données, car la valeur initiale a été donnée, et l'implémentation de cet appel int placera les données qui doivent être automatiquement initialisées dans un segment personnalisé, tel que .initcall.

Comment le mettre dans une section spécifique, vous devez utiliser le mot-clé attribut((section)) pour modifier la section de stockage des données.

Le programme actuel est compilé à l'aide de ces segments. À l'exception de .isr_vector, qui est également ajouté, les autres sont par défaut par le compilateur.

Simuler le processus dinitialisation automatique de Linux sur STM32

Ajoutez d'abord un morceau de code :

Simuler le processus dinitialisation automatique de Linux sur STM32

Bien sûr, cela ne suffit pas, vous devez également dire à l'éditeur de liens (LD) de lier la section .initcall au programme, cette section doit donc également être modifiée.

Simuler le processus dinitialisation automatique de Linux sur STM32

Cette section est alignée sur 8 octets, définit deux variables globales et relie ces données dans l'ordre 0-5. Avec ces deux modifications, jetons un œil à chaque section du programme.

Comme image :

Simuler le processus dinitialisation automatique de Linux sur STM32

Il y a une case rouge supplémentaire pour la section .initcalls. Cette section fait 8 octets au total, à partir de 0x80005a8.

Regardons la situation spécifique de ce paragraphe, en utilisant l'outil readelf.

Simuler le processus dinitialisation automatique de Linux sur STM32

Il correspond à l'outil de taille ci-dessus et l'adresse de la boîte verte est SystemInit (0x08000231, mode petit endian.)

Simuler le processus dinitialisation automatique de Linux sur STM32

Ainsi, grâce à l'attribut et à la modification du script de lien, la variable de pointeur de fonction est placée dans la section .initcall.

Alors, comment appeler cette fonction ? Elle est similaire aux données de segment de données d'initialisation précédentes. Elle traverse ce segment, puis extrait l'adresse de la fonction, puis convertit de force l'adresse du segment en pointeur de fonction, puis l'appelle directement. .

Simuler le processus dinitialisation automatique de Linux sur STM32Simuler le processus dinitialisation automatique de Linux sur STM32

L'image implémentée est de prendre l'adresse de la fonction dans la section .initcall puis de l'appeler directement. Il est très facile de confondre l'adresse de la fonction avec l'adresse de la variable du pointeur de fonction.

Avec le code modifié ainsi, la fonction d'initialisation automatique peut en effet être ajustée, mais à chaque fois je dois écrire une si longue section de static initcall_t __attribut__(( __ used__,__ section__(“.initcall.0.init”) )), c'est-à-dire inconfortable. Modifié via des macros dans le noyau Linux.

Il en va de même pour celui-ci.

Simuler le processus dinitialisation automatique de Linux sur STM32

Ajoutez quelques macros qui sont exécutées dans l'ordre logique du programme

0, low_level_init Par exemple, initialisez l'horloge de base du système

1, arch_init Par exemple, mettez l'architecture CPU d comme l'initialisation d'une initialisation de NVIC.

2. dev_init initialise les modules périphériques, tels que i2c, flash, spi, etc.

3. board_init effectue certains réglages pour des cartes matérielles spécifiques.

4. os_init Certains paramètres du système d'exploitation, tels que le système de fichiers, la pile de protocoles réseau, etc.

5, app_init exécute enfin le programme utilisateur.

Modifiez votre propre programme et utilisez plutôt des macros. De cette façon, l'appel à do_initcalls sera exécuté dans l'ordre de 0, 1 à 5.

Simuler le processus dinitialisation automatique de Linux sur STM32Simuler le processus dinitialisation automatique de Linux sur STM32

Enfin, jetons un œil à la section initcall :

Simuler le processus dinitialisation automatique de Linux sur STM32Simuler le processus dinitialisation automatique de Linux sur STM32Simuler le processus dinitialisation automatique de Linux sur STM32Simuler le processus dinitialisation automatique de Linux sur STM32

De cette façon, ajoutez simplement quelque chose comme dev_init(), app_init() à la fonction d'initialisation automatique, et elle sera appelée automatiquement, sans qu'il soit nécessaire de les exécuter un par un dans la fonction principale.

Par exemple, l'initialisation du contrôle i2c est placée dans dev_init. Il y a de nombreux périphériques esclaves i2c suspendus ci-dessous. Initialisez simplement chaque périphérique esclave avec app_init, même si un nouveau arrive, utilisez simplement ce app_init pour l'initialiser. pour changer celui d'origine, un haut degré de couplage entre modules séparés.

Cela simule l'initialisation et la vérification de Linux kenerl avec succès, et finalement téléchargé dans la bibliothèque.

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!

source:lxlinux.net
Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal