前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >开发板的第 1 个驱动程序

开发板的第 1 个驱动程序

作者头像
韦东山
发布2020-09-30 11:32:44
1.6K0
发布2020-09-30 11:32:44
举报
文章被收录于专栏:韦东山嵌入式韦东山嵌入式

9.1 前提

请按前面第七章使用 GIT 下载源码、使用 repo 下载工具链,并配置了交叉编译工具链。

为什么编译驱动程序之前要先编译内核?

① 驱动程序要用到内核文件: 比如驱动程序中这样包含头文件:#include <asm/io.h>,其中的 asm 是一个链接文件,指向 asm-arm或 asm-mips,这需要先配置、编译内核才会生成 asm 这个链接文件。

② 编译驱动时用的内核、开发板上运行到内核,要一致: 开发板上运行到内核是出厂时烧录的,你编译驱动时用到内核是你自己编译的,这两个内核不一致时会导致一些问题。

所以我们编译驱动程序前,要把自己编译出来到内核放到板子上去,替代原来的内核。

③ 更换板子上的内核后,板子上的其他驱动也要更换: 板子使用新编译出来的内核时,板子上原来的其他驱动也要更换为新编译出来的。

所以在编译我们自己的第 1 个驱动程序之前,要先编译内核、模块,并且放到板子上去。

9.2 编译内核

9.2.1 STM32MP157 开发板

内核的编译过程如下(编译内核前需要先配置好工具链等一些环境变量):

代码语言:javascript
复制
book@100ask:~/100ask_stm32mp157_pro-sdk$ cd Linux-5.4
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make 100ask_stm32mp157_pro_defconfig
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make uImage LOADADDR=0xC2000040 -j4
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make dtbs
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ cp arch/arm/boot/uImage ~/nfs_rootfs
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ cp arch/arm/boot/dts/stm32mp157c-100ask-512d-lcd-v1.dtb ~/nfs_rootfs

9.2.2 IMX6ULL 开发板

不同的开发板对应不同的配置文件,配置文件位于内核源码arch/arm/configs/目录。

1. IMX6ULL 全功能版 内核的编译过程如下(编译内核前需要先配置好工具链等一些环境变量):

代码语言:javascript
复制
book@100ask:~/100ask_imx6ull-sdk$ cd Linux-4.9.88
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make mrproper
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make 100ask_imx6ull_defconfig
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make zImage -j4
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make dtbs
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ cp arch/arm/boot/zImage ~/nfs_rootfs
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ cp arch/arm/boot/dts/100ask_imx6ull-14x14.dtb ~/nfs_rootfs

编译步骤参考如下,编译好zImage后再去编译设备树文件。

在这里插入图片描述
在这里插入图片描述

编译完成后生成的文件如下图所示

在这里插入图片描述
在这里插入图片描述

编译完成后,在arch/arm/boot目录下生成zImage内核文件, 在arch/arm/boot/dts目录下生成设备树的二进制文件100ask_imx6ull-14x14.dtb。

把这2个文件复制到/home/book/nfs_rootfs目录下备用,如下图:

在这里插入图片描述
在这里插入图片描述

2. IMX6ULL mini nand 版 kernel的编译过程如下(编译内核前需要先配置好工具链等一些环境变量):

代码语言:javascript
复制
book@100ask:~/100ask_myir_mini_imx6ull-sdk$ cd Linux-4.9.88
book@100ask:~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88$ make mrproper
book@100ask:~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88$ make 100ask_myir_imx6ull_mini_defconfig
book@100ask:~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88$ make zImage -jN //N 表示根据 CPU 个数,来加速编译系统
book@100ask:~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88$ make dtbs
book@100ask:~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88$ cp arch/arm/boot/zImage ~/nfs_rootfs
book@100ask:~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88$ cp arch/arm/boot/dts/100ask_myir_imx6ull_mini.dtb ~/nfs_rootfs

