设备树实践操作

news2024/11/18 17:45:36

目录

  • 一、使用设备树给DM9000网卡_触摸屏指定中断
    • 1、修改方法
    • 2、实验方法
  • 二、在设备树中时钟的简单使用
    • 1、参考文档
    • 2、知识讲解
  • 三、在设备树中pinctrl的简单使用
    • 1、几个概念
    • 2、设备树中pinctrl节点
    • 3、platform_device, platform_driver匹配
    • 4、驱动中想选择、设置某个状态的引脚
  • 四、使用设备树给LCD指定各种参数
    • 1、实验方法
    • 2、细节分析

一、使用设备树给DM9000网卡_触摸屏指定中断

1、修改方法

   (1)根据设备节点的compatible属性, 
   (2)在驱动程序中构造/注册 platform_driver,
   (3)在 platform_driver 的 probe 函数中获得中断资源

2、实验方法

(1)以下是修改好的代码与之前的变化:
dm9dev9000c.c
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
下面的是改动后新增部分(原本是没有的),放在代码文件最后即可:

//下面部分的代码,简单来说就是原有的网络设备驱动的基础上又增加了一层封装
//使用总线设备驱动模型,从而使用设备树描述的硬件资源
static int dm9000drv_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;		
	struct device_node *dp_node = dev->of_node;
	struct resource		*res;
	int i;

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res) {
		irq = res->start;
		printk("get dm9000 irq %d\n", irq);
	}
	else {
		printk("can not get irq res for dm9000\n");
		return -1;
	}
	

	return dm9000c_init();
}

static int dm9000drv_remove(struct platform_device *pdev)
{
	dm9000c_exit();
	return 0;
}


static const struct of_device_id of_match_dm9000[] = {
	{ .compatible = "davicom,dm9000", .data = NULL },
	{ /* sentinel */ }
};


struct platform_driver dm9000_drv = {
	.probe		= dm9000drv_probe,
	.remove		= dm9000drv_remove,
	.driver		= {
		.name	= "dm9000",
		.of_match_table = of_match_dm9000, /* 能支持哪些来自于dts的platform_device */
	}
};


static int dm9000drv_init(void)
{
	platform_driver_register(&dm9000_drv);
	return 0;
}

static void dm9000drv_exit(void)
{
	platform_driver_unregister(&dm9000_drv);
}



module_init(dm9000drv_init);
module_exit(dm9000drv_exit);
MODULE_LICENSE("GPL");

s3c_ts.c
在这里插入图片描述
在这里插入图片描述
下面的是改动后新增部分(原本是没有的),放在代码文件最后即可:

static int s3cts_drv_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;		
	struct device_node *dp_node = dev->of_node;
	struct resource		*res;
	int i;

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	if (res) {
		irq_tc = res->start;
		printk("get touchscreen's tc irq %d\n", irq_tc);
	}
	else {
		printk("can not get irq res for touchscreen's tc\n");
		return -1;
	}

	res = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	if (res) {
		irq_adc = res->start;
		printk("get touchscreen's adc irq %d\n", irq_adc);
	}
	else {
		printk("can not get irq res for touchscreen's adc\n");
		return -1;
	}

	return s3c_ts_init();
}

static int s3cts_drv_remove(struct platform_device *pdev)
{
	s3c_ts_exit();
	return 0;
}

static const struct of_device_id of_match_s3cts[] = {
	{ .compatible = "jz2440,ts", .data = NULL },
	{ /* sentinel */ }
};

struct platform_driver s3cts_drv = {
	.probe		= s3cts_drv_probe,
	.remove		= s3cts_drv_remove,
	.driver		= {
		.name	= "s3c_ts",
		.of_match_table = of_match_s3cts, /* 能支持哪些来自于dts的platform_device */
	}
};

static int s3cts_drv_init(void)
{
	platform_driver_register(&s3cts_drv);
	return 0;
}

static void s3cts_drv_exit(void)
{
	platform_driver_unregister(&s3cts_drv);
}

