zynq 驱动编译
学习《领航者ZYNQ之嵌入式linux开发指南》
有三种编译方式
- 利用linux内核源码进行模块编译
- 静态编译,使驱动编译进linux内核镜像中
- 利用petalinux工具进行模块编译,最终编译好的模块存放在根文件系统中
模块编译
-
编写设备驱动c文件 chrdevbase.c
#include <linux/types.h> #include <linux/kernel.h> #include <linux/delay.h> #include <linux/ide.h> #include <linux/init.h> #include <linux/module.h> #define CHRDEVBASE_MAJOR 200 // 主设备号 #define CHRDEVBASE_NAME "chrdevbase" //设备名字 static char readbuf[100]; static char writebuf[100]; static char kerneldata[]={"kernel data!"}; static int chrdevbase_open(struct inode* inode,struct file* filp) { printk("chrdevbase open!\r\n"); return 0; } static ssize_t chrdevbase_read(struct file* filp,char __user *buf,size_t cnt,loff_t* offt) { int retvalue=0; printk("chrdevbase read\r\n"); memcpy(readbuf,kerneldata,sizeof(kerneldata)); retvalue=copy_to_user(buf,readbuf,cnt); if(retvalue==0) { printk("kernel send data ok!\r\n"); } else { printk("kernel send data failed\e\n"); } return 0; } static ssize_t chrdevbase_write(struct file* filp,const char __user *buf,size_t cnt,loff_t* offt) { int retvalue=0; printk("chrdevbase write\r\n"); retvalue=copy_from_user(writebuf,buf,cnt); if(retvalue==0) { printk("kernel recv data:%s\r\n",writebuf); } else { printk("kernel recv data failed\r\n"); } return 0; } static int chrdevbase_release(struct inode* inode,struct file* filp) { printk("chrdevbase release\r\n"); return 0; } static struct file_operations chrdevbase_fops={ .owner=THIS_MODULE, .open=chrdevbase_open, .read=chrdevbase_read, .write=chrdevbase_write, .release=chrdevbase_release, }; static int __init chrdevbase_init(void) { int retvalue=0; printk("chrdevbase character device init\r\n"); retvalue=register_chrdev(CHRDEVBASE_MAJOR,CHRDEVBASE_NAME,&chrdevbase_fops); if(retvalue<0) { printk("chrdevbase driver register failed\r\n"); } return 0; } static void __exit chrdevbase_exit(void) { printk("chrdevbase_exit\r\n"); unregister_chrdev(CHRDEVBASE_MAJOR,CHRDEVBASE_NAME); } module_init(chrdevbase_init); module_exit(chrdevbase_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("alientek");
-
编写驱动编译的makefile文件
#!/bin/bash obj-m += chrdevbase.o KDIR :=/home/xilinx/linux-xlnx-xilinx-v2018.3 PWD ?= $(shell pwd) all: make -C $(KDIR) M=$(PWD) ARCH=arm CROSS_COMPILE=/home/cross_compiler/gcc-arm-linux-gnueabi/bin/arm-linux-gnueabihf- modules clean: rm -rf *.o *.mod.c *.cmd .*.cmd *.order *.symvers .tmp_versions dtclean: rm -rf *.o *.mod.c *.cmd .*.cmd *.order *.symvers .tmp_versions *.ko
-
执行编译
make #就可以得到chrdevbase.ko驱动模块
-
启动linux后就可以用insmod和rmmod去加载和卸载驱动模块
静态编译
-
编写驱动c文件chrdevbase.c 内容与上述一致
-
将驱动c文件chrdevbase.c拷贝到linux内核源码的drivers/char目录下,该目录是存放linux字符设备驱动相关驱动代码
-
修改drivers/char/Makefile 添加chrdevbase驱动
-
修改drivers/char/Kconfig文件,添加chrdevbase设备
-
执行make menuconfig 查看设备是否被勾选
-
执行linux内核编译
-
至此chrdevbase驱动设备已静态编译进linux内核中
petalinux编译
-
启动petalinux工具,进入到petalinux工程里面
-
执行petalinux-create -t modules --name chrdevbase --enable 命令, 创建一个内核模块,工具会自动在petalinux-project/project-spec/meta-user/recipes-modules下创建chrdevbase设备module
-
在petalinux-project/project-spec/meta-user/recipes-modules/chrdevbase/files目录替换为已编写好的chrdevbase.c文件
-
执行petalinux-config -c rootfs,在modules里面查看是否加载成功
-
执行petalinux-build 进行编译
-
编译成功后,至此chrdevbase设备驱动模块文件chrdevbase.ko已存在**/lib/modules/4.14.0-xilinx-v2018.3/extra**目录下,可以用insmod和rmmod来加载和卸载驱动模块