微波EDA网,见证研发工程师的成长!
首页 > 研发问答 > 无线和射频 > 射频无线通信设计 > 7.DB410c开发板dts加载功能测试

7.DB410c开发板dts加载功能测试

时间:10-02 整理:3721RD 点击:

DTS是Device Tree Source的缩写,用来描述设备的硬件细节。在过去的ARM Linux中,arch/arm/plat-xxx和arch/arm/mach-xxx中充斥着大量的垃圾代码,相当多数的代码只是在描述板级细节,而这些板级细节对于内核来讲,不过是垃圾,如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data。为了去掉这些垃圾代码,Linux采用DTS这种新的数据结构来描述硬件设备。采用Device Tree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。
Linux在启动后,到C入口时,会执行以下操作,加载系统平台上的总线和设备:
start_kernel() init/main.c
--> setup_arch()  arch/arm64/kernel/setup.c
--> unflatten_device_tree()  drivers/of/fdt.c
unflatten_device_tree函数将DTS节点信息解析出来,保存到allnodes链表中。
随后系统启动,接着调用arch/arm64/kernel/setup.c文件中arm64_device_init函数-->of_platform_populate(....)接口,加载平台总线和平台设备。至此,系统平台上的所有已配置的总线和设备将被注册到系统中。
注意:不是dtsi文件中所有的节点都会被注册,在注册总线和设备时,会对dts节点的状态作一个判断,如果节点里面的status属性没有被定义,或者status属性被定义了并且值被设为“ok”或者“okay”,其他情况则不被注册到系统中。
dtsi定义:


dtsi加载代码:#include "unflatten_dts.dtsi"
驱动源代码:

  1. #include <linux/init.h>
  2. #include <linux/module.h>
  3. #include <linux/device.h>
  4. #include <linux/platform_device.h>
  5. #include <linux/sysfs.h>
  6. #include <linux/slab.h>
  7. #include <linux/kernel.h>
  8. #include <linux/kobject.h>
  9. #include <linux/string.h>
  10. #include <linux/of.h>

  11. #define UNFLATTEN_DTS_TIP "unflatten_dts_tip"
  12. char unflatten_dts_code[64] = "UNFLATTEN_DTS, unflatten_dts_show";

  13. static ssize_t show(struct device_driver *driver, char *buf)
  14. {
  15.         if(NULL != buf)
  16.         {
  17.                 /* Newline is not appended on purpose, for convenience of reader programs */
  18.                 snprintf(buf, PAGE_SIZE, "%s\n", unflatten_dts_code);
  19.                 return strlen(buf);
  20.         }

  21.         return 0;
  22. }
  23. DRIVER_ATTR(unflatten_dts, 0444, show, NULL);

  24. static struct attribute *unflatten_dts_attrs[] = {
  25.         &driver_attr_unflatten_dts.attr,
  26.         NULL,
  27. };

  28. static struct attribute_group unflatten_dts_group = {
  29.         .name ="unflatten_dts",
  30.         .attrs = unflatten_dts_attrs,
  31. };

  32. static const struct attribute_group *unflatten_dts_groups[] = {
  33.         &unflatten_dts_group,
  34.         NULL,
  35. };

  36. static int unflatten_dts_probe(struct platform_device *pdev)
  37. {
  38.         int nNum;
  39.         const char *m_string;
  40.         if(NULL == pdev)
  41.         {
  42.                 printk("xiaomi_test: unflatten_dts_probe failed, pdev is NULL\n");
  43.                 return 0;
  44.         }

  45.         if(NULL == pdev->dev.of_node)
  46.         {
  47.                 printk( "xiaomi_test: unflatten_dts_probe failed, of_node is NULL\n");
  48.                 return 0;
  49.         }
  50.         /* UNFLATTEN_DTS_TIP*/
  51.         if(of_property_read_bool(pdev->dev.of_node, UNFLATTEN_DTS_TIP))
  52.         {
  53.                 printk( "unflatten_dts_probe: dtsi<%s> is existing\n", UNFLATTEN_DTS_TIP);
  54.         }
  55.         if (of_property_read_u32(pdev->dev.of_node, "linux,code", &nNum))
  56.         {
  57.                 printk(KERN_INFO "=11= nNum=%d\n", nNum);
  58.         }
  59.         else
  60.         {
  61.                 printk(KERN_INFO "=12= nNum=%d\n", nNum);
  62.         }
  63.         if (of_property_read_string(pdev->dev.of_node, "linux,string", &m_string))
  64.         {
  65.                 printk(KERN_INFO "=11= m_string=%s\n", m_string);
  66.         }
  67.         else
  68.         {
  69.                 printk(KERN_INFO "=12= m_string=%s\n", m_string);
  70.         }
  71.         return 0;
  72. }
  73. /* .compatible的信息要与dtsi中的compatible一致 */
  74. static struct of_device_id unflatten_dts_info_match_table[] = {
  75.         { .compatible = "unflatten_dts",},
  76.         { },
  77. };

  78. static struct platform_driver unflatten_dts = {
  79.         .driver = {
  80.                 /* 当然这里的name要跟dtsi的节点DTS_TEST一致 */
  81.                 .name  = "unflatten_dts",
  82.                 .owner  = THIS_MODULE,
  83.                 .groups = unflatten_dts_groups,
  84.                 .of_match_table = unflatten_dts_info_match_table,
  85.         },

  86.         .probe = unflatten_dts_probe,
  87.         .remove = NULL,
  88. };

  89. static int __init unflatten_dts_init(void)
  90. {
  91.         return platform_driver_register(&unflatten_dts);
  92. }

  93. static void __exit unflatten_dts_exit(void)
  94. {
  95.         platform_driver_unregister(&unflatten_dts);
  96. }

  97. module_init(unflatten_dts_init);
  98. module_exit(unflatten_dts_exit);
  99. MODULE_LICENSE("GPL");

复制代码


Makefile文件:


编译,拷贝,insmod后的运行信息如下:


将前者与dtsi的内容做比较,我们可以确定dtsi文件里面的信息显示完全正确。
后者则是sysfs的一个显示,修改代码可以将dtsi中的内容在设备节点中显示。
知识点:
1.linux kernel的加载顺序;
2.dts dtsi的概念,应用;
3.sysfs概念,应用;
4.驱动模块编译,加载。

代码那块好乱。

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top