module_init(s3cts_drv_init);
module_exit(s3cts_drv_exit);
MODULE_LICENSE("GPL");

(2)将修改后的文件放置到内核如下目录:

drivers/net/ethernet/davicom
drivers/input/touchscreen
a. 编译内核
b. 使用新的uImage启动
c. 测试网卡:
ifconfig eth0 192.168.1.101
ping 192.168.1.1
d. 测试触摸屏:
hexdump /dev/evetn0 // 然后点击触摸屏

hexdump命令看任何文件的十六进制编码,一般看“二进制”文件。

(3)本部分完整代码链接如下:

6课第1节_网卡_触摸屏驱动
https://www.aliyundrive.com/s/MgCwdpYGwFL
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,
视频原画倍速播放。

二、在设备树中时钟的简单使用

1、参考文档

内核 Documentation/devicetree/bindings/clock/clock-bindings.txt
内核 Documentation/devicetree/bindings/clock/samsung,s3c2410-clock.txt

在这里插入图片描述

2、知识讲解

(1)设备树中定义了各种时钟, 在文档中称之为"Clock providers", 比如:

clocks: clock-controller@4c000000 {
	compatible = "samsung,s3c2440-clock";
	reg = <0x4c000000 0x20>;
	#clock-cells = <1>; // 想使用这个clocks时要提供1个u32来指定它, 比如选择这个clocks中发出的LCD时钟、PWM时钟
};

(2) 设备需要时钟时, 它是"Clock consumers", 它描述了使用哪一个"Clock providers"中的哪一个时钟(id), 比如:

fb0: fb@4d000000{
    compatible = "jz2440,lcd";
    reg = <0x4D000000 0x60>;
    interrupts = <0 0 16 3>;
    clocks = <&clocks HCLK_LCD>;  // 使用clocks即clock-controller@4c000000中的HCLK_LCD		
};

(3)驱动中获得/使能时钟:

// 确定时钟个数
int nr_pclks = of_count_phandle_with_args(dev->of_node, "clocks",
					"#clock-cells");
// 获得时钟
for (i = 0; i < nr_pclks; i++) {
	struct clk *clk = of_clk_get(dev->of_node, i);
}

// 使能时钟
clk_prepare_enable(clk);

// 禁止时钟
clk_disable_unprepare(clk);

三、在设备树中pinctrl的简单使用

文档:
内核 Documentation/devicetree/bindings/pinctrl/samsung-pinctrl.txt

1、几个概念

Bank: 以引脚名为依据, 这些引脚分为若干组, 每组称为一个Bank
      比如s3c2440里有GPA、GPB、GPC等Bank,
      每个Bank中有若干个引脚, 比如GPA0,GPA1, ..., GPC0, GPC1,...等引脚

Group: 以功能为依据, 具有相同功能的引脚称为一个Group
       比如s3c2440中串口0的TxD、RxD引脚使用 GPH2,GPH3, 那这2个引脚可以列为一组
       比如s3c2440中串口0的流量控制引脚使用 GPH0,GPH1, 那这2个引脚也可以列为一组

State: 设备的某种状态, 比如内核自己定义的"default","init","idel","sleep"状态;
       也可以是其他自己定义的状态, 比如串口的"flow_ctrl"状态(使用流量控制)
	   
	   设备处于某种状态时, 它可以使用若干个Group引脚

2、设备树中pinctrl节点

a.1 它定义了各种 pin bank, 比如s3c2440有GPA,GPB,GPC,...,GPB各种BANK, 每个BANK
中有若干引脚:
	pinctrl_0: pinctrl@56000000 {
		reg = <0x56000000 0x1000>;

		gpa: gpa {
			gpio-controller;
			#gpio-cells = <2>;  /* 以后想使用gpa bank中的引脚时, 需要2个u32来指定引脚 */
		};

		gpb: gpb {
			gpio-controller;
			#gpio-cells = <2>;
		};

		gpc: gpc {
			gpio-controller;
			#gpio-cells = <2>;
		};

		gpd: gpd {
			gpio-controller;
			#gpio-cells = <2>;
		};
	};

