驱动——platform驱动ADC

本文介绍了STM32平台驱动ADC的过程,包括设备树在平台驱动中的作用、如何通过平台总线获取硬件资源和中断号,以及字符设备的注册和设备节点的创建。文章还讨论了平台总线驱动的模板和ADC驱动的寄存器初始化,强调了ADC转换过程中的中断处理和数据读取。
摘要由CSDN通过智能技术生成

我们再谈一下平台总线。
前面讲平台总线是可以让drv和dev实现分离。主要作用是用于平台升级。
现在结合设备树来看一下 平台总线的好处。(平台总线是虚拟总线,用于一些ADC,PWM这样的没有实体总线连接(iIC spi…)的一些设备,为了管理这些设备统一虚拟出平台总线来管理)

1)首先我们要了解到
当我们在设备树文件上写了应该设备后(属于我们的直接定义的设备,可以有2^20个子设备(前面说可以放无限个是错误的)
它就会把设备树的信息放在/sys/bus/plaoform/device下(那我要是iic设备就会放在/sys/bus/i2c下)
2)这样我们只要写DRV程序就可以了,利用platfrom根据compatinle进行匹配,然后用
platform_get_resource拿到硬件信息;
platform_get_irq拿到中断号
这样就可以在驱动程序中拿到硬件资源了,并且我们只需要写驱动程序,而硬件信息只需要修改设备树就可以了。
就不用像以前一样,还要写dev写drv写bus。。。这么麻烦。
———————————————————————————————————————
申请设备号的三种方式:
1)
register_chrdev(unsigned int major, const char * name, const struct file_operations * fops)
在 2.4 的内核我们使用 register_chrdev(0, “hello”, &hello_fops) 来进行字符设备设备节点的分配,这种方式每一个主设备号只能存放一种设备,它们使用相同的 file_operation 结构体,也就是说内核最多支持 256 个字符设备驱动程序。

  1. register_chrdev_region(dev, 1, FSPWM_DEV_NAME);
    cdev_init(&fspwm->cdev, &fspwm_ops);
    cdev_add(&fspwm->cdev, dev, 1);
    register_chrdev_region() 函数用于分配指定的设备编号范围。它需要手动初始化cdev并且将cdev加入到内核的cdev链表中。

3)
int alloc_chrdev_region(dev_t *dev, unsigned baseminor, unsigned count, const char *name)
alloc_chrdev_region() 函数用于动态申请设备编号范围。
——————————————————————————————————————
创建设备节点的两种方式。
对设备进行操作,其实就是对cdev进行一些操作。cdev里面有主设备号以及file_operatorion.
那么创建设备节点就可以便于用户找到主设备号并进行file_operatorion.操作。
1)手动创建:利用命令 :mknod /dev/(你自定义设备的名字) c(字符设备)/d(块设备) 主设备号(一定要和你申请的一样)

2)自动创建:对于热插拔事件,我们应用程序要完成,插入加载模块,并且自动创建设备节点,拔自动卸载模块,和注销设备节点。
对于普通事件我们也一般采用自动创建的方式。
:class_create(THIS_MODULE,“xxx”);
:device_create(…);
————————————————————————————————————————
我们还是讲怎么ADC驱动吧!!!!
平台总线驱动的另一种模板:
我们之前的都是module_init module_exit。。。实例化应该drv,设置匹配的complation 在init里面把drv注册进去,在exit里面移除。
。。。。千篇一律。。
那么我们在内核中,把这种固定的用平台总线的驱动封装了一个函数
module_platform_driver(fspwm_drv);
然后我们就可以这样做:

tatic const struct of_device_id fspwm_of_matches[] = {
   
	{
    .compatible = "fs4412,fspwm", },
	{
    /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, fspwm_of_matches);

struct platform_driver fspwm_drv = {
    
	.driver = {
    
		.name    = "fspwm",
		.owner   = THIS_MODULE,
		.of_match_table = of_match_ptr(fspwm_of_matches),
	},  
	.probe   = fspwm_probe,
	.remove  = fspwm_remove,
};

module_platform_driver(fspwm_drv);

其实module_platform_driver(fspwm_drv);里面也调用了init 和exit就是进行了封装而已。

——————————————————————————————————————
我们还是讲ADC驱动吧。。。这有什么讲的?我们模型都有了,驱动不是照套吗?
1)写设备树。
2)按上面的编写驱动代码模型。匹配成功之后调用proble。
3)在proble里面申请设备号,创建设备节点,获取设备信息。地址映射。
这样我们就拿到硬件信息了,还有虚拟地址。
那么不管他是ADC,PWM,KEY(当然key是用input子系统好一点),Led…都是对一些地址进行一些读写操作。
那我们来看一下对ADC需要哪些操作?
我们在proble下面肯定要对一些寄存器进行初始化:
writel((1 << 16) | (1 << 14) | (19 << 6), fsadc->adccon);
1<< 16是设置精度为12;
1<<14使能分频
19<<6设置为20倍分频。
初始化好了,之后我们就该操作了。我们要的是把继电器中连续变化的模拟量转化成数字量
在这里插入图片描述
在这里插入图片描述
可以看到我们的电位器连接到ain3口。所以我们要选择adcmux为0011
我们去读这个ADCDAT的0~11位就可以读到结果,
当我们数据转化的时候就会触发中断去读ADCDAT的数据,然后读取完毕,就会利用clrint清除中断。
————————————————详情请看arm——ADC裸机开发
驱动代码:

#include <linux/init.h>
#include <linux/kernel.h>
#include <linux/module.h>

#include <linux/fs.h>
#include <linux/cdev.h>

#include <linux/slab.h>
#include <linux/ioctl.h>
#include <linux/uaccess.h>

#include <linux/io.h>
#include <linux/ioport.h>
#include <linux/platform_device.h>

#include <linux/of.h>
#include <linux/interrupt.h>

#include "fsadc.h"

#define FSADC_MAJOR	256
#
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值