Linux kernel下c语言解析dts

                        Linux kernel下c语言解析dts

 

一、inux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。相当于从驱动代码分离出来的配置文件,比如串口的波特率通过设备树配置,当需要改变波特率时,就不用修改驱动,直接修改配置文件则可。设备树源文件扩展名为.dts(device tree source),一般放置在内核的"arch/arm64/boot/dts/"目录内。设备树源文件的通用部分用.dtsi文件描述,一般用于描述SOC的内部外设信息,如CPU架构,主频等。差异部分用.dts文件描述,一般用于描述设备上的其它设备,如IIC设备,SPI设备。

 

二、kernel下c语言解析dts实例学习。

1、添加dts panel节点。

	panel: panel {
		compatible = "simple-panel";
		backlight = <&backlight>;
		power-supply = <&vcc_lcd>;
		enable-gpios = <&gpio1 13 GPIO_ACTIVE_HIGH>;
		prepare-delay-ms = <20>;
		enable-delay-ms = <20>;
		reg = <0Xff8ff600 0x800>;
		status = "disabled";
		rockchip,key_table =
			<0xFF	KEY_POWER>,
			<0xF4	KEY_MENU>,
			<0xF6	KEY_BACK>,
			<0xE9	KEY_HOME>,
			<0xF1	KEY_ENTER>,
			<0xEE	KEY_VOLUMEUP>,
			<0xEB	KEY_VOLUMEDOWN>,
			<0xE9	KEY_REPLY>,
			<0xF3	KEY_UP>,
			<0xEF	KEY_DOWN>,
			<0xF2	KEY_LEFT>,
			<0xF0	KEY_RIGHT>,
			<0xFA	KEY_PLAY>,
			<0xE6	KEY_PLAYCD>,			
			<0xE7	KEY_STOP>,			
			<0xEC	KEY_MUTE>,
			<0xE5	KEY_1>,
			<0xE4	KEY_2>,
			<0xE3	KEY_3>,
			<0xE2	KEY_4>,
			<0xE1	KEY_5>,
			<0xE0	KEY_6>,
			<0xBF	KEY_7>,
			<0xBE	KEY_8>,
			<0xBD	KEY_9>,
			<0xBB	KEY_0>,
			<0xE8	KEY_APPSELECT>,
			<0xBC	KEY_NUMERIC_STAR>,
			<0xBA	KEY_NUMERIC_POUND>,
			<0xB6	KEY_TRIGGER_DUALSCREEN>; 

		display-timings {
			native-mode = <&timing0>;

			timing0: timing0 {
				clock-frequency = <200000000>;
				//hactive = <1536>;
				//vactive = <2048>;
				hactive = <3840>;
				vactive = <2160>;
				//hactive = <1920>;
				//vactive = <1080>;
				hfront-porch = <12>;
				hsync-len = <16>;
				hback-porch = <48>;
				vfront-porch = <8>;
				vsync-len = <4>;
				vback-porch = <8>;
				hsync-active = <0>;
				vsync-active = <0>;
				de-active = <0>;
				pixelclk-active = <0>;
			};
		};

		ports {
			panel_in: endpoint {
				remote-endpoint = <&edp_out>;
			};
		};
	};

