设备树下的字符设备驱动框架
设备树下的字符设备驱动框架
没有引入设备树时,相关寄存器物理地址是直接定义在驱动文件中的,通过地址映射成为虚拟地址后,再操作虚拟地址完成GPIO的初始化。设备树的本质也是操作寄存器,只不过寄存器的相关信息放在了设备树中,配置寄存器时使用OF函数从设备树中读取寄存器数据后再进行配置
下图为设备树下的字符设备驱动框架图:
接下来根据上面的框架图,以驱动LED (GPIO1_IO03)为例,分步介绍具体的代码编写流程
1. 修改设备树文件
在内核源码的/arch/arm/boot/dts/文件夹中复制一份官方I.MX6ULL EVK EMMC版的设备树文件imx6ull-14x14-evk-emmc.dts,并自定义文件名,此处重命名为了imx6ull-andyxi-emmc.dts,在根节点中添加LED设备节点
andyxiled {#address-cells = <1>; /*reg中起始地址占用一个字长*/#size-cells = <1>; /*reg中地址长度占用一个字长*/compatible = "andyxi-led";status = "okay";reg = < 0X020C406C 0x04 /*CCM_CCGR1_BASE*/ 0X020E0068 0x04 /*SW_MUX_GPIO1_IO03_BASE*/0X020E02F4 0x04 /*SW_PAD_GPIO1_IO03_BASE*/0X0209C000 0x04 /*GPIO1_DR_BASE*/0X0209C004 0x04 >; /*GPIO1_GDIR_BASE*/
};
设备树修改完成后,在内核源码的根目录下执行make命令编译设备树
make dtbs #编译设备树
make imx6ull-andyxi-emmc.dtb #单独编译指定设备树
编译完成后,使用新的设备树启动Linux内核,之后可进入/proc/device-tree文件夹查看dtsled节点是否存在
#启动Linux系统后,在开发板中查看节点
cd /proc/device-tree #查看andyxiled节点是否存在
2. 编写驱动程序
创建驱动程序文件dtsled.c,添加如下代码
⏩ 宏定义及设备结构体定义
#define DTSLED_CNT 1 //设备号个数
#define DTSLED_NAME "dtsled" //名字
#define LEDOFF 0 //关灯
#define LEDON 1 //开灯
/* 映射后的寄存器虚拟地址指针 */
static void __iomem *IMX6U_CCM_CCGR1;
static void __iomem *SW_MUX_GPIO1_IO03;
static void __iomem *SW_PAD_GPIO1_IO03;
static void __iomem *GPIO1_DR;
static void __iomem *GPIO1_GDIR;
/* dtsled 设备结构体 */
struct dtsled_dev{dev_t devid; //设备号struct cdev cdev; //cdevstruct class *class; //类struct device *device; //设备int major; //主设备号int minor; //次设备号struct device_node *nd; //设备节点
};struct dtsled_dev dtsled; //led设备
⏩ 编写设备操作函数:设备操作函数和LED开关函数,具体代码可参考Linux点灯一文相关部分
⏩ 驱动入口函数中:使用OF函数获取设备树中的属性值,并初始化
static int __init led_init(void) { u32 val = 0; int ret; u32 regdata[14]; const char *str; struct property *proper; /* 获取设备树中的属性数据 */ /* 1、获取设备节点:andyxiled */ dtsled.nd = of_find_node_by_path("/andyxiled"); if(dtsled.nd == NULL) { printk("andyxiled node can not found!\r\n"); return -EINVAL; } else { printk("andyxiled node has been found!\r\n"); } /* 2、获取compatible属性内容 */ proper = of_find_property(dtsled.nd, "compatible", NULL); if(proper == NULL) { printk("compatible property find failed\r\n"); } else { printk("compatible = %s\r\n", (char*)proper->value); } /* 3、获取status属性内容 */ ret = of_property_read_string(dtsled.nd, "status", &str); if(ret < 0){ printk("status read failed!\r\n"); } else { printk("status = %s\r\n",str); }/* 4、获取reg属性内容 */ ret = of_property_read_u32_array(dtsled.nd, "reg", regdata, 10); if(ret < 0) { printk("reg property read failed!\r\n"); } else { u8 i = 0; printk("reg data:\r\n"); for(i = 0; i < 10; i++) printk("%#X ", regdata[i]); printk("\r\n"); }/* 初始化LED */
#if 0 /* 1、寄存器地址映射 */ IMX6U_CCM_CCGR1 = ioremap(regdata[0], regdata[1]); SW_MUX_GPIO1_IO03 = ioremap(regdata[2], regdata[3]); SW_PAD_GPIO1_IO03 = ioremap(regdata[4], regdata[5]); GPIO1_DR = ioremap(regdata[6], regdata[7]); GPIO1_GDIR = ioremap(regdata[8], regdata[9]);
#else IMX6U_CCM_CCGR1 = of_iomap(dtsled.nd, 0); SW_MUX_GPIO1_IO03 = of_iomap(dtsled.nd, 1); SW_PAD_GPIO1_IO03 = of_iomap(dtsled.nd, 2); GPIO1_DR = of_iomap(dtsled.nd, 3); GPIO1_GDIR = of_iomap(dtsled.nd, 4);
#endif /* 2、使能GPIO1时钟 */ val = readl(IMX6U_CCM_CCGR1); val &= ~(3 << 26); //之前的设置val |= (3 << 26); //设置新值writel(val, IMX6U_CCM_CCGR1); /* 3、设置GPIO1_IO03复用功能,并设置IO属性 */ writel(5, SW_MUX_GPIO1_IO03); writel(0x10B0, SW_PAD_GPIO1_IO03); /* 4、设置GPIO1_IO03为输出功能 */ val = readl(GPIO1_GDIR); val &= ~(1 << 3); //之前的设置 val |= (1 << 3); //设置为输出writel(val, GPIO1_GDIR); /* 5、默认关闭LED */ val = readl(GPIO1_DR); val |= (1 << 3); writel(val, GPIO1_DR);
⏩ 驱动入口函数中:注册字符设备驱动,代码与Linux点灯一文中的一样
⏩ 驱动出口函数中:注销设备驱动,删除类和设备,代码可参考Linux点灯一文
3. 编写测序程序
实现操作驱动文件对外设进行控制的功能。创建测试程序文件dtsledApp.c,代码内容与Linux点灯一文中的测试程序代码一致,此处不再赘述
4. 编译测试
⏩ 编译驱动程序:当前目录下创建Makefile文件,并make编译
KERNELDIR := /home/andyxi/linux/kernel/linux-imx-rel_imx_4.1.15_2.1.0_ga_andyxi
CURRENT_PATH := $(shell pwd)
obj-m := dtsled.obuild: kernel_moduleskernel_modules:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) modules
clean:
$(MAKE) -C $(KERNELDIR) M=$(CURRENT_PATH) clean
⏩ 编译测试程序:无需内核参与,直接编译即可
arm-linux-gnueabihf-gcc dtsledApp.c -o dtsledApp
⏩ 运行测试:拷贝驱动模块和测试程序到开发板,启动开发板,加载驱动模块后,使用应用程序测试驱动是否正常工作
depmod #第一次加载驱动的时候需运行此命令
modprobe dtsled.ko #加载驱动
./dtsledApp /dev/dtsled 1 #打开LED灯
./dtsledApp /dev/dtsled 0 #关闭LED灯
rmmod dtsled.ko #卸载驱动模块
设备树下的字符设备驱动框架相关推荐
- I.MX6ULL ARM驱动开发---设备树下的platfrom设备驱动
引言 最新的 Linux 内核已经支持了设备树,因此在设备树下如何编写 platform 驱动就显得尤为重要,本章我们就来学习一下如何在设备树下编写 platform 驱动. 一.设备树下的 pl ...
- 设备树下的platform 驱动编写
目录 设备树下的platform 驱动简介 硬件原理图分析 实验程序编写 修改设备树文件 platform 驱动程序编写 编写测试APP 运行测试 编译驱动程序和测试APP 运行测试 上一章我们详细的 ...
- 【正点原子MP157连载】第三十五章 设备树下的platform驱动编写-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- Linux 有/无设备树下 platform_driver 驱动框架
文章目录 platform 驱动框架 platform 设备框架 有设备树下驱动开发注意事项 宏___一行代码创建 platform_driver platform 驱动框架 首先,定义一个 plat ...
- 设备树下字符设备驱动
设备树下字符设备驱动 一.在设备树里添加自己的节点 二.驱动代码 三.makefile 四.应用层代码 运行测试 总结 一.在设备树里添加自己的节点 alphaled { 2 #address-cel ...
- 设备树下的 platform 驱动开发框架
1. 设备树下的platform驱动开发 platform驱动框架分为总线.设备和驱动,其中总线是由Linux内核提供,在编写驱动时只要关注于设备和驱动的具体实现即可.Linux下的platform驱 ...
- Linux 设备树下的 platform 驱动实验基于正点原子IMX6ULL开发板
1 设备树下的 platform 驱动简介 platform 驱动框架分为总线.设备和驱动,其中总线不需要我们这些驱动程序员去管理,这个是 Linux 内核提供的,我们在编写驱动的时候只要关注于设备和 ...
- Linux 设备树下的 platform 驱动示例
1.简介 基于总线.设备和驱动这样的驱动框架,Linux 内核提出来 platform 这个虚拟总线,相应的也有 platform 设备和 platform 驱动. Linux 总线设备和驱动模式 2 ...
- 设备树下的platform驱动编写
文章目录 一.设备树下的platform驱动简介 1.在设备树中创建设备节点 2.编写 platform 驱动的时候要注意兼容属性 3.编写platform驱动 二.硬件原理图分析 三.实验程序编写 ...
最新文章
- 展望未来,总结过去10年的程序员生涯,给程序员小弟弟小妹妹们的一些总结性忠告...
- 成功解决ImportError: Missing optional dependency ‘fastparquet‘. fastparquet is required for parquet supp
- Python:matplotlib绘图
- 汉三水属国(北地属国、安定属国)
- poj 1060 Modular multiplication of polynomials
- Telnet远程访问思科交换机、路由器
- Android input keyevent
- python tab和空格混用_Python编程常见十大错误,看完你自己都笑了!
- mysql fixed数据类型_fixed数据类型
- 电子信息系统机房设计规范
- 群控源码源代码,微群控系统源码的实现原理,核心源码实现 核心框架,可二次开发
- npy/npz/pkl/csv长字符串存储
- python练习题003:圆的面积
- 2022-03微软漏洞通告
- linux csv乱码,CSV格式文件中文乱码问题解决
- 闪付卡(QuickPass)隐私泄露原理
- vc6.0是c语言吗,vc6.0我二级报的是C语言,听说现在C语 – 手机爱问
- 物资学院、草房、常营点过的外卖总结
- 算法梳理(二)逻辑回归算法梳理
- hightcharts-vue 蜡烛图 股票绘图 candlestick
热门文章
- 中山大学学报(自然科学版)Latex模板(非官方)
- 如何对项目的研发团队年终绩效考核?
- 【电影】英国男演员杠把子
- Fabric-samples开发模式下chaincode操作流程及错误锦集
- RAR Extractor - The Unarchiver Pro for mac(解压缩软件)v6.3.5激活版
- VPP使用介绍(route、tun、memif、abf)
- php 判断号码运营商,PHP根据手机号判断运营商(详细介绍附代码)
- openssl:Can‘t load /home/test/.rnd into RNG
- Python中关于浮点数运算的不确定尾数的解释
- 解决MAC下MySQL忘记初始密码的方法