迅为嵌入式linux驱动开发笔记(三)— 平台总线模型_platform总线模型

		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年嵌入式&物联网开发全套学习资料》,初衷也很简单,就是希望能够帮助到想自学提升又不知道该从何学起的朋友,同时减轻大家的负担。

img

img

img

img

img

img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

715840652577)]

[外链图片转存中…(img-cqAZKjJK-1715840652577)]

[外链图片转存中…(img-dmEU6Oep-1715840652578)]

[外链图片转存中…(img-2Db756rj-1715840652579)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,基本涵盖了95%以上嵌入式&物联网开发知识点,真正体系化!

如果你觉得这些内容对你有帮助,需要这份全套学习资料的朋友可以戳我获取!!

由于文件比较大,这里只是将部分目录大纲截图出来,每个节点里面都包含大厂面经、学习笔记、源码讲义、实战项目、讲解视频,并且后续会持续更新!!

  • 3
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值