仿qq网站程序h5高端网站开发
- 作者: 五速梦信息网
- 时间: 2026年03月21日 11:17
当前位置: 首页 > news >正文
仿qq网站程序,h5高端网站开发,施工合同电子版,自助建站免费搭建个人网站目录 前言一、平台设备总线1.是个啥#xff1f;2.API函数 二、设备端驱动端1. 匹配机制2. 实现代码 三、设备树驱动端1.匹配机制2.代码实现 前言 本文主要介绍了一下两种驱动编写方法#xff1a; 1.比较原始的设备端驱动端编写方法。 2.效率较高的设备树驱动端编写方法。 最… 目录 前言一、平台设备总线1.是个啥2.API函数 二、设备端驱动端1. 匹配机制2. 实现代码 三、设备树驱动端1.匹配机制2.代码实现 前言 本文主要介绍了一下两种驱动编写方法 1.比较原始的设备端驱动端编写方法。 2.效率较高的设备树驱动端编写方法。 最后使用LED闪烁实战验证了一下。 一、平台设备总线 1.是个啥 在Linux驱动开发中平台设备总线Platform Device Bus是一个重要的概念用于管理与特定平台紧密集成的设备。这些设备通常不是通过传统的总线如PCI、USB连接的而是直接连接到系统的硬件平台上。 说人话就是平台设备总线Platform Device Bus是Linux内核虚拟出来的一条总线不是真实的导线。它将底层驱动分为了设备端和驱动端。设备端主要就是负责提供稳定不变的东西。例如设备的信息等大部分就是和硬件相关的该部分可以选择用设备树写。驱动端主要就是负责先从设备端获取稳定不变的信息然后再去驱动一些需要变动的东西。 平台设备总线也分为两种编写方式1.设备端驱动端。2.设备树驱动端。本质上的区别就是硬件配置的管理方式不同前者是要单独写一个驱动程序里面包含了有关设备的所有配置信息。后者的硬件配置信息通过挂载到设备树上来管理。 注意无论是设备端驱动端还是设备树驱动端他们在加载时都不用分先后。 2.API函数 注册平台设备函数 int platform_device_register(struct platform_device *pdev);函数参数指向 platform_device 结构体的指针核心结构体 void xyd_release(struct device *dev)//虽然不用填东西但必须要有 { }struct platform_device {const char *name;int id;struct device dev;u32 num_resources;struct resource *resource; }核心结构体里的参数有很多需要填写的部分如上所示。 name:就是和驱动端所要匹配的名字。 id也是匹配方式的一种这里一般填-1即可 dev存放设备信息的核心结构体void (*release)(struct device *dev); num_resources提供资源的数量一般用ARRAY_SIZE()计算。 resource:提供的具体资源 struct resource { resource_size_t start; resource_size_t end; const char *name; unsigned long flags; };start资源设备的起始地址 end资源设备的结束地址 name给这个设备资源取的名字 flags资源的类型 — 使用宏即可内核已经帮你定义好了 注销平台设备函数 void platform_device_unregister(struct platform_device *pdev)函数参数平台设备的核心结构体 接下来是驱动端的API函数 platform_driver_register(struct platform_driver *prv) struct platform_driver { int (*probe)(struct platform_device *); int (*remove)(struct platform_device *); struct device_driver driver; };probe探测函数。 设备端和驱动端匹配成功时就会进入到该函数中去执行从而去获取资源以及注册相关的设备资源。 remove移除函数有一端被卸载时就会进入该移除函数中执行。一般存放卸载的API函数。 driver设备资源的核心结构体 struct device_driver { const char *name; const struct of_device_id *of_match_table; };name驱动端和设备端进行匹配的名字 of_match_table他是用于驱动端和设备树进行匹配的参数 struct of_device_id { char compatible[128];//他要和设备树里的 compatible 保持一致 };如果你使用的是驱动端设备树的编写方法那么此时你需要填写如下结构体 struct device_driver { const char *name, }否则你去加载内核驱动时内核会出问题。 二、设备端驱动端 这种方法现在用的已经较少了因为比较麻烦。设备信息通常在代码中直接定义通常适合简单的工作场景。
- 匹配机制 因为平台设备总线将驱动分为设备端和驱动端那么驱动运行时驱动端是如何找到对应的设备端去寻找设备信息的呢 关键就在于名字设备端驱动端的匹配是由名字来匹配的本质上就是利用strcmp函数进行字符串比较。 设备端和驱动端都有一个属于自己的核心结构体而各自的核心结构体里都有一个名为name的成员变量他们就是通过该变量进行匹配的。 在编写时一定要注意两端的name变量要保持一致
- 实现代码
设备端
#include linux/module.h
#include linux/kernel.h
#include linux/of.h
#include linux/of_gpio.h
#include linux/cdev.h
#include linux/gpio.h
#include linux/device.h
#include linux/fs.h
#include linux/platform_device.h//定义结构体表明存放的设备信息
struct resource Led_s[2]{[0]{.start 21,.end 22,.name my_leds,.flags IORESOURCE_MEM,}, [1]{.start 0,.end 1,.name my_leds,.flags IORESOURCE_MEM,}
};void xyd_release(struct device *dev)
{
}struct platform_device pdev{.namemy_leds,.id -1,.dev{.release xyd_release,},.num_resources ARRAY_SIZE(Led_s),.resource Led_s,
};static int __init mydevice_init(void)
{int a0;printk(设备端加载函数运行!\n);aplatform_device_register(pdev);if(a 0){printk(platform_device_register error\n);return -1;}printk(设备端注册成功\n); return 0;
}static void __exit mydevice_exit(void)
{printk(设备端卸载函数运行!\n);platform_device_unregister(pdev);printk(设备端卸载完成!\n);
}module_init(mydevice_init);
module_exit(mydevice_exit);
MODULE_LICENSE(GPL);驱动端
#include linux/module.h
#include linux/kernel.h
#include linux/miscdevice.h
#include linux/fs.h
#include linux/cdev.h
#includelinux/device.h
#include linux/gpio.h
#include linux/fs.h
#include linux/of_gpio.h
#include linux/of.h
#include linux/platform_device.hstruct resource *led[2];
dev_t dev;
struct cdev mydev;
struct class *myclass NULL;int my_open (struct inode *inode, struct file *fp)
{int i;for(iled[0]-start;iled[0]-end;i){gpio_set_value(i,led[1]-end);//21,1⁄22,1}printk(led灯:亮\n);return 0;
}int my_release (struct inode *inode, struct file *fp)
{int i;for(iled[0]-start;iled[0]-end;i){gpio_set_value(i,led[1]-start);//21,0/22,0}printk(led灯:灭\n);return 0;
}struct file_operations my_file {.open my_open,.release my_release,
};int my_probe(struct platform_device *pdev)
{int i;for(i0;i1;i){led[i] platform_get_resource(pdev,IORESOURCE_MEM,i);}gpio_request(led[0]-start, led1);gpio_request(led[0]-end, led2);gpio_direction_output(led[0] - start, 0);gpio_direction_output(led[0] - end, 0);//动态申请设备号alloc_chrdev_region(dev, 0, 1, myled);//初始化设备核心结构体cdev_init(mydev,my_file);//向内核申请Linux2.6字符设备cdev_add(mydev, dev, 1);myclass class_create(THIS_MODULE,LED_CLASS);device_create(myclass, NULL, dev, NULL, myleds);printk(探测函数设备端和驱动端匹配成功\n);return 0;
}int myled_remove(struct platform_device *pdev)
{printk(移除函数运行\n);device_destroy(myclass,dev);//销毁设备节点class_destroy(myclass);//销毁设备类cdev_del(mydev);//删除字符设备unregister_chrdev_region(dev,1);//释放设备号printk(设备注销成功\n);gpio_free(led[0]-start);gpio_free(led[1]-start);return 0;
}struct platform_driver drv {.probe my_probe,.remove myled_remove,.driver {.name my_leds,},
};static int __init mydriver_init(void)
{platform_driver_register(drv);return 0;
}static void __exit mydriver_exit(void)
{platform_driver_unregister(drv);
} module_init(mydriver_init);
module_exit(mydriver_exit);
MODULE_LICENSE(GPL);应用端
#include stdio.h
#include fcntl.h
#include unistd.h
#include string.h
int main(int argc,char *argv[])
{int fd 0;char buffer[100];const char *data Hello, this is a test write!;if(argc2){printf(请输入正确的参数\n);return -1;}fd open(argv[1],O_RDWR);if(fd0){perror(open);return -1;}while(1){fd open(argv[1],O_RDWR); // — 底层的open函数sleep(1);close(fd);//底层的closesleep(1);} return 0;
}三、设备树驱动端 使用设备树驱动端的编写方法是当前最常用且效率最高的方式。通过设备树我们能够通过几行简洁的代码完成硬件信息的挂载从而将主要精力集中在编写驱动端的代码上。
1.匹配机制 和设备端驱动端的匹配方法不同设备树驱动端的匹配机制主要是通过设备树里的 Compatible属性来匹配的。所以在编写时驱动端代码要和设备树上的compatible兼容性标识符保持一致。
设备树
驱动端
2.代码实现 设备树 // SPDX-License-Identifier: (GPL-2.0 OR MIT) /** Copyright © 2021 Rockchip Electronics Co., Ltd.**//dts-v1/;#include rk3588s-evb4-lp4x-yyt.dtsi #include rk3588-linux.dtsi/ {model Rockchip RK3588S EVB4 LP4X V10 Board;compatible rockchip,rk3588s-evb4-lp4x-v10, rockchip,rk3588;xydled:xyd_leds {compatible xyd_led;leds-gpios gpio0 RK_PC5 GPIO_ACTIVE_HIGH,gpio0 RK_PC6 GPIO_ACTIVE_HIGH,gpio0 RK_PD0 GPIO_ACTIVE_HIGH,gpio1 RK_PD5 GPIO_ACTIVE_HIGH;status okay;};xydkey:xyd_keys{compatible xyd_keys;keys-gpios gpio1 RK_PA7 GPIO_ACTIVE_LOW,gpio1 RK_PB1 GPIO_ACTIVE_LOW;interrupt-parent gpio1;interrupts RK_PA7 IRQ_TYPE_LEVEL_LOW,RK_PB1 IRQ_TYPE_LEVEL_LOW; status okay;};xydbeep:xyd_beep{compatible xyd-beep;beeps-gpios gpio1 RK_PA4 GPIO_ACTIVE_HIGH;status okay; };xydinfo:xyd_device{compatible xyd-device;devices-gpios gpio0 RK_PC5 GPIO_ACTIVE_HIGH,gpio0 RK_PC6 GPIO_ACTIVE_HIGH,gpio1 RK_PA7 GPIO_ACTIVE_LOW,gpio1 RK_PB1 GPIO_ACTIVE_LOW,gpio1 RK_PA4 GPIO_ACTIVE_HIGH;status okay; };xydnod:xyd_devs{compatible xyd-devs;xydled1: xyd_leds {leds-gpios gpio0 RK_PC5 GPIO_ACTIVE_HIGH, gpio0 RK_PC6 GPIO_ACTIVE_HIGH;status okay;};xydkey1: xyd_keys {keys-gpios gpio1 RK_PA7 GPIO_ACTIVE_LOW,gpio1 RK_PB1 GPIO_ACTIVE_LOW;status okay;};xydbeep1: xyd_beep {beeps-gpios gpio1 RK_PA4 GPIO_ACTIVE_HIGH;status okay;};}; };驱动端 #include linux/module.h #include linux/kernel.h #include linux/miscdevice.h #include linux/fs.h #include linux/cdev.h #includelinux/device.h #include linux/gpio.h #include linux/fs.h #include linux/of_gpio.h #include linux/of.h #include linux/platform_device.hint led[2]{0}; dev_t dev; struct cdev mydev; struct class *myclass NULL;int my_open (struct inode *inode, struct file *fp) {int i;for(i0;i1;i){gpio_set_value(led[i],1);//21,1⁄22,1}printk(led灯:亮\n);return 0; }int my_release (struct inode *inode, struct file *fp) {int i;for(i0;i1;i){gpio_set_value(led[i],0);//21,0/22,0}printk(led灯:灭\n);return 0; }struct file_operations my_file {.open my_open,.release my_release, };int my_probe(struct platform_device *pdev) {//获取编号led[0] of_get_named_gpio(pdev-dev.of_node,leds-gpios,0);led[1] of_get_named_gpio(pdev-dev.of_node,leds-gpios,1);gpio_request(led[0], led1);gpio_request(led[1], led2);gpio_direction_output(led[0], 0);gpio_direction_output(led[1], 0);//动态申请设备号alloc_chrdev_region(dev, 0, 1, myled);//初始化设备核心结构体cdev_init(mydev,my_file);//向内核申请Linux2.6字符设备cdev_add(mydev, dev, 1);myclass class_create(THIS_MODULE,LED_CLASS);device_create(myclass, NULL, dev, NULL, my_leds);printk(探测函数设备端和驱动端匹配成功\n);return 0; } int myled_remove(struct platform_device *pdev) {printk(移除函数运行\n);device_destroy(myclass,dev);//销毁设备节点class_destroy(myclass);//销毁设备类cdev_del(mydev);//删除字符设备unregister_chrdev_region(dev,1);//释放设备号printk(设备注销成功\n);gpio_free(led[0]);gpio_free(led[1]);return 0; }const struct of_device_id mydev_node{.compatible xyd_led, };struct platform_driver drv {.probe my_probe,.remove myled_remove,.driver {.name my_leds,.of_match_table mydev_node }, };static int __init mydriver_init(void) {platform_driver_register(drv);return 0; }static void __exit mydriver_exit(void) {platform_driver_unregister(drv); } module_init(mydriver_init); module_exit(mydriver_exit); MODULE_LICENSE(GPL);应用端 #include stdio.h #include fcntl.h #include unistd.h #include string.h int main(int argc,char *argv[]) {int fd 0;char buffer[100];const char *data Hello, this is a test write!;if(argc2){printf(请输入正确的参数\n);return -1;}fd open(argv[1],O_RDWR);if(fd0){perror(open);return -1;}while(1){fd open(argv[1],O_RDWR); // — 底层的open函数sleep(1);close(fd);//底层的closesleep(1);} return 0; }
- 上一篇: 仿99健康网网站源码繁昌网站建设
- 下一篇: 仿韩国网站源码如何做品牌推广方案
相关文章
-
仿99健康网网站源码繁昌网站建设
仿99健康网网站源码繁昌网站建设
- 技术栈
- 2026年03月21日
-
仿 wordpress主题温州seo公司
仿 wordpress主题温州seo公司
- 技术栈
- 2026年03月21日
-
房子装修设计软件企业网站搜索优化外
房子装修设计软件企业网站搜索优化外
- 技术栈
- 2026年03月21日
-
仿韩国网站源码如何做品牌推广方案
仿韩国网站源码如何做品牌推广方案
- 技术栈
- 2026年03月21日
-
仿礼物说网站模板php网页期末大作业
仿礼物说网站模板php网页期末大作业
- 技术栈
- 2026年03月21日
-
仿美团版网站开发制作广告设计与制作专业认识
仿美团版网站开发制作广告设计与制作专业认识
- 技术栈
- 2026年03月21日






