int (\*probe)(struct platform\_device \*);//函数指针
匹配函数:当driver和device匹配成功之后,执行probe函数
int (\*remove)(struct platform\_device \*);
当driver和device任意一个remove的时候,执行这个函数
void (\*shutdown)(struct platform\_device \*);
当设备收到shutdown,会执行这个函数
int (\*suspend)(struct platform\_device \*, pm\_message\_t state);
当设备收到suspend,会执行这个函数休眠
int (\*resume)(struct platform\_device \*);
当设备收到resume,会执行这个函数唤醒
struct device\_driver driver;
const struct platform\_device\_id \*id_table;
//优先匹配id\_table 的.name成员
bool prevent_deferred_probe;
};
struct device_driver {
const char *name;
//这个是我们匹配设备时候要用到的名字
struct bus_type *bus;
struct module *owner;
const char *mod_name; /* used for built-in modules */
bool suppress_bind_attrs; /* disables bind/unbind via sysfs */
const struct of_device_id *of_match_table;
const struct acpi_device_id *acpi_match_table;
int (*probe) (struct device *dev);
int (*remove) (struct device *dev);
void (*shutdown) (struct device *dev);
int (*suspend) (struct device *dev, pm_message_t state);
int (*resume) (struct device *dev);
const struct attribute_group **groups;
const struct dev_pm_ops *pm;
struct driver_private *p;
};
设备驱动代码编写:
#include<linux/init.h>
#include<linux/module.h>
#include <linux/platform_device.h>
int beep_probe(struct platform_device *pdev){
printk(“beep_probe”);
return 0;
}
int beep_remove(struct platform_device *pdev){
printk(“beep_remove”);
return 0;
}
//id_table 的优先级比较高
const struct platform_device_id beepid_table =
{
.name = “123”
};
struct platform_driver beep_driver = {
.probe = beep_probe,
.remove = beep_remove,
.driver = {
.owner = THIS_MODULE,
.name = “beep_test”
},
.id_table = &beepid_table
};
static int beep_driver_init(void)
{
int ret =0;
ret = platform_driver_register(&beep_driver);
if (ret<0)
{
printk(“platform_driver_register is error”);
return ret;
}
printk("platform\_driver\_register is error");
return 0;
}
static void beep_driver_exit(void)
{
platform_driver_unregister(&beep_driver);
printk(“bye bye”);
}
module_init(beep_driver_init);
module_exit(beep_driver_exit);
MODULE_LICENSE(“GPL”);
##### 实验现象
![在这里插入图片描述](https://img-blog.csdnimg.cn/bcdb1a77b30e43afb6b1bbe04154c1ab.png)
device和driver综合测试:
结果如下:进入了probe函数~~~!!!
![在这里插入图片描述](https://img-blog.csdnimg.cn/14b0e68818114046981d6298e3ed1b53.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBA5qKF5bGx5YmR5a6i,size_20,color_FFFFFF,t_70,g_se,x_16)
#### 四、平台总线probe函数编写
probe 函数编写思路:
(1)从 device.c 里面获取资源
方式一、直接获得,不推荐。
printk(“beep_res is %s\n”,pdev->resource[0].name);//直接获取,打印成员变量
方法二、使用函数获得
struct resource *platform_get_resource_byname(struct platform_device *,unsigned int,const char *);
(2)注册杂项 / 字符设备,完善file\_operation 结构体,并生成设备节点。
注册之前要先登记。
#define request_mem_region(start,n,name) __request_region(&iomem_resource, (start), (n ), (name), 0)
登记使用
int beep_probe(struct platform_device *pdev){
printk("beep\_probe");
//方法1、直接获取,打印成员变量
printk("beep\_res is %s\n",pdev->resource[0].name);
//方法2 结构体成员 资源类型,同类中第几个
beep_mem = platform\_get\_resource(pdev,IORESOURCE_MEM,0);
if (beep_mem == NULL)
{
printk("platform\_get\_resource is error\n");
return -EBUSY;
}
printk("beep\_res start is 0x%x\n",beep_mem->start);
printk("beep\_res end is 0x%x\n",beep_mem->end);
//登记使用
beep_mem_temp = requset\_mem\_region(beep_mem->start,beep_mem->end-beep_mem->start+1,"beep");
if (beep_mem_temp == NULL)
{
printk("requset\_mem\_region is error\n");
goto err_region;
}
return 0;
err_region:
release_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1);
}
与原先的区别就是在probe函数中使用杂项设备和字符设备,将device和driver分开了。先前是在misc\_init中注册杂项设备。
#include<linux/init.h>
#include<linux/module.h>
#include <linux/platform_device.h>
#include <linux/ioport.h>
#include <linux/miscdevice.h>
#include <linux/fs.h>
#include <linux/uaccess.h>
#include <linux/io.h>
#define GPIO5_DR 0x020AC000
unsigned int *vir_gpio_dr;//存放映射完成的虚拟地址的首地址
int misc_open(struct inode *inode,struct file *file)
{
printk(“hello misc_open\n”);
return 0;
}
int misc_close(struct inode *inode,struct file *file)
{
printk(“bye bye\n”);
return 0;
}
int misc_read(struct file *file,char __user *ubuf,size_t size,loff_t *loff_t)
{
char kbuf[64] = “hello”;
if(copy\_to\_user(ubuf,kbuf,sizeof(kbuf))!=0)
{
printk("copy to user error\n");
return -1;
}
return 0;
}
int misc_write(struct file *file,const char __user *ubuf,size_t size,loff_t *loff_t)
{
char kbuf[64] = {0};
if(copy\_from\_user(kbuf,ubuf,size)!=0) //ubuf 传送进来 保存到 kbuf中
{
printk("copy\_from\_user\n");
return -1;
}
printk("kbuf is %s\n",kbuf);
if (kbuf[0] == 1)
\*vir_gpio_dr |= (1 <<1);//open
else if (kbuf[0] == 0)
\*vir_gpio_dr &= ~(1 <<1);//close
return 0;
}
struct file_operations misc_fops ={
.owner = THIS_MODULE,
.open = misc_open,
.release = misc_close,
.read = misc_read,
.write = misc_write
};
struct miscdevice misc_dev = {
.minor = MISC_DYNAMIC_MINOR,
.name = “hello_misc”,
.fops = &misc_fops
};
struct resource *beep_mem;
struct resource *beep_mem_temp;
int beep_probe(struct platform_device *pdev){
int ret = 0;
printk("beep\_probe");
//方法1、直接获取,打印成员变量
printk("beep\_res is %s\n",pdev->resource[0].name);
//方法2 结构体成员 资源类型,同类中第几个
beep_mem = platform\_get\_resource(pdev,IORESOURCE_MEM,0);
if (beep_mem == NULL)
{
printk("platform\_get\_resource is error\n");
return -EBUSY;
}
printk("beep\_res start is 0x%x\n",beep_mem->start);
printk("beep\_res end is 0x%x\n",beep_mem->end);
#if 0
//登记使用
beep_mem_temp = requset_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1,“beep”);
if (beep_mem_temp == NULL)
{
printk("requset\_mem\_region is error\n");
goto err_region;
}
#endif
/************************************************************/
vir_gpio_dr = ioremap(beep_mem->start,4);
if(vir_gpio_dr == NULL)
{
printk("GPIO5\_DR ioremap error\n");
return -EBUSY;
}
printk("GPIO5\_DR ioremap ok\n");
/************************************************************/
ret = misc\_register(&misc_dev);//注册
if (ret<0)
{
printk("misc\_register is error\n");
return -1;
}
printk("misc\_register is successful\n");
return 0;
// err_region:
// release_mem_region(beep_mem->start,beep_mem->end-beep_mem->start+1);
}
int beep_remove(struct platform_device *pdev){
printk("beep\_remove");
return 0;
}
//id_table 的优先级比较高
const struct platform_device_id beepid_table =
{
.name = “123”
};
struct platform_driver beep_driver = {
.probe = beep_probe,
.remove = beep_remove,
.driver = {
.owner = THIS_MODULE,
.name = “beep_test”
},
.id_table = &beepid_table
};
static int beep_driver_init(void)
{
int ret =0;
ret = platform_driver_register(&beep_driver);
if (ret<0)
{
printk(“platform_driver_register is error”);
return ret;
}
最后
自我介绍一下,小编13年上海交大毕业,曾经在小公司待过,也去过华为、OPPO等大厂,18年进入阿里一直到现在。
深知大多数Java工程师,想要提升技能,往往是自己摸索成长,自己不成体系的自学效果低效漫长且无助。
因此收集整理了一份《2024年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!
715840652577)]
[外链图片转存中…(img-cqAZKjJK-1715840652577)]
[外链图片转存中…(img-dmEU6Oep-1715840652578)]
[外链图片转存中…(img-2Db756rj-1715840652579)]
既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!
如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!
由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!