Linux驱动之设备树(设备树下的LED驱动实验)
概念
Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设备树配置,当需要改变波特率时,就不用修改驱动,直接修改配置文件则可。
设备树源文件扩展名为.dts(device tree source),一般放置在内核的"arch/arm/boot/dts/"目录内。设备树源文件的通用部分用.dtsi文件描述,一般用于描述SOC的内部外设信息,如CPU架构,主频等。差异部分用.dts文件描述,一般用于描述设备上的其它设备,如IIC设备,SPI设备。
dts基本语法
设备节点:dts文件中描述一个设备信息的内容。比如IIC0。
根节点:设备树文件开头会有’/’就是根节点,每个设备树文件只有一个根节点,
每个节点都有一堆属性,有的可以用户自定义,有的为标准属性。
compatible:“兼容性”属性,用于将设备和驱动绑定起来,一般驱动程序都会有一个OF匹配,匹配相等,则可使用这个驱动。
module:属性也是字符串,描述模块信息,如名字什么的。
status:设备状态,可以是“okey”、“disable”,“fail”、“fail-sss”
reg:一般reg都是和地址相关的内容,起始地址和地址长度。
#address-cells:描述reg属性中的起始地址占用字长。
#size-cells:描述reg属性中的地址长度所占用的字长。
举例:
apb {compatible = "simple-bus";#address-cells = <1>; //父节点的起始地址字长1,即uart0的reg属性中,第一个字为起始地址。#size-cells = <1>;//父节点的地址长度字长为1。ranges;uart0: serial@f0024000 {//节点标签:节点名@设备地址或者寄存器首地址compatible = "atmel,at91sam9260-usart";//<厂商,驱动名>reg = <0xf0024000 0x100>;//uart0寄存器的起始地址为0xf002c000,可以在SOC的datasheet中查看到。interrupts = <16 IRQ_TYPE_LEVEL_HIGH 5>;pinctrl-names = "default";pinctrl-0 = <&pinctrl_uart0>;clocks = <&uart0_clk>;clock-names = "usart";status = "disabled";//状态为disable};
根节点中有两个特殊节点aliases(别名)和chosen。
设备树在系统中的体现
在根文件系统中/proc/device-tree目录下,包括根节点’/’的所有属性和子节点。
在设备树存放目录arch/arm/boot/dts/中搜索model内容,可以找到对应的.dts文件入口。可以看到model和compatible的属性值完全相同。
设备树和datasheet对应
以下以调试串口打印配置为例,学习如何查看设备树和datasheet如何对应的。
① 通过原理图,可以知道调试串口连接的PB30和PB31.
② 在datasheet中,引脚功能描述,可以看到PB30和PB31功能为调试打印DBGU。
③ 在datasheet的”Memory Mapping”中,可以看到DBGU的起始地址0Xffff ee00
④ 从上一章节知道设备树的入口文件为”sama5d34ek.dts”,在“sama5d34ek.dts”文件中#include了很多dtsi文件。
⑤ 进入相应的.dtsi文件,可以找到相关dbgu的设备节点。可以看到里面描述的内容与datasheet一致。
⑥ 在系统中,也可以找到dbgu的相关信息
基于设备树驱动LED
大致可以分为三个步骤:
① 在.dts文件中创建相应的设备节点
② 编写驱动,获取设备树中的属性值
③ 使用获取的属性值初始化LED所使用的GPIO。
一.根节‘/’下创建子节点
添加内容如下:
boyee_led{#address-cells = <1>;#size-cells = <1>;compatible = "boyee-led";status = "okay";reg = <0Xfffff600 0x200>;//PIOC的基地址};
二.编译.dts生成.dtb
在内核根目录下执行make dtbs,编译生成新的.dtb。或者执行make,也会对更改过的dtbs进行重新编译。然后使用新的.dtb启动linux内核。
三.驱动编写
提取设备节点的属性,linux内核中使用device_node结构体来描述一个节点,此结构体定义在文件include/linux/of.h中。
查找节点有关的OF函数(获取设备节点属性函数都以of_开头)有5个:
of_find_node_by_name:通过节点名字查找指定的节点。
of_find_nade_by_type:通过device_type属性查找指定的节点。
of_find_compatible_node:根据device_type和compatibe两个属性查找指定的节点。
of_find_matching_node_and_match:通过of_device_id查找指定节点。
of_find_node_by_path:通过路径来查找指定的节点。
#include <linux/fs.h> /*包含file_operation结构体*/
#include <linux/init.h>/* 包含module_init module_exit */
#include <linux/module.h>/* 包含LICENSE的宏 */
#include <linux/miscdevice.h>/*包含miscdevice结构体*/
#include <linux/io.h>/*包含ioremap等操作函数*/
#include <linux/kernel.h>/*包含printk等操作函数*/
#include <linux/of.h>/*设备树操作相关的函数*//**************宏定义***************/
#define PIO_SODR (*(volatile unsigned long *)(virt_addr +0x0030))
#define PIO_CODR (*(volatile unsigned long *)(virt_addr +0x0034))
#define PIO_PER (*(volatile unsigned long *)(virt_addr +0x0000))
#define PIO_MDDR (*(volatile unsigned long *)(virt_addr +0x0054))
#define PIO_OER (*(volatile unsigned long *)(virt_addr +0x0010))
#define PIO_OWDR (*(volatile unsigned long *)(virt_addr +0x00A4))/*
#define PIO_PDSR (*(volatile unsigned long *)(virt_addr +0x003C))
#define PIO_ODR (*(volatile unsigned long *)(virt_addr +0x0014))
#define PIO_PUER (*(volatile unsigned long *)(virt_addr +0x0064))
#define PIO_PUDR (*(volatile unsigned long *)(virt_addr +0x0060 ))
#define PIO_PPDER (*(volatile unsigned long *)(virt_addr +0x0094))
*/#define LED2 1 << 29
#define LED1 1 << 26
#define LED_ON 1
#define LED_OFF 0
#define LED1_CTL 5
#define LED2_CTL 6
/**************内部变量***************/
unsigned long virt_addr;/* 定义一个打开设备的,open函数 */
static int led_open(struct inode *inode,struct file *file)
{return 0;
}/* 定义一个打开设备的,ioctl函数 */
static long led_ioctl(struct file *file,unsigned int data,unsigned long arg)
{switch(data){case LED1_CTL:if(arg == LED_ON){PIO_SODR |= LED1;/*对芯片寄存器IO操作*/}else{PIO_CODR |= LED1;}break;case LED2_CTL:if(arg == LED_ON){PIO_SODR |= LED2;}else{PIO_CODR |= LED2;}break;default:break;}return 0;
}
/*字符设备驱动程序就是为具体硬件的file_operations结构编写各个函数*/
static const struct file_operations led_ctl={.owner = THIS_MODULE,.unlocked_ioctl = led_ioctl,.open = led_open,
};/*杂项设备,主设备号为10的字符设备,相对普通字符设备,使用更简单*/
static struct miscdevice led_miscdev = {.minor = 255,.name = "led_ctl",.fops = &led_ctl,
};static int __init led_init(void)
{int res;struct device_node *led_nd;//设备节点struct property *proper;unsigned int regdata[2];char str[30];/*获取设备树中的属性数据*//*1.获取设备节点:boyee_led*/led_nd = of_find_node_by_path("/boyee_led");if(led_nd == NULL){printk("boyee_led node not find\r\n");}else{printk("boyee_led node find\r\n");}/*2.获取compatible属性内容*/proper = of_find_property(led_nd,"compatible",NULL);if(proper == NULL){printk("compatible property find failed\r\n");}else{printk("compatible =%s\r\n",(char *)proper->value);}/*3.获取status属性内容*/res = of_property_read_string(led_nd,"status",&str);if(res < 0){printk("status read failed\r\n");}else{printk("status =%s\r\n",str);}/*4.获取reg属性内容*/res = of_property_read_u32_array(led_nd,"reg",regdata,2);if(res <0 ){printk("reg property read failed\r\n");}else{printk("regdata[0]=%x\r\n",regdata[0]);printk("regdata[1]=%x\r\n",regdata[1]);}/*注册杂项设备驱动*/res = misc_register(&led_miscdev);printk(KERN_ALERT"led_init %d\n",res);/*通过物理地址,得到寄存器的虚拟地址*/virt_addr =(volatile unsigned long )ioremap(regdata[0],regdata[1]); /*对芯片寄存器操作,输出IO使能*/PIO_PER |= LED1 | LED2;PIO_MDDR |= LED1 | LED2;PIO_OER |= LED1 | LED2;PIO_OWDR |= LED1 | LED2;PIO_CODR |= LED1 | LED2;return res;
}static void __exit led_exit(void)
{/*释放杂项设备*/misc_deregister(&led_miscdev);/*取消虚拟地址映射*/iounmap((unsigned long *)virt_addr);printk(KERN_ALERT"led_exit\r\n");
}/*驱动模块的加载和卸载入口*/
module_init(led_init);
module_exit(led_exit);MODULE_LICENSE("GPL");
MODULE_AUTHOR("boyee");
MODULE_DESCRIPTION("control output led");
四.编译测试
编译驱动生成xx.ko,insmod驱动,编写测试APP、Makefile,运行测试APP,查看现象。
Linux驱动之设备树(设备树下的LED驱动实验)相关推荐
- 【正点原子Linux连载】第四十四章 设备树下的LED驱动实验 -摘自【正点原子】I.MX6U嵌入式Linux驱动开发指南V1.0
1)实验平台:正点原子阿尔法Linux开发板 2)平台购买地址:https://item.taobao.com/item.htm?id=603672744434 2)全套实验源码+手册+视频下载地址: ...
- linux uart寄存器 代替 printk,Linux驱动学习之设备树(设备树下的LED驱动实验),...
Linux驱动学习之设备树(设备树下的LED驱动实验), 概念 Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离.相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设 ...
- 【正点原子MP157连载】第二十四章 设备树下的LED驱动实验-摘自【正点原子】STM32MP1嵌入式Linux驱动开发指南V1.7
1)实验平台:正点原子STM32MP157开发板 2)购买链接:https://item.taobao.com/item.htm?&id=629270721801 3)全套实验源码+手册+视频 ...
- firefly-rk3288j开发板--设备树下的 LED 驱动
firefly-rk3288j开发板–设备树下的 LED 驱动 1 准备工作 开发板:aio-rk3288j SDK版本:rk3288_linux_release_20210304 下载工具:Linu ...
- STM32MP157驱动开发——设备树下的LED驱动
STM32MP157驱动开发--设备树下的LED驱动 主要内容:将之前章节中使用新设备设备驱动编写的LED驱动改成设备树形式 文章目录 STM32MP157驱动开发--设备树下的LED驱动 一.主要步 ...
- <Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动
<Linux开发>驱动开发 -之-基于pinctrl/gpio子系统的LED驱动 交叉编译环境搭建: <Linux开发> linux开发工具-之-交叉编译环境搭建 uboot移 ...
- 韦东山 IMX6ULL和正点原子_「正点原子Linux连载」第四十四章设备树下的LED驱动实验...
1)实验平台:正点原子Linux开发板 2)摘自<正点原子I.MX6U嵌入式Linux驱动开发指南> 关注官方微信号公众号,获取更多资料:正点原子 上一章我们详细的讲解了设备树语法以及在驱 ...
- I.MX6ULL ARM驱动开发---设备树下的LED驱动实验
一.什么是设备树? 设备树(Device Tree),将这个词分开就是"设备"和"树",描述设备树的文件叫做 DTS(Device Tree Source) ...
- linux显卡驱动安全模式,Win7怎么在安全模式下安装显卡驱动?
什么是显卡驱动?它是一种硬件所对应的软件,支持计算机与设备之间的通信,没有驱动程序,计算机的硬件就无法工作.下面我们就Win7系统下安装显卡驱动的一个案例与大家详细地分析一下. 案例分析: 最近安装了 ...
- 驱动技巧:如何在Win7下安装SATA驱动开启AHCI模式
问题描述:装win7的时候没有在AHCI模式下安装,而是在IDE模式下安装的,后来安装完毕以后想更改成AHCI模式,可是更改以后启动电脑蓝屏并重启. 解决方法: 如果是在IDE模式下安装的系统,由于在 ...
最新文章
- mesos+marathon平台搭建
- 【直播回放】中外大厂奇葩说:谁是技术圈的嘴炮王者?
- Linux环境变量中PS1
- java几点钟_实现 Java 本地缓存,该从这几点开始
- python 控件叠加_Python3 tkinter基础 Checkbutton anchor for生成多个控件并西对齐
- 快速迭代的开发方式中的QA实践方法
- html定义不同的类,定义不同的节点类型.html
- 时间复杂度o(n^0.5)_算法基础1.1:算法复杂度计算(二)
- ffmpeg屏幕推流
- Vue 之 下载本地资源文件
- 病毒周报(081208至081214)
- select用法详解
- 现在润新加坡是个好主意吗?
- 设计模式之策略模式(Strategy)
- 爱普生荣膺第十届制博会机器人类唯一奖项
- [1]: the default discovery settings are unsuitable for production use; at least one of [discovery.se
- 2022年在中国大陆通过Azure的学生认证方法指北
- 2021江西高考成绩查询入口已开通,2021年江西省高考成绩查询系统入口【官网】...
- 微信小程序input弹出键盘挡住文字的解决办法
- 计算机组装与维护课程课程介绍,有关计算机组装与维护课程的教学改革与实践...
热门文章
- 14.	Zigbee应用程序框架开发指南 - 睡眠设备
- VScode中使用platformIO开发,编译时找不到自己的源文件(报错信息:undefined reference to )
- DEVC++安装后编程运行时老是提示“源文件未编译”
- 最新最全的前端面试题集锦之 微信小程序 篇(从基础到高级)
- python语言的开题报告怎么写_开题报告怎么写
- 2022国开中国现代文学专题阶段作业2-4答案
- Android 多语言对照表
- Android 自动朗读TT
- C语言 --- sizeof() 7种使用详解
- 10年老司机倾囊相授,贴片晶振的PCB layout需要注意哪些?