在这里插入图片描述

a.2 它还定义了各种group(组合), 某种功能所涉及的引脚称为group,
    比如串口0要用到2个引脚: gph0, gph1:

	uart0_data: uart0-data {
		samsung,pins = "gph-0", "gph-1";
		samsung,pin-function = <2>;   /* 在GPHCON寄存器中gph0,gph1可以设置以下值:
		                                     0 --- 输入功能
		                                     1 --- 输出功能
		                                     2 --- 串口功能
										  我们要使用串口功能,  
										  samsung,pin-function 设置为2
        	                           */
	};

	uart0_sleep: uart0_sleep {
		samsung,pins = "gph-0", "gph-1";
		samsung,pin-function = <0>;   /* 在GPHCON寄存器中gph0,gph1可以设置以下值:
		                                     0 --- 输入功能
		                                     1 --- 输出功能
		                                     2 --- 串口功能
										  我们要使用输入功能,  
										  samsung,pin-function 设置为0
        	                           */
	};
a.3 设备节点中要使用某一个 pin group
serial@50000000 {
    ......
	pinctrl-names = "default", "sleep";  /* 既是名字, 也称为state(状态) */
	pinctrl-0 = <&uart0_data>;
	pinctrl-1 = <&uart0_sleep>;
};

pinctrl-names中定义了2种state: default 和 sleep,
default 对应的引脚是: pinctrl-0, 它指定了使用哪些pin group: uart0_data
sleep   对应的引脚是: pinctrl-1, 它指定了使用哪些pin group: uart0_sleep

3、platform_device, platform_driver匹配

  之前的文章中讲解过platform_device和platform_driver的匹配过程,
最终都会调用到 really_probe (drivers/base/dd.c)

really_probe:
	/* If using pinctrl, bind pins now before probing */
	ret = pinctrl_bind_pins(dev);
				dev->pins->default_state = pinctrl_lookup_state(dev->pins->p,
								PINCTRL_STATE_DEFAULT);  /* 获得"default"状态的pinctrl */
				dev->pins->init_state = pinctrl_lookup_state(dev->pins->p,
								PINCTRL_STATE_INIT);    /* 获得"init"状态的pinctrl */

				ret = pinctrl_select_state(dev->pins->p, dev->pins->init_state);    /* 优先设置"init"状态的引脚 */
				ret = pinctrl_select_state(dev->pins->p, dev->pins->default_state); /* 如果没有init状态, 则设置"default"状态的引脚 */
								
	......
	ret = drv->probe(dev);

所以: 如果设备节点中指定了pinctrl, 在对应的probe函数被调用之前, 先"bind pins", 即先绑定、设置引脚

4、驱动中想选择、设置某个状态的引脚

devm_pinctrl_get_select_default(struct device *dev);      // 使用"default"状态的引脚

pinctrl_get_select(struct device *dev, const char *name); // 根据name选择某种状态的引脚

pinctrl_put(struct pinctrl *p);   // 不再使用, 退出时调用		

四、使用设备树给LCD指定各种参数

参考文章:
让TQ2440也用上设备树(1):
http://www.cnblogs.com/pengdonglin137/p/6241895.html

参考代码: https://github.com/pengdonglin137/linux-4.9/blob/tq2440_dt/drivers/video/fbdev/s3c2410fb.c

1、实验方法

所使用全部源码:

6课第4节_LCD驱动
https://www.aliyundrive.com/s/AkFjPKLqWmJ
点击链接保存,或者复制本段内容,打开「阿里云盘」APP ,无需下载极速在线查看,
视频原画倍速播放。
a. 替换dts文件:"jz2440_irq.dts" 放入内核 arch/arm/boot/dts目录,

