(五)驱动测试

由于NanoPi Fire3使用的是linux 4.4的内核版本,所以不知道以前的linux 2.6版本的驱动程序能否兼容,所以这一章来说明linux2.6版本与4.4版本的驱动程序的区别。

这一章用到的内核源码和交叉编译工具链可以在NanoPi Fire3的wiki第7节中找到

http://wiki.friendlyarm.com/wiki/index.php/NanoPi_Fire3/zh#.E7.BC.96.E8.AF.91Linux_kernel_4.4.y


首先,我使用以前2.6版本所写的最简单的驱动程序来进行试验

#include <linux/module.h>
#include <linux/kernel.h>
#include <linux/fs.h>
#include <linux/init.h>
#include <linux/delay.h>
#include <asm/uaccess.h>
#include <asm/irq.h>
#include <asm/io.h>


int major; //主设备号

static struct class *hellodrv_class;
static struct class_device	*hellodrv_class_dev;

static int hello_drv_open(struct inode *inode, struct file *file)
{
	printk(KERN_EMERG "hello_drv_open\n");
	
	return 0;
}

static ssize_t hello_drv_read(struct file *fd, char __user *buf, size_t count, loff_t *ppos)
{
	printk(KERN_EMERG "hello_drv_read\n");

	return 0;
}

static ssize_t hello_drv_write(struct file *fd, const char __user *buf, size_t count, loff_t *ppos)
{
	printk(KERN_EMERG "hello_drv_write\n");

	return 0;
}

static struct file_operations hello_drv_fops = {
    .owner  =   THIS_MODULE,    /* 这是一个宏,推向编译模块时自动创建的__this_module变量 */
    .open   =   hello_drv_open,
    .read 	=   hello_drv_read,
    .write	=   hello_drv_write,
};

static int hello_drv_init(void)
{
	printk(KERN_EMERG "hello_drv_init...\n");

	major = register_chrdev(0, "hello_drv", &hello_drv_fops); //注册,告诉内核
	
	hellodrv_class = class_create(THIS_MODULE, "hellodrv");

	hellodrv_class_dev = class_device_create(hellodrv_class, NULL, MKDEV(major, 0), NULL, "hello_drv");
	

	return 0;
}

static void hello_drv_exit(void)
{
	printk(KERN_EMERG "hello_drv_exit...\n");

	unregister_chrdev(major, "hello_drv");
	
	class_device_unregister(hellodrv_class_dev);
	class_destroy(hellodrv_class);
}

module_init(hello_drv_init);
module_exit(hello_drv_exit);

MODULE_LICENSE("GPL");

MakeFile如下

KERN_DIR = /home/Linux_kernel/4.4.y/linux

all:
	make -C $(KERN_DIR) M=`pwd` modules 

clean:
	rm -rf *.o
	make -C $(KERN_DIR) M=`pwd` modules clean

obj-m	+= hello_driver.o

KERN_DIR根据实际源码所在文件目录位置进行修改

如果是第一次编译驱动,首先要把源码编译一遍才可以,否则会报错。

将驱动程序与Makefile放入ubuntu

然后执行make

aarch64-linux-gcc: error: unrecognized argument in option ‘-mcmodel=kernel’
aarch64-linux-gcc: note: valid arguments to ‘-mcmodel=’ are: large small tiny
aarch64-linux-gcc: error: unrecognized command line option ‘-mno-sse’; did you mean ‘-fno-ds’?
aarch64-linux-gcc: error: unrecognized command line option ‘-mno-mmx’
aarch64-linux-gcc: error: unrecognized command line option ‘-mno-sse2’; did you mean ‘-fno-dse’?
aarch64-linux-gcc: error: unrecognized command line option ‘-mno-3dnow’
aarch64-linux-gcc: error: unrecognized command line option ‘-m64’
aarch64-linux-gcc: error: unrecognized command line option ‘-mno-red-zone’; did you mean ‘-fno-regmove’?

很好,一堆错误。这时候不要急,看着错误信息一步一步查。

红框里的是错误的关键,仔细一看,居然用了x86架构下的Makefile,难怪这么多错误,我们写的是arm架构下的驱动。

那么在make的时候加入架构相关的信息

make ARCH=arm64

implicit declaration of function ‘class_create’ [-Werror=implicit-function-declaration]
implicit declaration of function ‘class_device_create’ [-Werror=implicit-function-declaration]

报错,原因是因为内核版本不一样导致的一些函数的名字不一样

增加头文件

#include <linux/device.h>

使用struct device代替struct class_device

使用device_create()代替class_device_create()

使用device_unregister()代替class_device_unregister()

再次编译试试

没有报错,生成了.ko文件,成功了

接下来写测试程序

#include <stdio.h>
#include <unistd.h>

#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>

int main(int argc, char **argv)
{
	int fd;
	int ret;
	char *file_name = "/dev/hello_drv";

	fd = open(file_name, O_RDWR|O_NOCTTY|O_NDELAY);
	if(fd < 0)
	{
		printf("can't open file %s\n", file_name);
		return -1;
	}

	close(fd);

	return 0;
}

交叉编译

aarch64-linux-gcc -o hello_test hello_test.c

将生成的驱动和测试程序拷贝到ARM板上进行测试

首先,安装驱动

insmod hello_driver.ko

lsmod查看

已经安装成功

查看设备号,这里使用的是自动分配设备号的方式

cat /proc/devices

查看是否生成设备节点

ls /dev/

启动测试程序,先添加可执行属性

chmod +x hello_test

./hello_test

执行完发现没有任何打印信息,但是我们在驱动中,在初始化、退出、打开文件的地方都有打印语句,这是为什么?

原来,我使用的是SSH远程登录,而printk所打印的内核信息只会通过控制台串口进行输出,也就是ttySAC0串口,并不会打印到远程端口,那么如何查看是否有打印信息呢?

第一种方法,在命令行输入

cat kmsg

可以看到最下面就是驱动打印的信息

第二种方法,在命令行输入

dmsg

在最后也可以看到驱动的打印信息

最简单的驱动程序测试成功!

万事开头难,接下来可以继续完善复杂的驱动了。

 

完整的源码放在github上,有需要可以自行下载。 代码名称为190518.zip

https://github.com/ljy980330/opencv_face_sys

 

有任何问题可以在下面给我留言!大家一起学习!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值