Comment créer un pilote de périphérique Linux intégré (11)

11ème: Ajouter un périphérique I2C à l'arborescence des périphériques

À propos de cette série

Article HowTo pour développer des pilotes de périphériques Linux embarqués en tant que modules de noyau. Tout le contenu de cet article peut être exécuté sur Raspberry Pi.

Le code source complet qui apparaît dans cet article

https://github.com/take-iwiw/DeviceDriverLesson/tree/master/11_01

Contenu de cette époque

Jusqu'à présent, nous avons implémenté plusieurs pilotes de périphériques. Cependant, chaque pilote de périphérique avait des «informations spécifiques au matériel» directement dans le pilote de périphérique.

Par exemple, dans 5ème fois, GPIO Devadler a été implémenté en frappant directement le registre mappé en mémoire. À ce moment-là, j'avais des informations spécifiques à la puce (SoC) telles que l'adresse offset dans l'appareil. Ce n'est pas bien. (En premier lieu, GPIO lui-même n'est pas créé et les fonctions standard du noyau Linux sont généralement utilisées.)

Même si vous utilisez les fonctions standard du noyau Linux, Devadora peut toujours avoir des informations spécifiques au matériel. Dans 10th, les périphériques I2C étaient accessibles à l'aide des fonctions de contrôle I2C standard du noyau Linux. Cependant, les informations spécifiques à la carte telles que le bus I2C auquel le périphérique I2C cible est connecté et l'adresse de l'esclave ont été décrites dans le périphérique.

Cela n'est plus autorisé par les règles. La raison en est que le code augmente régulièrement avec chaque variation de SoC et de carte. Aujourd'hui, ces informations spécifiques au matériel sont gérées par l'arborescence des périphériques.

La dernière fois, j'ai créé un pilote de périphérique pour un capteur d'accélération (LIS3DH) connecté à I2C. Cependant, à ce moment, il était nécessaire de fournir manuellement au noyau des informations sur le périphérique I2C. Cette fois, je vais essayer d'incorporer ces informations dans l'arborescence des périphériques. Cet article concerne le Raspberry Pi2 Model B

Fichiers liés à l'arborescence des appareils

Bien qu'il soit appelé "arborescence de périphériques", il s'agit en fait d'un micrologiciel au format binaire. L'extension sera .dtb. C'est sous / boot dans Raspeye. Par exemple, pour RaspberryPi2 Model B, ce serait / boot / bcm2709-rpi-2-b.dtb.

ls /boot/*.dtb
/boot/bcm2708-rpi-0-w.dtb     /boot/bcm2709-rpi-2-b.dtb  /boot/bcm2835-rpi-a-plus.dtb  /boot/bcm2835-rpi-zero.dtb
/boot/bcm2708-rpi-b.dtb       /boot/bcm2710-rpi-3-b.dtb  /boot/bcm2835-rpi-b.dtb       /boot/bcm2836-rpi-2-b.dtb
/boot/bcm2708-rpi-b-plus.dtb  /boot/bcm2710-rpi-cm3.dtb  /boot/bcm2835-rpi-b-plus.dtb
/boot/bcm2708-rpi-cm.dtb      /boot/bcm2835-rpi-a.dtb    /boot/bcm2835-rpi-b-rev2.dtb

Les informations spécifiques au SoC doivent être stockées dans le fichier DTSI et les informations spécifiques à la carte doivent être stockées dans le fichier DTS. En les compilant avec un compilateur spécial appelé DTC, le fichier DTB mentionné précédemment est créé. Pour Raspeye 2, il se trouve dans / linux / arch / arm / boot / dts / bcm2709-rpi-2-b.dts.

Réécrire directement le fichier dtb (version découpée)

Ajouter à l'arborescence des appareils

Comme j'écrirai plus tard, la bonne façon est d'apporter dans l'arborescence des sources Linux, éditer / linux / arch / arm / boot / dts / bcm2709-rpi-2-b.dts et compiler. Cependant, dans cette série, je l'ai vérifié aussi facilement que possible sur Razpai. Encore une fois, je vais l'essayer facilement d'abord.

Veuillez sauvegarder bcm2709-rpi-2-b.dts de la carte SD sur un PC, etc. à l'avance. Au pire, cela peut ne pas démarrer. Il installe également le compilateur (DTC) pour l'arborescence des périphériques. sudo apt-get install device-tree-compiler

Puis recompilez le fichier DTB actuellement utilisé dans DTS.

dtc -I dtb -O dts /boot/bcm2709-rpi-2-b.dtb > dis_bcm2709-rpi-2-b.dts

Cela créera un fichier texte appelé dis_bcm2709-rpi-2-b.dts. Ce fichier contient une arborescence d'informations de connexion de périphérique sur cette carte (Raspy 2). En outre, l'adresse du registre, etc. est également répertoriée. Cette fois, supposons que vous connectiez LIS3DH (adresse esclave = 0x18) à I2C_1. Tout d'abord, recherchez le nœud pour I2C1. Il est écrit dans l'adresse, mais il est à ʻi2c @ 7e804000. Ajoutez-y un nœud appelé mydevice. En définissant «compatible» sur «mycompany, myoriginaldevice», il est spécifié comme «un périphérique nommé myoriginaldevice fabriqué par un fabricant nommé mycompany». Définissez également l'adresse de l'esclave à la place de reg`. Cela amène le noyau à reconnaître que cette carte a un périphérique appelé "mycompany, myoriginaldevice" connecté à 0x18 sur I2C_1.

dis_bcm2709-rpi-2-b.dts


réduction
i2c@7e804000 {
	compatible = "brcm,bcm2835-i2c";
	reg = <0x7e804000 0x1000>;
	interrupts = <0x2 0x15>;
	clocks = <0x7 0x14>;
	#address-cells = <0x1>;
	#size-cells = <0x0>;
	status = "disabled";
	pinctrl-names = "default";
	pinctrl-0 = <0x10>;
	clock-frequency = <0x186a0>;
	phandle = <0x20>;

	/*Ajoutez votre propre appareil*/
	mydevice@18 {
		compatible = "mycompany,myoriginaldevice";
		reg = <0x18>;
	};
};
réduction