b. 替换驱动文件:"s3c2410fb.c" 放入内核 drivers/video/fbdev/ 目录,
修改 内核 drivers/video/fbdev/Makefile :
obj-$(CONFIG_FB_S3C2410)          += lcd_4.3.o
改为:
obj-$(CONFIG_FB_S3C2410)          += s3c2410fb.o

c. 编译驱动、编译dtbs:
export  PATH=PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/work/system/gcc-linaro-4.9.4-2017.01-x86_64_arm-linux-gnueabi/bin
cp config_ok  .config
make uImage   // 生成 arch/arm/boot/uImage
make dtbs     // 生成 arch/arm/boot/dts/jz2440_irq.dtb

d. 使用上述uImage, dtb启动内核即可看到LCD有企鹅出现

2、细节分析

设备树中的描述:

    fb0: fb@4d000000{
        compatible = "jz2440,lcd";
        reg = <0x4D000000 0x60>;
        interrupts = <0 0 16 3>;
        clocks = <&clocks HCLK_LCD>;   /* a. 时钟 */
        clock-names = "lcd";
        pinctrl-names = "default";     /* b. pinctrl */
        pinctrl-0 = <&lcd_pinctrl &lcd_backlight &gpb0_backlight>;
        status = "okay";

		/* c. 根据LCD引脚特性设置lcdcon5, 指定lcd时序参数 */
        lcdcon5 = <0xb09>;
        type = <0x60>;
        width = /bits/ 16 <480>;
        height = /bits/ 16 <272>;
        pixclock = <100000>;       /* 单位: ps, 10^-12 S,  */
        xres = /bits/ 16 <480>;
        yres = /bits/ 16 <272>;
        bpp = /bits/ 16 <16>;
        left_margin = /bits/ 16 <2>;
        right_margin =/bits/ 16  <2>;
        hsync_len = /bits/ 16 <41>;
        upper_margin = /bits/ 16 <2>;
        lower_margin = /bits/ 16 <2>;
        vsync_len = /bits/ 16 <10>;
    };

&pinctrl_0 {
	gpb0_backlight: gpb0_backlight {
		samsung,pins = "gpb-0";
		samsung,pin-function = <1>;
		samsung,pin-val = <1>;
	};
};

代码中的处理:

a. 时钟:
info->clk = of_clk_get(dev->of_node, 0);
clk_prepare_enable(info->clk);

b. pinctrl:
代码中无需处理, 在 platform_device/platform_driver匹配之后就会设置"default"
状态对应的pinctrl

c. 根据LCD引脚特性设置lcdcon5, 指定lcd时序参数:

   直接读设备树节点中的各种属性值, 用来设置驱动参数

	of_property_read_u32(np, "lcdcon5", (u32 *)(&display->lcdcon5));
	of_property_read_u32(np, "type", &display->type);
	of_property_read_u16(np, "width", &display->width);
	of_property_read_u16(np, "height", &display->height);
	of_property_read_u32(np, "pixclock", &display->pixclock);
	of_property_read_u16(np, "xres", &display->xres);
	of_property_read_u16(np, "yres", &display->yres);
	of_property_read_u16(np, "bpp", &display->bpp);
	of_property_read_u16(np, "left_margin", &display->left_margin);
	of_property_read_u16(np, "right_margin", &display->right_margin);
	of_property_read_u16(np, "hsync_len", &display->hsync_len);
	of_property_read_u16(np, "upper_margin", &display->upper_margin);
	of_property_read_u16(np, "lower_margin", &display->lower_margin);
	of_property_read_u16(np, "vsync_len", &display->vsync_len);

注:本文章参考了《韦东山老师嵌入式课程》笔记,并结合了自己的实际开发经历以及网上他人的技术文章,综合整理得到。如有侵权,联系删除!水平有限,欢迎各位在评论区交流

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/374849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

ESP32设备驱动-BMI160惯性测量传感器驱动

