Notes d'étude sur le développement de pilotes Linux [1]: développement de pilotes de périphériques de caractères

table des matières

1. Pilote de périphérique de caractères

Deux étapes de développement de pilote de périphérique de caractère

1. Compilez le module de pilote de périphérique de caractères

2. Chargement et déchargement du module variateur

3. Mise en œuvre spécifique de l'enregistrement et de l'annulation des dispositifs de caractères

4. Réalisez la fonction de fonctionnement spécifique de l'appareil

Troisièmement, testez l'écriture et le test de l'application


1. Pilote de périphérique de caractères

Les périphériques caractères sont le type de pilote de périphérique le plus basique dans les pilotes Linux. Un périphérique caractère est un périphérique qui lit et écrit les octets un par un, et lit et écrit les données dans un ordre séquentiel. Par exemple, nos éclairages, boutons, IIC, SPI, LCD, etc. les plus courants sont tous des périphériques de caractères, et les pilotes de ces périphériques sont appelés pilotes de périphériques de caractères. Appels d'applications Linux au pilote

 

Le programme d'application s'exécute dans l'espace utilisateur et le pilote Linux fait partie du noyau, de sorte que le pilote s'exécute dans l'espace noyau. Lorsque nous voulons implémenter des opérations sur le noyau dans l'espace utilisateur, comme l'utilisation de la fonction open pour ouvrir le pilote / dev / led, car l'espace utilisateur ne peut pas directement opérer sur le noyau, nous devons utiliser une méthode appelée "appel système" pour implémenter des utilisateurs esclaves L'espace est "piégé" dans l'espace noyau, de sorte que le fonctionnement du pilote sous-jacent peut être réalisé. Ces fonctions telles que ouvrir, fermer, écrire et lire sont fournies par la bibliothèque C. Dans les systèmes Linux, les appels système font partie de la bibliothèque C. Lorsque nous appelons la fonction ouverte, le processus est comme indiqué dans la figure

 

Deux étapes de développement de pilote de périphérique de caractère

Choses à noter lors de l'écriture d'un pilote:

1. Le code source du noyau Linux est nécessaire lors de la compilation du pilote! Par conséquent, décompressez le code source du noyau Linux et compilez le code source du noyau Linux. Obtenez zImage et .dtb. Vous devez utiliser les zImage et dtb compilés pour démarrer le système.

2. Démarrez à partir de la carte SD et uboot est gravé sur la carte SD. uboot obtient zimage et dtb d'ubuntu via tftp, et rootfs est également monté via nfs.

3. Configurer bootcmd et bootargs

setenv bootargs 'console=ttymxc0,115200
  root=/dev/nfs rw
  nfsroot=192.168.199.158:/home/denghengli/linux/nfs/rootfs
  ip=192.168.199.20:192.168.199.158:192.168.199.1:255.255.255.0::eth0:off'
setenv bootcmd ‘tftp 80800000 zImage; tftp 83000000 imx6ull-alientek-emmc.dtb; bootz 80800000 - 83000000;’

4. Placez le fichier .ko compilé dans le répertoire / lib / modules / <kernel-version> du système de fichiers racine .

1. Compilez le module de pilote de périphérique de caractères

Étape 1: créer un projet VSCode

Étape 2: Ajouter le chemin du fichier d'en-tête pour VSCode

Le chemin du fichier d'en-tête dans le code source. Ouvrez VSCode, appuyez sur Crtl + Shift + P "pour ouvrir la console VSCode, puis entrez C / C ++: Modifier les configurations (JSON)", ouvrez le fichier de configuration d'édition C / C ++, après l'avoir ouvert, il générera automatiquement un nom dans le répertoire .vscode C'est le fichier de c_cpp_properties.json, includePath représente le chemin du fichier d'en-tête, vous devez ajouter le chemin du fichier d'en-tête dans le code source Linux

"${workspaceFolder}/**", 
"/home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux/include", 
"/home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux/arch/arm/include", 
"/home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux/arch/arm/include/generated/"

Étape 3: Créez un nouveau fichier de pilote de caractères chardevbase.c et écrivez un Makefile

KERNELDIR := /home/denghengli/linux/IMX6ULL/linux/nxptoalpha_linux

CURRENT_PATH := $(shell pwd)
#obj-m表示将 chardevbase.c这个文件编译为chardevbase.ko模块。
obj-m := chardevbase.o

build: kernel_modules

#具体的编译命令,后面的 modules表示编译模块,-C表示将当前的工作目录切
#换到指定目录中,也就是 KERNERLDIR目录。 M表示模块源码目录,“ make modules”命令
#中加入 M=dir以后程序会自动到指定的 dir目录中读取模块的源码并将其编译为 .ko文件。
kernel_modules :
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules

clean:
	$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean

Une fois terminé, entrez make pour compiler le fichier de module dynamique de chardevbase.ko

2. Chargement et déchargement du module variateur

Une fois le noyau démarré, entrez dans le système de fichiers racine et utilisez insmod ou modprobe pour charger le pilote. La commande insmod ne peut pas résoudre la dépendance du module. Modprobe analysera la dépendance du module, puis chargera tous les modules dépendants du module dans le noyau. La commande est plus intelligente que insmod; par défaut, la commande modprobe recherchera les modules dans le répertoire / lib / modules / <kernel-version> sous le système de fichiers racine . Lors du chargement d'un nouveau module avec modprobe, vous devez d'abord appeler la commande depmod. Utilisez la commande rmmod pour supprimer le pilote.