Après l'édition, compilez avec la commande suivante et écrasez le fichier DTB d'origine. Pour le moment, définissez le droit d'accès.

dtc -O dtb -o bcm2709-rpi-2-b.dtb dis_bcm2709-rpi-2-b.dts
chmod 755 bcm2709-rpi-2-b.dtb
sudo cp bcm2709-rpi-2-b.dtb /boot/bcm2709-rpi-2-b.dtb
sudo reboot yes

Vous pouvez vérifier les informations de l'arborescence des périphériques dans / proc / device-tree. Après le redémarrage, il réussit si mon appareil est ajouté sous I2C1.

ls /proc/device-tree/soc/i2c@7e804000/mydevice@18/
   compatible  name  reg

Prise en charge côté pilote de périphérique

Du côté du pilote de périphérique, il est nécessaire d'enregistrer le périphérique correspondant. Auparavant, j'avais enregistré un appareil appelé "mycompany, myoriginaldevice" dans l'arborescence des appareils, je vais donc le faire correspondre. Pour ce faire, définissez struct of_device_id sur" mycompany, myoriginaldevice "et enregistrez-le dans .of_match_table de struct i2c_driver`. À part cela, c'est la même chose que l'implémentation précédente. Le code source est indiqué ci-dessous.

myDeviceDriver.c


#include <linux/init.h>
#include <linux/module.h>
#include <linux/types.h>
#include <linux/kernel.h>
#include <linux/device.h>
#include <linux/i2c.h>
#include <linux/of_platform.h>

/***Informations sur cet appareil***/
MODULE_LICENSE("Dual BSD/GPL");
#define DRIVER_NAME "MyDevice"				/* /proc/Nom de l'appareil affiché sur les appareils, etc.*/

/*Tableau de correspondance des périphériques gérés par ce pilote de périphérique*/
/*Correspond à ce qui suit en dts
	i2c@7e804000 {
		mydevice@18 {
			compatible = "mycompany,myoriginaldevice";
			reg = <0x18>;
		};
*/
static const struct of_device_id mydevice_of_match_table[] = {
	{.compatible = "mycompany,myoriginaldevice",},
	{ },
};
MODULE_DEVICE_TABLE(of, mydevice_of_match_table);

