一. 简介
本文继上一篇文章的学习,前面几篇文章对字符设备驱动进行了简单的了解。文章地址如下:
字符设备驱动开发基础-CSDN博客
本文学习字符设备驱动的开发,主要学习字符设备驱动模块的加载与卸载。
二. 编写字符设备驱动框架
1. Linux驱动的运行方式
选择驱动运行方式
2. 驱动的加载与卸载
module_init(xxx_init); //注册模块加载函数
module_exit(xxx_exit); //注册模块卸载函数
3. 编写字符设备驱动框架
(1) 在 ubuntu系统下,创建一个存放驱动代码工程的目录,我这里在自己之前创建的正点原子文件目录下创建:
用 vscode软件打开 上面创建的工程目录 1_chrdevbase。通过 vscode在 目录 1_chrdevbase下创建一个 .c文件,命名为 chrdevbase.c,如下所示:
(2) 使用 vscode软件再打开 Linux内核源码,这里使用之前我更改的 NXP官方的 Linux内核源码。
Linux内核源码一般都会有使用到 驱动模块加载与卸载注册函数的。
在 Linux内核源码工程中,搜索 module_init() 函数与 module_eixt() 函数:
可以看到,Linux内核源码中,很多地方有调用到 module_init() 函数。当然也会调用到 module_exit()函数。
可以打开一个调用 module_init()函数的 .c文件,模仿 如何调用 module_init()函数。这里打开 aes_glue.c 文件,aes_glue.c文件中涉及 module_init()与 module_exit()函数的代码:
.......................................
static int __init aes_init(void)
{
return crypto_register_alg(&aes_alg);
}
static void __exit aes_fini(void)
{
crypto_unregister_alg(&aes_alg);
}
module_init(aes_init);
module_exit(aes_fini);
.......................................
模仿上面驱动模块的加载与卸载函数,编写 我的 chrdevbase.c 文件,再根据 上面 aes_glue.c中头文件添加相应的头文件,chrdevbase.c 文件的代码如下:
#include <linux/module.h>
/*
* 驱动模块入口函数
*/
static int __init chrdevbase_init(void)
{
return 0;
}
/*
* 驱动模块出口函数
*/
static void __exit chrdevbase_exit(void)
{
;
}
/*
* 驱动模块的入口与出口函数
*/
module_init(chrdevbase_init); /* 入口 */
module_exit(chrdevbase_exit); /* 出口 */
(3) 设置vscode软件中 1_chrdevbase工程的 头文件路径。具体设置 Linux内核源码路径。
不设置的话,vscode可能会提示一些错误,一些函数也找不到函数定义。
将正点原子提供的 Linux驱动例程中,01_chrdevbase工程代码中 .vscode文件及其下的文件都拷贝到 现在的 工程下。我这里没有安装 FTP客户端,所以,没办法拷贝文件夹。所以,可以在我1_chrdevbase工程下首先创建 .vscode目录,再在 .vscode目录下分别创建文件,将正点原子提供的 01_chrdevbase工程代码中 .vscode目录下文件的内容分别拷贝到相应文件。
.vscode目录下,创建如下两个文件:
编写驱动的时候注意事项:
(1) 编译驱动时需要用到 Linux内核源码!因此,需要解压缩 Linux内核源码。因为驱动代码中可能会调用到Linux内核源码中的一些函数。
同时,还需要编译linux内核源码,得到zImage和 .dtb设备树文件。需要使用编译后得到的zImage和 .dtb设备树文件来启动系统。
使用的Linux内核源码包:
这里使用正点原子第三期我编译的 Linux内核源码,也就是 在 NXP官方提供的 Linux内核源码更改后的 Linux内核源码包。
我这里的 Linux内核源码所在路径为:
/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga
更改 .vscode目录下 c_cpp_propertities.json文件下的 Linux源码路径:
{
"configurations": [
{
"name": "Linux",
"includePath": [
"${workspaceFolder}/**",
"/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/include",
"/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include",
"/home/wangtian/zhengdian_Linux/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga/arch/arm/include/generated/"
],
"defines": [],
"compilerPath": "/usr/bin/clang",
"cStandard": "c11",
"cppStandard": "c++17",
"intelliSenseMode": "clang-x64"
}
],
"version": 4
}
下一篇文章学习对工程进行编译,并加载与卸载字符驱动模块。