IMX6学习记录(11)-字符驱动

上面是我的微信和QQ群,欢迎新朋友的加入。

1.测试驱动程序

#include <linux/init.h>
#include <linux/module.h>

static int hello_init(void)
{
    printk(KERN_ALERT "Hello, world\n");
    return 0;
}
static void hello_exit(void)
{
    printk(KERN_ALERT "Goodbye, cruel world\n");
}
module_init(hello_init);
module_exit(hello_exit);

MODULE_LICENSE("GPL");
MODULE_AUTHOR("jun");

就是个简单的helloworld

2.makefile

obj-m := char_test.o

KERNEL_SRC := /home/jun/i.mx6/source/linux-imx-rel_imx_4.1.15_2.1.0_ga
SRC := $(shell pwd)

all:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC)

modules_install:
	$(MAKE) -C $(KERNEL_SRC) M=$(SRC) modules_install

clean:
	rm -f *.o *~ core .depend .*.cmd *.ko *.mod.c
	rm -f Module.markers Module.symvers modules.order
	rm -rf .tmp_versions Modules.symvers

执行编译:make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j8

3.驱动测试

将驱动传到开发板上

测试驱动

4.完善字符驱动

#include <linux/init.h>
#include <linux/module.h>
#include <linux/fs.h>
#include <linux/cdev.h>
#include <linux/device.h>

static int major = 232; /* 静态设备号方式的默认值 */
static int minor = 0; /* 静态设备号方式的默认值 */

module_param(major, int, S_IRUGO);
module_param(minor, int, S_IRUGO);

struct cdev *char_test; /* cdev 数据结构 */
static dev_t devno; /* 设备编号 */
static struct class *char_test_class;

#define DEVICE_NAME "char_test"

static int char_test_open(struct inode *inode, struct file *file )
{ 
	try_module_get(THIS_MODULE);
	printk(KERN_INFO DEVICE_NAME " opened!\n");
	return 0;
}

static int char_test_release(struct inode *inode, struct file *file )
{
	printk(KERN_INFO DEVICE_NAME " closed!\n");
	module_put(THIS_MODULE);
	return 0;
}

static ssize_t char_test_read(struct file *file, char *buf,size_t count, loff_t *f_pos)
{
	printk(KERN_INFO DEVICE_NAME " read method!\n");
	return count;
}

static ssize_t char_test_write(struct file *file, const char *buf, size_t count, loff_t *f_pos)
{
	printk(KERN_INFO DEVICE_NAME " write method!\n");
	return count;
}

//static int char_test_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
static long char_test_ioctl(struct file *f, unsigned int cmd, unsigned long arg)
{
	printk(KERN_INFO DEVICE_NAME " ioctl method!\n");
	return 0;
}

struct file_operations char_test_fops = {
.owner = THIS_MODULE,
.read = char_test_read,
.write = char_test_write,
.open = char_test_open,
.release = char_test_release,
.unlocked_ioctl = char_test_ioctl
};

static int __init char_test_init(void)
{
	int ret;

	if (major > 0) { /* 静态设备号 */
		devno = MKDEV(major, minor);
		ret = register_chrdev_region(devno, 1, "char_test");
        printk(KERN_ALERT " 静态设备号:%d!\n",major);
	} else { /* 动态设备号 */
		ret = alloc_chrdev_region(&devno, minor, 1, "char_test"); /* 从系统获取主设备号 */
		major = MAJOR(devno);
        printk(KERN_ALERT " 动态设备号:%d!\n",major);
	}

	if (ret < 0) {
		printk(KERN_ERR "cannot get major %d \n", major); 
		return -1;
	}

	char_test = cdev_alloc(); /* 分配 char_test 结构 */
	if (char_test != NULL) { 
		cdev_init(char_test, &char_test_fops); /* 初始化 char_test 结构 */
		char_test->owner = THIS_MODULE;
		if (cdev_add(char_test, devno, 1) != 0) { /* 增加 char_test 到系统中 */
			printk(KERN_ERR "add cdev error!\n");
			goto error;
		}
	} else {
		printk(KERN_ERR "cdev_alloc error!\n"); 
		return -1;
	}

	char_test_class = class_create(THIS_MODULE, "char_test_class");
	if (IS_ERR(char_test_class)) { 
		printk(KERN_INFO "create class error\n");
		return -1;
	}

	//device_create(char_test_class, NULL, devno, NULL, "char_test" "%d", MINOR(devno));
	device_create(char_test_class, NULL, devno, NULL, "char_test", NULL);
    printk(KERN_ALERT "mod init!\n"); 
	return 0;

	error:
	unregister_chrdev_region(devno, 1); /* 释放已经获得的设备号 */
	return ret;

}

static void __exit char_test_exit(void)
{
	cdev_del(char_test); /* 移除字符设备 */
	unregister_chrdev_region(devno, 1); /* 释放设备号 */
	device_destroy(char_test_class, devno);
	class_destroy(char_test_class);
}

module_init(char_test_init);
module_exit(char_test_exit);
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jun,2839084093@qq.com");

5.编译测试

6.写应用APP

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <errno.h>
#include <fcntl.h>

#define DEV_NAME "/dev/char_test"

int main(int argc, char *argv[])
{
	int i;
	int fd = 0;
	int dat = 0;
	fd = open (DEV_NAME, O_RDWR);
	if (fd < 0) {
		perror("Open "DEV_NAME" Failed!\n"); 
		exit(1);
	}

	i = read(fd, &dat, 1);
	if (!i) {
		perror("read "DEV_NAME" Failed!\n");
		exit(1);
	}

	dat = 0;
	i = write(fd, &dat, 1);
	if (!i) {
	perror("write "DEV_NAME" Failed!\n");
	exit(1);
	}

	close(fd);
	return 0;
}

编译程序

arm-linux-gnueabihf-gcc char_app.c -o char_app

传到设备上,运行

找不到驱动

查找/dev下面,确实没有这个驱动

检查一下当前系统加载的驱动

cat /proc/devices

在字符驱动里面是存在的,248是我调试的时候分配了动态设备号

看来是没有设备节点

mknod /dev/char_test c 248 0
cd /mnt
./char_app

正常了

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值