比如加载chardevbase.ko 
insmod chardevbase.ko 

depmod modprobe chardevbase.ko 
rmmod chardevbase

 

Une fois le module de pilote chargé, vous pouvez utiliser lsmod pour le vérifier.

lsmode

Désinstallez le module à l'aide de la commande rmmod

3. Mise en œuvre spécifique de l'enregistrement et de l'annulation des dispositifs de caractères

Le chargement et le déchargement du module de pilote enregistrent et désenregistrent en fait le périphérique de caractères avec le système.

1, nous avons besoin de charger la fonction du module chardevbase_init , utilisez la fonction register_chrdev enregistrer un dispositif de caractère au système, désinstaller le pilote lorsque le besoin d'annuler le caractère devant un appareil enregistré, utilisez la fonction unregister_chrdev dans chardevbase_exit annulation du dispositif de caractères

2. Le noyau Linux divise le numéro de périphérique en deux parties: le numéro de périphérique principal et le numéro de périphérique mineur. Le numéro de périphérique principal occupe les 12 premiers chiffres et le numéro de périphérique mineur occupe les 20 chiffres inférieurs. Fonction d'opération ou macro du numéro d'appareil:

从dev_t获取主设备号和次设备号:MAJOR(dev_t),MINOR(dev_t)
使用主设备号和次设备号构成dev_t:MKDEV(major,minor)

Si vous utilisez des numéros de périphérique attribués statiquement, vous devez vérifier quels numéros de périphérique sont utilisés par le système actuel lors de la configuration, pour éviter les conflits, utilisez la commande: 

cat /proc/devices

3. Ajouter des informations sur la LICENCE et l'auteur

/*
    模块输入与输出
 */
static int __init chardevbase_init(void)
{
    int ret = 0;
    printk("chardevbase_init\r\n");

    /*注册字符设备*/
    ret = register_chrdev(CHARDEVBASE_MAJOR, CHARDEVBASE_NAME, &chardevbase_fops);
    if (ret < 0){
        printk("chardevbase init failed!\r\n");
    }
    return 0;
}

static void __exit chardevbase_exit(void)
{
    printk("chardevbase_exit\r\n");

    /*卸载字符设备*/
    unregister_chrdev(CHARDEVBASE_MAJOR, CHARDEVBASE_NAME);
}

module_init(chardevbase_init); /*入口*/
module_exit(chardevbase_exit); /*出口*/

MODULE_AUTHOR("denghengli");
MODULE_LICENSE("GPL");

4. Réalisez la fonction de fonctionnement spécifique de l'appareil

Après avoir enregistré le périphérique de caractères avec le système, vous devez ajouter vous-même les opérations de fichier liées au périphérique .

/*
 字符设备操作集合
*/
static struct file_operations chardevbase_fops = {
    .owner = THIS_MODULE,
    .open = chardevbase_open,
    .release = chardevbase_release,
    .read = chardevbase_read,
    .write = chardevbase_write,
};

 

Troisièmement, testez l'écriture et le test de l'application

Lors de l'écriture d'un pilote, vous pouvez utiliser le manuel man fourni avec Linux pour afficher l'utilisation de la fonction. La méthode d'utilisation est man [section] [commande], comme man 1 ls

1、Standard commands (标准命令)
2、System calls (系统调用)
3、Library functions (库函数)
4、Special devices (设备说明)
5、File formats (文件格式)
6、Games and toys (游戏和娱乐)
7、Miscellaneous (杂项)
8、Administrative Commands (管理员命令)
9 其他(Linux特定的), 用来存放内核例

1. Écrivez le programme de test d'application chardevbaseAPP.c, compilez-le dans un fichier exécutable chardevbaseAPP et copiez-le dans rootfs / lib / modules / 4.1.15 /

arm-linux-gnueabihf-gcc chardevbaseAPP.c -o chardevbaseAPP 
sudo cp chardevbaseAPP /home/denghengli/linux/nfs/rootfs/lib/modules/4.1.15/ -f

2. Chargez le module de pilote et vérifiez le numéro de périphérique du pilote chardevbase

modprobe chardevbase.ko 
cat /proc/devices

3. Créez un fichier de nœud de périphérique

Pour charger correctement le pilote, vous devez créer un fichier de nœud de périphérique correspondant dans le répertoire / dev. Le programme d'application termine l'opération du périphérique spécifique en exécutant le fichier de nœud de périphérique. Après avoir chargé le module du pilote, il sera automatiquement créé dans / dev, mais il n'a pas encore été enregistré, donc commencez par en enregistrer un manuellement. Si chardevbaseAPP veut lire et écrire le périphérique chardevbase, lire et écrire directement sur / dev / chardevbase. Le fichier équivalent à / dev / chardevbase est la réalisation du périphérique chardevbase dans l'espace utilisateur.

/*其中“ mknod”是创建节点命令 ,“/dev/chardevbase”是要创建的节点文件 
*c表示这是个字符设备,200是设备的主设备号 0”是设备的次设备号。
*/

mknod /dev/chardevbase c 200 0

4. Exécutez le programme de test

./chardevbaseAPP /dev/chardevbase

 

 

 

 

Je suppose que tu aimes

Origine blog.csdn.net/m0_37845735/article/details/106892621
conseillé
Classement