2、c语言解析代码


	struct device_node *panel_nd;//设备节点
	struct property *proper;
	struct device_node *entry;
	struct device_node *timings_np;
	int res=-1;
	unsigned int regdata[2];
	const char *str;
	int val = 0;
	int loop;
	//u32 *phy_config;
	struct rkxx_remote_key_table key_table[50];

	/*获取设备树中的属性数据*/
	/*1.获取设备节点:panel*/
	panel_nd = of_find_node_by_path("/panel");
	if(panel_nd == NULL)
	{
		printk("panel_nd node not find\r\n");
	}
	else
	{
		printk("panel_nd node find\r\n");
	}

	/*2.获取compatible属性内容*/
	proper =  of_find_property(panel_nd,"compatible",NULL);
	if(proper == NULL)
	{
		printk("panel_nd compatible property find failed\r\n");
	}
	else
	{
		printk("panel_nd compatible =%s\r\n",(char *)proper->value);
	}
	/*3.获取status属性内容*/
	res = of_property_read_string(panel_nd,"status",&str);
	if(res < 0)
	{
		printk("panel_nd status read failed\r\n");
	}
	else
	{
		printk("panel_nd status =%s\r\n",str);
	}
	
	/*4.获取reg属性内容*/
	res = of_property_read_u32_array(panel_nd,"reg",regdata,2);
	if(res <0 )
	{
		printk("panel_nd reg property read failed\r\n");
	}
	else
	{
		printk("panel_nd regdata[0]=0x%x\r\n",regdata[0]);
		printk("panel_nd regdata[1]=0x%x\r\n",regdata[1]);
	}

	if (of_get_property(panel_nd, "rockchip,key_table", &val))
	{
	    printk("panel_nd rockchip,rockchip,key_table val=%d\r\n",val);
		of_property_read_u32_array(panel_nd, "rockchip,key_table",
					   (u32 *)key_table, val / sizeof(u32));
		for (loop=0; loop<(val / sizeof(u32)/2); loop++) {
			printk("key_table[%d]=[0x%x,0x%x]\n", loop,
					key_table[loop].scancode,key_table[loop].keycode);
		}
		
	}

	timings_np = of_find_node_by_name(panel_nd, "display-timings");
	if (!timings_np) {
		printk("%s: could not find timings_np node\n",
			of_node_full_name(panel_nd));
	}else
		printk("finded timings_np node\n");

	entry = of_parse_phandle(timings_np, "native-mode", 0);
	
	if (!of_property_read_u32(entry, "hback-porch", &val))
		    printk("\nhback-porch=%d\n",val);

	if (!of_property_read_u32(entry, "hfront-porch", &val))
		    printk("\nhfront-porch=%d\n",val);

	if (!of_property_read_u32(entry, "hactive", &val))
			printk("\nhactive=%d\n",val);

	if (!of_property_read_u32(entry, "hsync-len", &val))
			printk("\nhsync-len=%d\n",val);

	if (!of_property_read_u32(entry, "vback-porch", &val))
			printk("\nvback-porch=%d\n",val);

	if (!of_property_read_u32(entry, "vfront-porch", &val))
			printk("\nvfront-porch=%d\n",val);	

	if (!of_property_read_u32(entry, "vactive", &val))
			printk("\nvactive=%d\n",val);	

	if (!of_property_read_u32(entry, "vsync-len", &val))
			printk("\nvsync-len=%d\n",val);	
	
	if (!of_property_read_u32(entry, "clock-frequency", &val))
			printk("\nclock-frequency=%d\n",val);


 

3、运行后看打印信息如下,解析ok。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个简单的 Linux kernel panic 堆栈信息解析示例: ``` Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b [<c0102a9e>] (unwind_backtrace+0x0/0xe8) from [<c042f8f6>] (panic+0x64/0x13c) [<c042f8f6>] (panic+0x64/0x13c) from [<c042d7c2>] (do_exit+0x5fe/0x602) [<c042d7c2>] (do_exit+0x5fe/0x602) from [<c0101e80>] (die+0x20c/0x214) [<c0101e80>] (die+0x20c/0x214) from [<c0113a98>] (__do_kernel_fault.part.3+0x5c/0x84) [<c0113a98>] (__do_kernel_fault.part.3+0x5c/0x84) from [<c0113b88>] (do_page_fault+0x2a0/0x2b8) [<c0113b88>] (do_page_fault+0x2a0/0x2b8) from [<c0100e6e>] (do_DataAbort+0x34/0x98) [<c0100e6e>] (do_DataAbort+0x34/0x98) from [<c0102d24>] (__dabt_svc+0x44/0x60) ---[ end trace 5a7926b607e5b2d5 ]--- ``` 这个堆栈信息表示系统发生了一个 kernel panic,导致系统无法正常运行。下面是对每一行的解析: - 第一行是 kernel panic 的描述信息,告诉我们出现了什么问题。 - 第二行中的 `<c0102a9e>` 表示函数 `unwind_backtrace` 在代码中的位置,`0x0/0xe8` 表示函数内部的偏移量。这个函数是用来跟踪函数调用栈的,可以帮助我们定位问题发生的位置。 - 第三行中的 `<c042f8f6>` 表示函数 `panic` 在代码中的位置,`0x64/0x13c` 表示函数内部的偏移量。这个函数会导致系统进入 panic 模式,因此我们需要关注它。 - 第四行中的 `<c042d7c2>` 表示函数 `do_exit` 在代码中的位置,`0x5fe/0x602` 表示函数内部的偏移量。这个函数是用来退出进程的,可能与问题有关。 - 第五行中的 `<c0101e80>` 表示函数 `die` 在代码中的位置,`0x20c/0x214` 表示函数内部的偏移量。这个函数是用来输出错误信息和导致系统进入 panic 模式的,因此我们需要关注它。 - 第六行中的 `<c0113a98>` 表示函数 `__do_kernel_fault.part.3` 在代码中的位置,`0x5c/0x84` 表示函数内部的偏移量。这个函数是用来处理页面故障的,可能与问题有关。 - 第七行中的 `<c0113b88>` 表示函数 `do_page_fault` 在代码中的位置,`0x2a0/0x2b8` 表示函数内部的偏移量。这个函数也是用来处理页面故障的,可能与问题有关。 - 第八行中的 `<c0100e6e>` 表示函数 `do_DataAbort` 在代码中的位置,`0x34/0x98` 表示函数内部的偏移量。这个函数是用来处理数据异常的,也可能与问题有关。 - 最后一行表示跟踪结束的信息,可以忽略。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值