/*Enregistrer une table qui identifie les périphériques gérés par ce pilote de périphérique*/
/*L'important est le champ du prénom. Cela détermine le nom de l'appareil. Le dos est des données qui peuvent être utilisées librement avec ce pilote. Insérer des pointeurs et des numéros d'identification*/
static struct i2c_device_id mydevice_i2c_idtable[] = {
	{"MyI2CDevice", 0},
	{ }
};
MODULE_DEVICE_TABLE(i2c, mydevice_i2c_idtable);

static int mydevice_i2c_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	printk("mydevice_i2c_probe\n");
	if(id != NULL)
		printk("id.name = %s, id.driver_data = %d", id->name, id->driver_data);
	if(client != NULL)
		printk("slave address = 0x%02X\n", client->addr);

	/*Habituellement ici pour vérifier si l'appareil est pris en charge par ce Devadora*/

	int version;
	version = i2c_smbus_read_byte_data(client, 0x0f);
	printk("id = 0x%02X\n", version);

	return 0;
}

static int mydevice_i2c_remove(struct i2c_client *client)
{
	printk("mydevice_i2c_remove\n");
	return 0;
}

static struct i2c_driver mydevice_driver = {
	.driver = {
		.name			= DRIVER_NAME,
		.owner			= THIS_MODULE,
		.of_match_table = mydevice_of_match_table,
	},
	.id_table		= mydevice_i2c_idtable,		//Périphériques I2C pris en charge par ce pilote de périphérique
	.probe			= mydevice_i2c_probe,		//Processus appelé lorsque le périphérique I2C cible est reconnu
	.remove			= mydevice_i2c_remove,		//Processus appelé lorsque le périphérique I2C cible est supprimé
};

module_i2c_driver(mydevice_driver);

Le noyau appellera le pilote de périphérique correspondant en fonction des informations de connexion dans l'arborescence des périphériques. L'adresse de l'esclave définie dans l'arborescence des périphériques est stockée dans la struct i2c_client passée à mydevice_i2c_probe ().

Un point à noter est que dans ce cas, struct i2c_device_id contiendra NULL. Je ne sais pas si c'est la raison, mais il semble que «.probe» sera bientôt aboli. Il semble utiliser .probe_new à la place. Dans .probe_new, struct i2c_device_id est supprimé.

Essayez de bouger

Construisez et chargez avec la commande suivante.

make && sudo insmod MyDeviceModule.ko
dmesg
[ 3507.003163] mydevice_i2c_probe
[ 3507.003175] slave address = 0x18
[ 3507.003656] id = 0x33

Si vous regardez le journal, vous pouvez voir que la sonde est appelée correctement et que la communication I2C est également possible. La dernière fois, j'avais besoin de notifier manuellement la connexion de l'appareil, mais cette fois je ne l'ai pas fait.

Créer DTB à partir du code source

Préparation environnementale