编 译 成 功 后 , 可 以 得 到 这 些 文 件 : 内 核 文 件 arch/arm/boot/zImage , 设 备 树 文 件arch/arm/boot/100ask_myir_imx6ull_mini.dtb。

把这2个文件复制到/home/book/nfs_rootfs目录下备用。

9.2.3 其他开发板

使用 GTI 下载源码后,在以下目录有其他开发板的使用手册,请自行参考对应手册:

在这里插入图片描述
在这里插入图片描述

9.3 编译内核模块

9.3.1 STM32MP157 开发板

进入内核源码目录后,就可以编译内核模块了:

代码语言:javascript
复制
book@100ask:~$ cd 100ask_stm32mp157_pro-sdk/Linux-5.4
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ make modules -j4
book@100ask:~/100ask_stm32mp157_pro-sdk/Linux-5.4$ sudo make INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install

最后一条命令是把模块安装到 /home/book/nfs_rootfs 目 录 下 备 用 , 会 得 到/home/book/nfs_rootfs/lib/modules目录。

9.3.2 IMX6ULL 开发板

无论是哪个版本的IMX6ULL开发板,编译内核模块的命令是一样的。

1. IMX6ULL 全功能版 进入内核源码目录后,就可以编译内核模块了:

代码语言:javascript
复制
book@book-virtual-machine:~$ cd ~/100ask_imx6ull-sdk/Linux-4.9.88/
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ sudo make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install

最后一条命令是把模块安装到 /home/book/nfs_rootfs 目 录 下 备 用 , 会 得 到/home/book/nfs_rootfs/lib/modules目录。

在这里插入图片描述
在这里插入图片描述

内核模块编译完成后截图示例

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

安装模块后的/home/book/nfs_rootfs/目录结构如下图所示。

注意:下图用到tree命令,如果提示没有该命令,需要执行“sudo apt install tree”命令安装tree工具(前提是Ubuntu能上网)。

在这里插入图片描述
在这里插入图片描述

2. IMX6ULL mini nand 版 进入内核源码目录后,就可以编译内核模块了:

代码语言:javascript
复制
book@book-virtual-machine:~$ cd ~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88
book@100ask:~/100ask_myir_mini_imx6ull-sdk/Linux-4.9.88$ make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- modules
book@100ask:~/100ask_imx6ull-sdk/Linux-4.9.88$ sudo make ARCH=arm INSTALL_MOD_PATH=/home/book/nfs_rootfs modules_install

编译过程请参考上面IMX6ULL全功能版的截图,最后一条命令是把模块安装到/home/book/nfs_rootfs目录下备用,会得到/home/book/nfs_rootfs/lib/modules目录。

9.3.3 其他开发板

使用 GTI 下载源码后,在以下目录有其他开发板的使用手册,请自行参考对应手册:

在这里插入图片描述
在这里插入图片描述

9.4 安装内核和模块到开发板上

假设:执行上述命令后,在Ubuntu的/home/book/nfs_rootfs目录下已经有了zImage或uImage、dtb文件,并且有lib/modules子目录(里面含有各种模块)。

下面,要把这些文件复制到开发板上。

如果你使用的是VMware NAT方式,假设Windows IP为192.168.1.100,在开发板启动进入Linux后,输入root登录,然后执行以下命令(注意:必须指定port为2049、mountport为9999):

