linux学习-字符设备驱动流程

字符设备驱动流程

一.修改设备树文件

1.添加pinctrl节点

1.找到相关板卡的dts文件;如打开imx6ull-alientek-emmc.dts

​ 其中肯定有iomux节点(input/ouput Multiplexer),在此节点下添加pinctrl节点;命名格式为:

pinctrl_xxx:name{
	fsl,pins = <
		复用功能配置 电气属性配置
	>;
}
//例子
princtrl_beep: beepgrp {
    fsl,pins = <
        MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 
        0X10B0
        >
}

​ 其中MX6ULL_PAD_SNVS_TAMPER1__GPIO5_IO01 实际是一个宏定义,抛开外壳,本质是配置IOMUXC的复用功能,以及记录起配置电气属性的寄存器等,0x10b0即为配置电气属性。

2.添加设备节点

​ 在根节点创建设备节点,格式如下;

name {
    #address-cells = <num>;
    #size-cells    = <num>;
    compatible     = "string";
    pinctrl-names  = "default";
    pinctrl-0      = <&pinctrl_xxx>;
    xxx-gpio       = <&gpiox num polarity>;
    status         = "okay";
};

//例子

beep{
    #address-cells = <1>;
    #size-cells    = <1>;
    compatible     = "atkalpha-beep";
    pinctrl-names  = "default";
    pinctrl-0      = <&pinctrl_beep>;
    beep-gpio     = <&gpio5 1 GPIO_ACTIVE_HIGH>;
    status         = "okay";
};

3.检查Pin是否被其他外设使用

​ 检查有要复用的PIN被使用的话,那就要屏蔽相应的PIN

4.编译设备树

make dtbs执行这行命令,然后使用新编译的.dtb文件启动linux,进入/proc/device-tree目录查看设备节点是否存在

二.编写字符设备驱动文件

第一步:加载和卸载函数,定义相关宏定义

#define XXX_CNT NUM /*设备号个数*/
#define xxx_NAME "STRING" /*名字*/

static int __init xxx_init(){}

static void __exit xxx_exit(){}

module_init()

module_exit()

第二步:编写设备结构体以及文件结构体

struct xxx_dev{
	dev_t devid;
	struct cdev cdev;
	struct class *class;
	struct device *device;
	int major;
	int minor;
	struct device_node *nd;
	int xxx_gpio;
}

struct xxx_dev xxx;

static struct file_operation xxx_fops ={
	.owner = THIS_MODULE,
    .open  = xxx_open,
    .write = xxx_write,
    .release = xxx_release,
    .read  = xxx_read,
};

第三步获取相关设备节点

//获取设备节点
xxx.nd = of_find_node_by_path("path");
//例子:beep.nd = of_find_node_by_path("/beep");
//获取设备树的GPIO属性,得到设备使用的GPIO编码
xxx.xxx_gpio =
of_get_named_gpio(xxx.nd,"propname",0);
/*
例子:beep.beep_gpio = 
of_get_named_gpio(beep.nd,"beep-gpio",0)
*/
//"beep-gpio"是指BEEP设备节点中beep-gpio     = <&gpio5 1 GPIO_ACTIVE_HIGH>;
ret =gpio_direction_output(xxx.xxx_gpio,1)

第四步:注册字符设备驱动

if(xxx.major){
	xxx.devid = MKDEV(xxx.major,0)
	register_chrdev_region
        (xxx.devid,xxx_CNT,XXX_NAME);
}else{
	alloc_chrdev_region                     		 			(&xxx.devid,0,xxx_CNT,xxx_NAME);
	xxx.major = MAJOR(xxx.devid);
	xxx.minor = MINOR(xxx.devid);
}

第五步:初始化cdev,添加cdev,class,设备

cdev_init(&xxx.cdev,&xxx_fops);

cdev_add(&xxx.cdev,xxx_devid,xxx_CNT);

xxx.class = class_create(THIS_MODULE,xxx_NAME);

XXX.device = device_create
    (xxx.class,NULL,XXX.devid,NULL,XXX_NAME);


第六步.编写文件操作函数

static int xxx_open(struct inode *inode,struct file *filp)
    
static ssize_t xxx_write(struct file *filp,const char __user *buf,size_t cnt,loff_t *offt)
    
static int xxx_release(struct inode *inode ,struct file *filp)
    

第七步.编写驱动出口函数

cdev_del(&xxx.cdev);
unregister_chrdev_region(xxx.devid,xxx_CNT);
device_destroy(xxx.class,xxx.devid);
class_destroy(xxx.class)

第八步 开源

MODULE_LICENSE(“GPL”)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值