Faisons un DTB à partir du code source Linux pour Raspeye. Tout d'abord, récupérez le code source. Installez également les outils nécessaires à la construction. Fondamentalement, c'est comme (https://www.raspberrypi.org/documentation/linux/kernel/building.md). Puisqu'il s'agit d'une version native, aucune autre préparation n'est requise.

sudo apt-get install git bc
git clone https://github.com/raspberrypi/linux.git

Essayez de modifier le fichier DTS pour Raspeye

Le fichier DTS pour Raspberry Pi 2 Model B est / linux / arch / arm / boot / dts / bcm2709-rpi-2-b.dts. (Ce fichier est beaucoup plus propre que le fichier dts compilé à l'envers, car il est divisé en plusieurs fichiers. Ce fichier dts inclut bcm2709.dtsi au début. Il semble que cela soit gâché car tous les fichiers dts compilés à l'envers sont inclus.)

Modifiez / linux / arch / arm / boot / dts / bcm2709-rpi-2-b.dts de la même manière que précédemment. Ajoutez l'appareil à la place de I2C_1.

/linux/arch/arm/boot/dts/bcm2709-rpi-2-b.dts


réduction
&i2c1 {
	pinctrl-names = "default";
	pinctrl-0 = <&i2c1_pins>;
	clock-frequency = <100000>;

	/*Ajoutez votre propre appareil*/
	mydevice@18 {
		compatible = "mycompany,myoriginaldevice";
		reg = <0x18>;
	};
};
réduction

Essayez de créer DTB

Après avoir modifié le fichier DTS, compilez uniquement le DTB avec la commande suivante. La compilation sur Raspeye prend moins d'une minute. Copiez le fichier DTB résultant dans / boot.

cd ~/linux
KERNEL=kernel7
make bcm2709_defconfig
make -j4 dtbs
sudo cp arch/arm/boot/dts/*.dtb /boot/
sudo cp arch/arm/boot/dts/overlays/*.dtb* /boot/overlays/
sudo cp arch/arm/boot/dts/overlays/README /boot/overlays/

Remarque

DTB pour les superpositions semble être utilisé lorsque l'état de la connexion change de manière dynamique après le démarrage du noyau. Vous n'avez donc pas à le copier.

Essayez de bouger

Le pilote de périphérique est le même que la version découpée précédente et est OK. Le redémarrage devrait donner le même résultat.

en conclusion

J'ai essayé de jouer avec l'arborescence des appareils en utilisant un appareil I2C comme exemple. Le contenu mentionné dans cet article n'est qu'une touche de l'arborescence des appareils. Pour en savoir plus sur l'arborescence des appareils, veuillez consulter l'article + lien sur ici.

Recommended Posts

Comment créer un pilote de périphérique Linux intégré (11)
Comment créer un pilote de périphérique Linux intégré (8)
Comment créer un pilote de périphérique Linux intégré (1)
Comment créer un pilote de périphérique Linux intégré (4)
Comment créer un pilote de périphérique Linux intégré (7)
Comment créer un pilote de périphérique Linux intégré (2)
Comment créer un pilote de périphérique Linux intégré (3)
Comment créer un pilote de périphérique Linux intégré (6)
Comment créer un pilote de périphérique Linux intégré (5)
Comment créer un pilote de périphérique Linux intégré (10)
Comment créer un pilote de périphérique Linux intégré (9)
Comment créer un pilote de périphérique Linux intégré (12) (Terminé)
Comment faire reconnaître Yubico Yubikey par Manjaro Linux
Comment créer un outil CLI interactif avec Golang
Comment créer un serveur HTTPS avec Go / Gin
[Python] Comment créer une matrice de contiguïté / liste de contiguïté [Théorie des graphes]
Comment créer un laboratoire de piratage - Kali Linux (2020.1) VirtualBox 64 bits Partie 2-
Comment créer un laboratoire de piratage - Kali Linux (2020.1) VirtualBox 64-bit edition -
Comment créer un package Python (écrit pour un stagiaire)
Comment créer un fichier ISO (image CD) sous Linux
Comment faire une traduction japonais-anglais
Comment créer un bot slack
Comment installer VMware-Tools sur Linux
Comment créer un robot - Avancé
Comment créer une fonction récursive
Comment installer MBDyn (Linux Ubuntu)
[Blender] Comment créer un plug-in Blender
[Blender] Comment rendre les scripts Blender multilingues
Comment créer un robot - Basic
Comment créer un pilote de langage MongoDB C
Comment vérifier la version du système d'exploitation Linux
Comment transformer une chaîne en tableau ou un tableau en chaîne en Python
Comment obtenir le pilote d'imprimante pour Oki Mac sous Linux
Comment rendre les caractères de Word Cloud monochromatiques
Comment créer mon propre serveur Linux
Comment rendre le sélénium aussi léger que possible
[Linux] Comment subdiviser des fichiers et des dossiers
Comment créer un bot LINE à intelligence artificielle avec l'API de messagerie Flask + LINE
Comment installer aws-session-manager-plugin sur Manajro Linux
[Python] Comment rendre une classe itérable
python3 Comment installer un module externe
Comment créer un environnement NVIDIA Docker
Comment convertir Python en fichier exe
Je veux savoir comment fonctionne LINUX!
[Linux] Comment utiliser la commande echo
Comment mettre à jour PHP sur Amazon Linux 2
Comment afficher des pictogrammes sur Manjaro Linux
Comment installer des packages sur Alpine Linux
[Cocos2d-x] Comment créer une liaison de script (partie 2)
Comment faire fonctionner Linux depuis la console
Comment installer le sous-système Windows pour Linux
Comment mettre hors tension de Linux sur Ultra96-V2
Comment mettre à jour la sécurité sur CentOS Linux 8
Je veux faire un programme d'automatisation!