当前位置: 首页 > news >正文

建站软件大全最先进的深圳网站建设

建站软件大全,最先进的深圳网站建设,网站用的横幅广告怎么做,什么叫做网站整站一、新字符设备驱动原理 因为 register_chrdev 和 unregister_chrdev 两个函数是老版本驱动文件#xff0c;现在可以用新字符设备驱动 API 函数。 1. 分配和和释放设备号 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可#xff0c;但是这样会带来两…一、新字符设备驱动原理 因为  register_chrdev 和 unregister_chrdev 两个函数是老版本驱动文件现在可以用新字符设备驱动 API 函数。 1. 分配和和释放设备号 使用 register_chrdev 函数注册字符设备的时候只需要给定一个主设备号即可但是这样会带来两个问题  1、需要我们事先去确定哪些主设备号没有使用 2、会将主设备号下的所有次设备号都用掉。比如设置 LED 主设备号为 200那么 0~1048575 这个区间的次设备号全部都被 LED 一个设备分走了。一个 LED 设备肯定只能有一个主设备号一个次设备号。  解决这两个问题最好的方法就是在使用设备号的时候向 Linux 内核申请需要几个就申请几个如果没有指定设备号的话就使用如下函数来申请设备号  int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name) 如果给定了设备的主设备号和次设备号就使用如下所示函数来注册设备号即可  /** param - from : 要申请的起始设备号自己给定的设备号* param - count : 申请的数量* param - name : 设备名字*/ int register_chrdev_region(dev_t from, unsigned count, const char *name); 无论是通过  alloc_chrdev_region  函数还是  register_chrdev_region 函数统一使用以下释放函数 void unregister_chrdev_region(dev_t from, unsigned count); 使用新字符设备驱动设备号分配实例 int major; /* 主设备号 */ int minor; /* 次设备号 */ dev_t devid; /* 设备号 *//* 设备号分配 */ if (major) {/* 定义了主设备号 */devid MKDEV(major, 0); // 如果 major 有效的话就使用 MKDEV 来构建设备号次设备号选择 0并且大部分驱动次设备号都选择 0register_chrdev_region(devid, 1, test); } else {/* 没有定义设备号 */alloc_chrdev_region(devid, 0, 1, test); /* 申请设备号 */major MAJOR(devid); /* 获取分配号的主设备号 */minor MINOR(devid); /* 获取分配号的次设备号 */ }/* 设备号释放 */ unregister_chrdev_region(devid, 1); /* 注销设备号 */ 2. 新的字符设备注册方法 ① 字符设备结构 编写字符设备驱动之前需要定义一个 cdev 结构体变量这个变量就表示一个字符设备 struct cdev test_cdev; ② 初始化字符设备 定义好 cdev 变量以后就要使用 cdev_init 函数对其进行初始化 void cdev_init(struct cdev *cdev, const struct file_operations *fops); 初始化示例如下 struct cdev testcdev;/* 设备操作函数 */ static struct file_operations test_fops {.owner THIS_MODULE,/* 其他具体的初始项 */ };testcdev.owner THIS_MODULE; cdev_init(testcdev, test_fops); /* 初始化 cdev 结构体变量 */ ③ 添加字符设备 cdev_add 函数用于向 Linux 系统添加字符设备(cdev 结构体变量)首先使用 cdev_init 函数完成对 cdev 结构体变量的初始化然后使用 cdev_add 函数向 Linux 系统添加这个字符设备。  /** param - p : 指向要添加的字符设备(cdev结构体变量)* param - dev : 设备所使用的设备号* param - count : 要添加的设备数量*/ int cdev_add(struct cdev *p, dev_t dev, unsigned count); 添加 cdev_add 示例如下 struct cdev testcdev;/* 设备操作函数 */ static struct file_operations test_fops {.owner THIS_MODULE,/* 其他具体的初始项 */ };testcdev.owner THIS_MODULE; cdev_init(testcdev, test_fops); /* 初始化 cdev 结构体变量 */ cdev_add(testcdev, devid, 1); /* 添加字符设备 */ Linux 内核中大量的字符设备驱动都是采用这种方法向 Linux 内核添加字符设备。  ④ 卸载字符设备 cdev_del 函数是从 Linux 内核中删除相应的字符设备 void cdev_del(struct cdev *p); 删除字符设备示例如下 cdev_del(testcdev); /* 删除 cdev */ 二、自动创建设备节点 使用 modprobe 加载驱动模块成功的话就会自动在/dev 目录下创建对应的设备文件。  1. mdev  使用 mdev 来实现设备节点文件的自动创建与删除。buildroot 已经帮我们处理好了 mdev 。 2. 创建和删除类 自动创建设备节点的工作是在驱动程序的入口函数中完成的一般在 cdev_add 函数后面添加自动创建设备节点相关代码。  /** description : 创建的类* param - owner : 一般为 THIS_MODULE* param - name : 设备名字* return : 指向结构体 class 的指针也就是创建的类*/ struct class *class_create (struct module *owner, const char *name);/* 类删除函数 */ void class_destroy(struct class *cls); // cls 就是要删除的类 3. 创建设备 自动创建设备节点还需要在这个类下创建一个设备。使用 device_create 函数在类下面创建设备 /** param - cls : 设备要创建哪个类下面* param - parent : 父设备一般为 NULL* param - devt : 设备号* param - drvdata : 设备可能会使用的一些数据一般为 NULL* param - fmt : 设备名字如果设置 fmtxxx 的话就会生成/dev/xxx 这个设备文件* return : 创建好的设备*/ struct device *device_create(struct class *cls,struct device *parent,dev_t devt,void *drvdata,const char *fmt, ...)/* 删除创建的设备 */ void device_destroy(struct class *cls, dev_t devt); // classs 是要删除的设备所处的类 // devt 是要删除的设备号 4. 示例 struct class *class; /* 类 */ struct device *device; /* 设备 */ dev_t devid; /* 设备号 *//* 驱动入口函数 */ static int __init xxx_init(void) {/* 创建类 */class class_create(THIS_MODULE, xxx);/* 创建设备 */device device_create(class, NULL, devid, NULL, xxx);return 0; }/* 驱动出口函数 */ static void __exit led_exit(void) {/* 删除设备 */device_destroy(newchrled.class, newchrled.devid);/* 删除类 */class_destroy(newchrled.class); }module_init(led_init); module_exit(led_exit); 三、设置文件私有数据 每个硬件设备都有一些属性比如主设备号(dev_t)类(class)、设备(device)、开关状态(state)等等在编写驱动的时候你可以将这些属性全部写成变量的形式但对于一个设备的所有属性信息我们最好将其做成一个结构体。编写驱动 open 函数的时候将设备结构体作为私有数据添加到设备文件中 struct test_dev {dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */int major; /* 主设备号 */int minor; /* 次设备号 */ };struct test_dev testdev;/* open 函数 */ static int test_open(struct inode *inode, struct file *filp) {filp-private_data testdev; /* 设置私有数据 */return 0; } 在 open 函数里面设置好私有数据以后在 write、read、close 等函数中直接读取 private_data 即可得到设备结构体。  四、驱动程序编写 1. LED 驱动程序编写 在 3/linux/atk-mpl/Drivers 下创建 3_newchrled 子目录并且 VScode 工作区名为 newchrled并且新建 newchrled.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 #include linux/errno.h #include linux/gpio.h #include linux/cdev.h #include linux/device.h #include asm/mach/map.h #include asm/uaccess.h #include asm/io.h#define NEWCHRLED_CNT 1 /* 设备号个数 */ #define NEWCHRLED_NAME newchrled /* 名字 */ #define LEDOFF 0 /* 关灯 */ #define LEDON 1 /* 开灯 *//* 寄存器物理地址 */ #define PERIPH_BASE (0x40000000) #define MPU_AHB4_PERIPH_BASE (PERIPH_BASE 0x10000000) #define RCC_BASE (MPU_AHB4_PERIPH_BASE 0x0000) #define RCC_MP_AHB4ENSETR (RCC_BASE 0XA28) #define GPIOI_BASE (MPU_AHB4_PERIPH_BASE 0xA000) #define GPIOI_MODER (GPIOI_BASE 0x0000) #define GPIOI_OTYPER (GPIOI_BASE 0x0004) #define GPIOI_OSPEEDR (GPIOI_BASE 0x0008) #define GPIOI_PUPDR (GPIOI_BASE 0x000C) #define GPIOI_BSRR (GPIOI_BASE 0x0018)/* 映射后的寄存器虚拟地址指针 */ static void __iomem *MPU_AHB4_PERIPH_RCC_PI; static void __iomem *GPIOI_MODER_PI; static void __iomem *GPIOI_OTYPER_PI; static void __iomem *GPIOI_OSPEEDR_PI; static void __iomem *GPIOI_PUPDR_PI; static void __iomem *GPIOI_BSRR_PI;/* newchrled设备结构体 */ struct newchrled_dev {dev_t devid; /* 设备号 */struct cdev cdev; /* cdev */struct class *class; /* 类 */struct device *device; /* 设备 */int major; /* 主设备号 */int minor; /* 次设备号 */ };struct newchrled_dev newchrled; /* led设备 *//** description : LED打开/关闭* param - sta : LEDON(0) 打开LEDLEDOFF(1) 关闭LED* return : 无*/ void led_switch(u8 sta) {u32 val 0;if(sta LEDON) {val readl(GPIOI_BSRR_PI);val | (1 16); writel(val, GPIOI_BSRR_PI);}else if(sta LEDOFF) {val readl(GPIOI_BSRR_PI);val| (1 0); writel(val, GPIOI_BSRR_PI);} }/** description : 取消映射* return : 无*/ void led_unmap(void) {/* 取消映射 */iounmap(MPU_AHB4_PERIPH_RCC_PI);iounmap(GPIOI_MODER_PI);iounmap(GPIOI_OTYPER_PI);iounmap(GPIOI_OSPEEDR_PI);iounmap(GPIOI_PUPDR_PI);iounmap(GPIOI_BSRR_PI); }/** description : 打开设备* param - inode : 传递给驱动的inode* param - filp : 设备文件file结构体有个叫做private_data的成员变量* 一般在open的时候将private_data指向设备结构体。* return : 0 成功;其他 失败*/ static int led_open(struct inode *inode, struct file *filp) {filp-private_data newchrled; /* 设置私有数据 */return 0; }/** description : 从设备读取数据 * param - filp : 要打开的设备文件(文件描述符)* param - buf : 返回给用户空间的数据缓冲区* param - cnt : 要读取的数据长度* param - offt : 相对于文件首地址的偏移* return : 读取的字节数如果为负值表示读取失败*/ static ssize_t led_read(struct file *filp, char __user *buf, size_t cnt, loff_t *offt) {return 0; }/** description : 向设备写数据 * param - filp : 设备文件表示打开的文件描述符* param - buf : 要写给设备写入的数据* param - cnt : 要写入的数据长度* param - offt : 相对于文件首地址的偏移* return : 写入的字节数如果为负值表示写入失败*/ static ssize_t led_write(struct file *filp, const char __user *buf, size_t cnt, loff_t *offt) {int retvalue;unsigned char databuf[1];unsigned char ledstat;retvalue copy_from_user(databuf, buf, cnt);if(retvalue 0) {printk(kernel write failed!\r\n);return -EFAULT;}ledstat databuf[0]; /* 获取状态值 */if(ledstat LEDON) { led_switch(LEDON); /* 打开LED灯 */} else if(ledstat LEDOFF) {led_switch(LEDOFF); /* 关闭LED灯 */}return 0; }/** description : 关闭/释放设备* param - filp : 要关闭的设备文件(文件描述符)* return : 0 成功;其他 失败*/ static int led_release(struct inode *inode, struct file *filp) {return 0; }/* 设备操作函数 */ static struct file_operations newchrled_fops {.owner THIS_MODULE,.open led_open,.read led_read,.write led_write,.release led_release, };/** description : 驱动入口函数* param : 无* return : 无*/ static int __init led_init(void) {u32 val 0;int ret;/* 初始化LED *//* 1、寄存器地址映射 */MPU_AHB4_PERIPH_RCC_PI ioremap(RCC_MP_AHB4ENSETR, 4);GPIOI_MODER_PI ioremap(GPIOI_MODER, 4);GPIOI_OTYPER_PI ioremap(GPIOI_OTYPER, 4);GPIOI_OSPEEDR_PI ioremap(GPIOI_OSPEEDR, 4);GPIOI_PUPDR_PI ioremap(GPIOI_PUPDR, 4);GPIOI_BSRR_PI ioremap(GPIOI_BSRR, 4);/* 2、使能PI时钟 */val readl(MPU_AHB4_PERIPH_RCC_PI);val ~(0X1 8); /* 清除以前的设置 */val | (0X1 8); /* 设置新值 */writel(val, MPU_AHB4_PERIPH_RCC_PI);/* 3、设置PI0通用的输出模式。*/val readl(GPIOI_MODER_PI);val ~(0X3 0); /* bit0:1清零 */val | (0X1 0); /* bit0:1设置01 */writel(val, GPIOI_MODER_PI);/* 3、设置PI0为推挽模式。*/val readl(GPIOI_OTYPER_PI);val ~(0X1 0); writel(val, GPIOI_OTYPER_PI);/* 4、设置PI0为高速。*/val readl(GPIOI_OSPEEDR_PI);val ~(0X3 0); /* bit0:1 清零 */val | (0x2 0); /* bit0:1 设置为10*/writel(val, GPIOI_OSPEEDR_PI);/* 5、设置PI0为上拉。*/val readl(GPIOI_PUPDR_PI);val ~(0X3 0); /* bit0:1 清零*/val | (0x1 0); /*bit0:1 设置为01*/writel(val,GPIOI_PUPDR_PI);/* 6、默认关闭LED */val readl(GPIOI_BSRR_PI);val | (0x1 0);writel(val, GPIOI_BSRR_PI);/* 注册字符设备驱动 *//* 1、创建设备号 */if (newchrled.major) { /* 定义了设备号 */newchrled.devid MKDEV(newchrled.major, 0);ret register_chrdev_region(newchrled.devid, NEWCHRLED_CNT, NEWCHRLED_NAME);if(ret 0) {pr_err(cannot register %s char driver [ret%d]\n,NEWCHRLED_NAME, NEWCHRLED_CNT);goto fail_map;}} else { /* 没有定义设备号 */ret alloc_chrdev_region(newchrled.devid, 0, NEWCHRLED_CNT, NEWCHRLED_NAME); /* 申请设备号 */if(ret 0) {pr_err(%s Couldnt alloc_chrdev_region, ret%d\r\n, NEWCHRLED_NAME, ret);goto fail_map;}newchrled.major MAJOR(newchrled.devid); /* 获取分配号的主设备号 */ // 这两行可有可无newchrled.minor MINOR(newchrled.devid); /* 获取分配号的次设备号 */}printk(newcheled major%d,minor%d\r\n,newchrled.major, newchrled.minor); /* 2、初始化cdev */newchrled.cdev.owner THIS_MODULE;cdev_init(newchrled.cdev, newchrled_fops);/* 3、添加一个cdev */ret cdev_add(newchrled.cdev, newchrled.devid, NEWCHRLED_CNT);if(ret 0){goto del_unregister;}/* 4、创建类 */newchrled.class class_create(THIS_MODULE, NEWCHRLED_NAME);if (IS_ERR(newchrled.class)) {goto del_cdev;}/* 5、创建设备 */newchrled.device device_create(newchrled.class, NULL, newchrled.devid, NULL, NEWCHRLED_NAME);if (IS_ERR(newchrled.device)) {goto destroy_class;}return 0;destroy_class:class_destroy(newchrled.class); del_cdev:cdev_del(newchrled.cdev); del_unregister:unregister_chrdev_region(newchrled.devid, NEWCHRLED_CNT); fail_map:led_unmap();return -EIO;}/** description : 驱动出口函数* param : 无* return : 无*/ static void __exit led_exit(void) {/* 取消映射 */led_unmap();/* 注销字符设备驱动 */cdev_del(newchrled.cdev);/* 删除cdev */unregister_chrdev_region(newchrled.devid, NEWCHRLED_CNT); /* 注销设备号 */device_destroy(newchrled.class, newchrled.devid);class_destroy(newchrled.class); }module_init(led_init); module_exit(led_exit);MODULE_LICENSE(GPL); MODULE_AUTHOR(LXS); MODULE_INFO(intree, Y); 这里做了一个流程图方便理解 2.  编写测试 APP  这个用上次的那个 ledApp.c 来测试。 五、运行测试 1.  编译驱动程序 编写 Makefile KERNELDIR : /home/alientek/linux/atk-mpl/linux/my_linux/linux-5.4.31 # Linux内核源码路径 CURRENT_PATH : $(shell pwd) # 获取当前所处路径 obj-m : newchrled.o build: kernel_moduleskernel_modules:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) modules clean:$(MAKE) -C $(KERNELDIR) M$(CURRENT_PATH) clean 输入命令 make # 成功后会出现一个 newchrled.ko 驱动模块文件 2.  编译测试 APP 利用交叉编译器编译 APP 测试程序 arm-none-linux-gnueabihf-gcc ledApp.c -o ledApp 3.  运行测试 需要将 ledApp newchrled.ko 复制到 /home/alientek/linux/nfs/rootfs/lib/modules/5.4.31/ 目录下。 depmod # 第一次加载驱动的时候需要运行此命令 modprobe newchrled # 加载驱动 申请主设备号为 241次设备号为 0。并且驱动会自动在 /dev 目录下创建设备节点文件 /dev/newchrdev 再测试一下 LED 红灯是否可以工作 ./ledApp /dev/newchrled 1 # 打开 LED 灯./ledApp /dev/newchrled 0 # 关闭 LED 灯# 最后卸载驱动 rmmod newchrled 总结跟上一章相比多了设备自动分配、新的字符设备注册方法、自动创建设备节点和设置文件私有数据其他和上一章相差不大。
http://www.pierceye.com/news/137614/