代码语言:javascript
复制
mount -t nfs -o nolock,vers=3,port=2049,mountport=9999 192.168.1.100:/home/book/nfs_rootfs /mnt
cp /mnt/zImage /boot 或 cp /mnt/uImage /boot 
cp /mnt/*.dtb /boot
cp /mnt/lib/modules /lib -rfd
sync
reboot

如果你使用的是VMware桥接方式,假设Ubuntu IP为192.168.1.100,在开发板上执行以下命令:

代码语言:javascript
复制
mount -t nfs -o nolock,vers=3 192.168.1.100:/home/book/nfs_rootfs /mnt
cp /mnt/zImage /boot 或 cp /mnt/uImage /boot 
cp /mnt/*.dtb /boot
cp /mnt/lib/modules /lib -rfd
sync
reboot

最后重启开发板,它就使用新的zImage或uImage、dtb、模块了。

9.5 体验第 1 个驱动程序

9.5.1 修改 Makefile 指定内核目录

把第 1 个驱动程序 01_hello_drv 上传到 Ubuntu 后,修改它的 Makefile,设置其中的 KERN_DIR 变量为内核的源码目录,以 IMX6ULL 为例,如下:

代码语言:javascript
复制
KERN_DIR = /home/book/100ask_imx6ull-sdk/Linux-4.9.88

9.5.2 编译

设置好工具链、配置、编译过内核之后,在01_hello_drv目录下执行make命令即可编译驱动程序及测试程序,如下 :

在这里插入图片描述
在这里插入图片描述

9.5.3 在开发板上运行

开发板启动后通过 nfs 挂载 Ubuntu 目录的方式,将相应的文件拷贝到开发板上。如果你使用的是VMware NAT方式,假设Windows IP为192.168.1.100,在开发板上执行以下命令(注意: 必须指定port为2049、mountport为9999):

代码语言:javascript
复制
[root@board:~]# mount -t nfs -o nolock,vers=3,port=2049,mountport=9999 192.168.1.100:/home/book/nfs_rootfs /mnt

如果你使用的是VMware桥接方式,假设Ubuntu IP为192.168.1.100,在开发板上执行以下命令:

代码语言:javascript
复制
[root@board:~]# mount -t nfs -o nolock,vers=3 192.168.1.100:/home/book/nfs_rootfs /mnt

挂载 NFS 成功后,把驱动和测试程序复制到开发板上:

代码语言:javascript
复制
[root@board:~]# cp /mnt/hello_drv.ko ./
[root@board:~]# cp /mnt/hello_drv_test ./

然后安装驱动程序并验证是否成功:

代码语言:javascript
复制
[root@board:~]# insmod hello_drv.ko

执行“lsmod”可以看到hello_drv驱动,如下:

在这里插入图片描述
在这里插入图片描述

执行“cat /proc/devices”:

在这里插入图片描述
在这里插入图片描述

执行“ls -l /dev/hello”,可以发现有这个设备节点,并且它的主设备号跟上图一样:

在这里插入图片描述
在这里插入图片描述

最后执行测试程序:

代码语言:javascript
复制
./hello_drv_test -w www.100ask.net
./hello_drv_test -r
在这里插入图片描述
在这里插入图片描述

如果不想看到驱动调试信息,可以先执行以下命令用来关闭内核的打印信息:

代码语言:javascript
复制
echo "1 4 1 7" > /proc/sys/kernel/printk
在这里插入图片描述
在这里插入图片描述

9.6 常见问题

安装驱动程序时,如果有以下提示信息,原因就是板子上运行的内核太老了,解决方法就是先编译内核、 替换板能上的内核,再重新编译、安装驱动程序:

代码语言:javascript
复制
disagrees about version of symbol device_create
[ 2098.200219] hello_drv: Unknown symbol device_create (err -22)
[ 2098.208445] hello_drv: disagrees about version of symbol device_destroy
[ 2098.215871] hello_drv: Unknown symbol device_destroy (err -22)
insmod: ERROR: could not insert module hello_drv.ko: Invalid parameters
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-09-27 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 9.1 前提
  • 9.2 编译内核
    • 9.2.1 STM32MP157 开发板
      • 9.2.2 IMX6ULL 开发板
        • 9.2.3 其他开发板
        • 9.3 编译内核模块
          • 9.3.1 STM32MP157 开发板
            • 9.3.2 IMX6ULL 开发板
            • 9.3.3 其他开发板
            • 9.4 安装内核和模块到开发板上
            • 9.5 体验第 1 个驱动程序
              • 9.5.1 修改 Makefile 指定内核目录
                • 9.5.2 编译
                  • 9.5.3 在开发板上运行
                  • 9.6 常见问题
                  领券
                  问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档