BMI160惯性测量传感器驱动 BMI160 是一种高度集成的低功耗惯性测量单元 (IMU),可提供精确的加速度和角速率(陀螺仪)测量。 BMI160 集成: 16位数字,三轴加速度计16位数字,三轴陀螺仪BMI160特性: 高性能加速度计和陀螺仪(硬件同步) 极低功耗:typ.925A(加速度计和陀螺…

BIM小技巧丨关于如何在Revit明细表中显示门窗面积

在明细表中显示门窗面积(以门明细表为例)在新建一个门明细表后&#xff0c;可以发现在Revit中不能直接使用明细表统计门窗面积。 这时&#xff0c;可以通过使用添加“计算值”的方式来处理&#xff0c;得到如下图所示&#xff0c;两种不同的面积统计结果&#xff1a; 除此之外&…

Android 12 快速适配

Android 12 需要更新适配点并不多&#xff0c;本篇主要介绍最常见的两个需要适配的点&#xff1a;android:exported[1] 和 SplashScreen[2] 。一、android:exported它主要是设置 Activity 是否可由其他应用的组件启动&#xff0c; “true” 则表示可以&#xff0c;而“false”表…

满汉楼练习 马踏棋盘

1. 满汉楼 1.结构图 2. 数据库 pwd CHAR(32) NOT NULL DEFAULT ‘’,# 密码&#xff0c;32位 INSERT INTO employee VALUES(NULL, ‘666’, MD5(‘123456’), ‘老韩’, ‘经理’); MD5(‘123456’)是经过MD5加密过后的32位的字符串&#xff0c;用来保存密码 select * fro…

辉光管时钟学习制作及开源软硬件工程

文章目录前言开源地址辉光管项目介绍辉光管的工作条件硬件部分部分介绍充电电路驱动电路不足之处软件部分总结前言 作为一个电子人&#xff0c;一直想做一个辉光管时钟&#xff0c;算是大学的一个心愿&#xff0c;终于在快要毕业前做了一个&#xff0c;下面把软件和硬件的部分…

Windows事件日志监控

大多数数据泄露属内部人员而为&#xff0c;但各企业在监控内部网络活动方面仍存在不足。无论是大型还是小型企业&#xff0c;监控内部网络活动已成为其主要要求。要保护网络安全以防范泄露和威胁&#xff0c;各企业需要采取积极的措施来保证其网络和数据的安全性。监控事件日志…

NCRE计算机等级考试Python真题(四)

第四套试题1、以下选项中&#xff0c;不属于需求分析阶段的任务是&#xff1a;A.需求规格说明书评审B.确定软件系统的性能需求C.确定软件系统的功能需求D.制定软件集成测试计划正确答案&#xff1a; D2、关于数据流图&#xff08;DFD&#xff09;的描述&#xff0c;以下选项中正…

跨境人都在用的指纹浏览器到底有什么魔力?三分钟带你了解透彻

什么是指纹浏览器&#xff1f;这是东哥近期收到最多的粉丝私信咨询&#xff0c;指纹两个字大家都很熟悉&#xff0c;指纹浏览器就变得陌生起来。之前东哥也跟大家分享过很多次指纹浏览器的用法&#xff0c;鉴于还是很多人不认识这个好用的工具&#xff0c;东哥今天就来详细给大…

【ICCV2022】 CAPAO:一种高效的单阶段人体姿态估计模型

CAPAO&#xff1a;一种高效的单阶段人体姿态估计模型 重新思考关键点表示&#xff1a;将关键点和姿态建模作为多人姿态估计的对象&#xff08;Rethinking Keypoint Representations: Modeling Keypoints and Poses as Objects for Multi-Person Human Pose Estimation&#xf…

k8s学习之路 | Day16 k8s 中的容器初探

文章目录容器镜像镜像名称镜像拉取策略私有仓库的拉取策略容器的环境变量和启动命令容器的环境变量容器的启动命令容器的生命周期钩子postStartpreStop容器的探针startupProbelivenessProbereadinessProbek8s 集群中最小的管理单元就是一个Pod&#xff0c;而Pod里面才是容器&am…

linux下devmem访问物理寄存器MT7621 mdio控制

在同专栏的mdio访问phy的三种方式篇&#xff0c;我们着重介绍了通过ioctrl的方式将mdio总线与网卡绑定进行访问&#xff0c;但是实时上数据接口和管理接口可以独立去控制&#xff0c;很不幸&#xff0c;作者现在必须把mdio与网卡解除绑定并独立操控&#xff0c;因此接下来将详细…

【elementUI】基于elementUI自定义封装分页内容

文章目录前端分页的封装后端进行分页的封装&#xff0c;利用el-pagination网页获取数据进行分页主要有前端分页和后端分页&#xff0c;对于数据量较小的数据&#xff0c;可以使用前端分页进行实现。但是一般的分页都是后端获取分页实现前端分页的封装 思路&#xff1a; 1.假设一…

Mybatis源码学习笔记(五)之Mybatis框架缓存机制原理解析

1 Mybatis框架的缓存模块 MyBatis 内置了一个强大的事务性查询缓存机制&#xff0c;它可以非常方便地配置和定制。Mybatis框架中的缓存分为一级缓存和二级缓存&#xff0c;三级缓存基本都要借助自定义缓存或第三方服务来进行实现。但本质上是一样的&#xff0c;都是借助Cache接…

只会手工测试,裸辞后怎么才能找到工作

我们可以从以下几个方面来具体分析下&#xff0c;想通了&#xff0c;理解透了&#xff0c;才能更好的利用资源提升自己。 一、我会什么&#xff1f; 先说第一个我会什么&#xff1f;第一反应&#xff1a;我只会功能测试&#xff0c;在之前的4年的中我只做了功能测试。内心存在…

如何改变照片的大小kb?照片怎么改到100kb?

在平时的日常工作生活当中&#xff0c;我们都会遇到需要上传照片的情况&#xff0c;但是随着拍摄的照片越来越清晰照片体积也越来越大&#xff0c;很容易遇到图片太大上传不成功的情况&#xff0c;那么这时候应该怎么办呢&#xff1f;今天来给大家分享一款照片压缩器&#xff0…

TCP/IP协议,网络工程部分

这个博客参考了许多up主的视频和网上其他的博主的文章&#xff0c;还有我老师的ppt 这里是目录一、osi七层模型&#xff08;参考模型&#xff09;1.物理层2.数据链路层&#xff08;数据一跳一跳进行传递&#xff09;3.网络层&#xff08;端到端传输&#xff09;4.传输层&#x…

synchronized底层如何实现?什么是锁的升级、降级?

第16讲 | synchronized底层如何实现&#xff1f;什么是锁的升级、降级&#xff1f; 我在上一讲对比和分析了 synchronized 和 ReentrantLock&#xff0c;算是专栏进入并发编程阶段的热身&#xff0c;相信你已经对线程安全&#xff0c;以及如何使用基本的同步机制有了基础&#…

Web Spider案例 网洛者 第一题 JS混淆加密 - 反hook操作 练习(五)

文章目录一、资源推荐二、第一题 JS混淆加密 - 反hook操作2.1 过控制台反调试(debugger)2.2 开始逆向分析三、python具体实现代码四、记录一下&#xff0c;execjs调用混淆JS报错的问题总结提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、资源推荐 …

Echarts 实现电池效果的柱状图

第022个点击查看专栏目录本示例是解决显示电池电量状态的柱状图&#xff0c;具体的核心代码请参考源代码。 文章目录示例效果示例源代码&#xff08;共102行&#xff09;相关资料参考专栏介绍示例效果 示例源代码&#xff08;共102行&#xff09; /* * Author: 还是大剑师兰特…

aws ecs 使用application autoscaling自动扩缩ecs服务

参考资料 https://aws.amazon.com/cn/blogs/china/microservices-on-amazon-ecs-1/ https://aws.amazon.com/cn/blogs/china/microservices-on-amazon-ecs-2/ https://zhuanlan.zhihu.com/p/355383555 https://docs.amazonaws.cn/en_us/AmazonECS/latest/developerguide/ser…