相关文章:

  • 中国建设银行上海市分行网站音乐网站开发可行性分析
  • 如何用天地图做网站做面包有哪些网站知乎
  • 买了域名之后怎么建设网站做网站一年赚一千万
  • 跟网站开发公司签合同主要要点个人网站logo需要备案吗
  • 免费询盘网站自我介绍ppt模板
  • 中国会议营销网站怎么做找优惠券的网站
  • 做网站的那些事wordpress改写
  • 仿造整个网站呼市网站建设公司
  • 网站被黑客入侵怎么办企业文化墙设计网站推荐
  • 建设网站的群婚礼婚庆网站建设需求分析
  • 全椒县城乡建设局网站网站怎么做营销策划
  • 响应式网站制作流程河北企业建网站
  • 常州新北区有做淘宝网站策划的吗什么建设网站
  • 成品网站源码68w68游戏wordpress php推送示例
  • 博优云软件官方网站wordpress 个人
  • 登封 网站建设烟台网站关键词推广
  • 深圳实惠的专业建站公司淘宝券商城网站制作
  • 珠海手机网站建设成都设计网站
  • 网站mp3播放器代码国家企业信息系统官方
  • 江西建设银行招聘网站pc网站还有必要做吗
  • 网站建设几个要素做网站需要学会什么软件
  • 做视频网站什么平台好站酷设计网站首页
  • 班级网站设计论文网站多国语言
  • 网站制作评价标准网站服务器怎么收费
  • 怎么建立自己的网站平台多少钱wordpress自建菜单
  • 深圳购物网站如何制作外贸网站 wordpress
  • 商品展示网站模板中国建设电工立网站
  • 网站推广的基本方法对于大部分网站来说都是适用的河北网站开发费用
  • 高安网站建设公司外链代发免费
  • 企业网站建设的价格wordpress免费用户