irpas技术客

Linux字符驱动开发__创建字符设备驱动_嵌入式DZC_创建字符设备驱动

网络投稿 2618

环境:ubuntu20.04、source insight4.0、secure CRT

内核版本:Linux-3.14-fs4412

开发板:fs4412(ARM)

一、环境安装步骤

1.将内核拷贝到虚拟机tftpboot目录下(目的使用tftp挂载到开发板上,见前章)

2.配置环境变量,使用CRT终端操作

注:第一次使用要用网线,并关闭网络托管

sudo? /etc/init.d/network-manager stop

set ipaddr 192.168.3.202 set serverip 192.168.3.163 set gatewayip 192.168.3.1//网关 set netmask 255.255.255.0 save

3.烧录uImage

?? ?tftp ?41000000 uImage ?? ?movi write kernel ?41000000

4.烧录设备树(298f1f注意最后一个参数表示ramdisk实际大小,每个人都可能不一样)

tftp 41000000 exynos4412-fs4412.dtb movi write dtb 41000000

5.开机执行

set bootcmd movi read kernel 41000000\;movi read dtb 42000000\;movi read rootfs 43000000 298f1f\;bootm 41000000 43000000 42000000 ##注意,最后一个表示ramdisk实际大小 set bootargs root=/dev/ram0 rw console=ttySAC2,115200 init=/linuxrc save 二、创建字符设备驱动

????1.向内核申请一个设备号 ?? ?2.创建一个字符设备驱动对象 ?? ?3.创建一个字符设备文件节点,让用户访问到

chrdev.c部分 #include <linux/kernel.h> #include <linux/module.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/device.h> /* 如何编写一个字符设备驱动程序 1.向内核申请一个 设备号 2.创建一个字符设备驱动对象 [ 属性:devno 方法: open r w close ] 3.创建一个字符设备文件节点--和驱动对象有相同的devno,让用户访问到 1)创建一个类, 2)在类下创建一个文件节点,会反馈到/dev/xxxx */ struct class *cls; struct cdev cdev_obj; //字符设备驱动的对象 int chdev_open(struct inode *inode, struct file *file) { printk("%s->%d\n",__func__,__LINE__); return 0; } int chdev_close (struct inode *inode, struct file *file) { printk("%s->%d\n",__func__,__LINE__); return 0; } struct file_operations chdev_ops = { .open = chdev_open, .release = chdev_close, }; int modx_init(void) { int ret; int major,minor; dev_t devno; /*1.向内核申请一个 设备号 int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char * name) dev_t *dev,保存设备号的第一个 地址, baseminor: 你的设备号的 次设备号从哪里开始0~ 2^20-1 count: 你要申请多少个啊,连续的 name,调试用的, /proc 返回值: linux返回约定, 负值表示失败 0/正值 成功 */ ret = alloc_chrdev_region(&devno,0, 1, "my char dev"); if(ret < 0 ){ printk("%s->%d alloc_chrdev_region err\n",__func__,__LINE__); return -23 ; } major = MAJOR(devno); //devno>>20; minor = MINOR(devno); //devno<<12>>12; devno = MKDEV(major,minor); //major<<20 | minor; printk("%s->%d major=%d minor=%d devno=%d\n",\ __func__,__LINE__,major,minor,devno); /* 2.创建一个字符设备驱动对象 [ 属性:devno 方法: open r w close ] struct cdev { const struct file_operations *ops; 方法的集合 dev_t dev; 设备号 }; void cdev_init(struct cdev * cdev, const struct file_operations * fops) cdev,字符设备驱动对象本身 fops,给object指定的方法集合 int cdev_add(struct cdev p[], dev_t dev, unsigned count) p,字符设备驱动对象本身 dev: 设备号 count: 你要添加多少个驱动到内核/os 返回值: 0-成功 负值 失败 */ cdev_init(&cdev_obj, &chdev_ops); ret = cdev_add(&cdev_obj, devno, 1); if(ret < 0 ){ printk("%s->%d cdev_add err\n",__func__,__LINE__); return -24 ; } /* 3.创建一个字符设备文件节点--和驱动对象有相同的devno,让用户访问到 1)创建一个类, struct class * class_create(owner, name) owner: THIS_MODULE,它是一个指向当前模块的指针 name: 类名, /sys/class/xxxx 2)在类下创建一个文件节点,会反馈到/dev/xxxx device_create(struct class * class, struct device * parent, dev_t devt, void * drvdata, const char * fmt, ...) class: 要在该类下创建节点 parent: null devt:设备号 drvdata:null const char * fmt, ... : printf("chdev %d %c %s %x", 34,'a',"xxxx",0x999) */ cls = class_create(THIS_MODULE, "chdev class"); if(!cls){ printk("%s->%d class_create err\n",__func__,__LINE__); return -26 ; } /*在 /dev目录下创建一个 设备文件节点 /dev/chdev0 */ device_create(cls,NULL, devno,NULL, "chdev%d",0); printk("%s->%d\n",__func__,__LINE__); return 0; } void mod_exit(void) { printk("%s->%d\n",__func__,__LINE__); } module_init( modx_init ); module_exit(mod_exit); MODULE_LICENSE("GPL"); /*告诉内核你是良民,愿意公布你的源码*/ apptest.c部分 #include <stdio.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <unistd.h> int main() { int fd = open("/dev/chdev0",O_RDWR); if(fd < 0 ){ perror("open err"); return 0; } close(fd); return 0; }

Makefile部分

KERNEL_PATH = /home/dzc/tftpboot/linux-3.14-fs4412 ### kernel source must be compiled obj-m += chrdev.o ## indicate module.c will be compiled as module file all: make modules -C $(KERNEL_PATH) M=$(shell pwd) ARCH=arm CROSS_COMPILE=arm-none-linux-gnueabi- clean: rm *.o *.ko *.out *.mod.c *.order Module.symvers -rf ### make modules 表示编译东西为模块 # -C 后面跟上内核路径 # M:跟上当前模块所在的位置 ubuntu操作 make clean make //编译 arm-none-linux-gnueabi-gcc apptest.c -o apptest.out CRT终端操作 lrz //加载.ko和.out文件 insmod chrdev.ko//安装模块 chmod 777 apptest.out ./apptest.out//启动模块 mkdir /lib/modules/3.14.0 -p remmod chrdev


1.本站遵循行业规范,任何转载的稿件都会明确标注作者和来源;2.本站的原创文章,会注明原创字样,如未注明都非原创,如有侵权请联系删除!;3.作者投稿可能会经我们编辑修改或补充;4.本站不提供任何储存功能只提供收集或者投稿人的网盘链接。

标签: #创建字符设备驱动 #insight40secure #stopset #ipaddr #1921683202set