gpt4 book ai didi

beagleboneblack - 如何使用设备树覆盖在Beaglebone Black上添加i2c设备?

转载 作者:行者123 更新时间:2023-12-03 13:01:49 29 4
gpt4 key购买 nike

我为什么要读这个?

如果您有Beaglebone Black(BBB),并且想将自己的设备连接到它(而不是斗篷),则可能已经听说过设备树。就我而言,我想将RTC设备连接到BBB上的I2C总线。网络上散布着许多信息,本文旨在总结我所发现的内容,并以此为指导。

因此,我将给出一个激活BBB上的I2C总线以及使用内核中包含的设备驱动程序连接DS1308 RTC芯片的完整示例。听起来不错?

然后继续阅读,如果不清楚,请发表评论。如果您有急事,也可以在Github上获取设备树覆盖代码并飞走。

首先是第一件事。

我在BBB上使用ArchLinux ARM主要是因为Arch Linux很棒,而且我可能太愚蠢而无法使用debianoid发行版。
这是系统的screenfetch

ArchLinux screenfetch on BBB

您可能会注意到内核版本已经高于该3.x版本。在屏幕抓取中看不到的是内核使用Capemgr实用程序支持设备树覆盖。

什么是设备树?

我将快速进行操作,您可以找到更深入的知识herehereherehere
设备树是描述平台上基础硬件的结构。它在嵌入式设备中大量使用,因为SOC和其他东西没有像PCI这样的总线可以在其中发现设备。必须静态定义它们,并将它们附加到“平台总线”上,以提供内核附带的设备驱动程序的句柄。

在将设备树引入Linux之前,所有工作都必须使用特定的C头文件和自定义实现来完成,然后将所有这些合并到主线内核中。因此,这是一项可以想象的详尽的工作,它来到了著名的Linus Torvalds rant。在这里,您还有更多device tree background

是的,但是如何运作?

为了描述设备树,我们使用.dts(设备树源)文件,这些文件是人类可读的,并由设备树编译器(dtc)编译为二进制格式的设备树blob(.dtb)。系统启动时,引导加载程序(例如u-boot)将那个blob移交给内核。内核将对其进行解析并创 build 备树所指定的所有设备。

如果您不相信我,请使用设备树编译器深入了解BBB现在正在使用的设备树。

如果尚未安装,请获取适当的软件包。

pacman -Sy dtc-overlay
dtc -f -I fs /proc/device-tree | less

建议使用传呼机 less的管道,因为该命令会产生大量输出。结果应如下所示。

enter image description here

您还可以在内核源代码中调查设备树的所有部分,但是由于还包含一个包含机制,因此信息会分成几个文件。
 <kernel-source>/arch/arm/boot/dts/.. 

一些相关文件是:
  • am335x-bone-common.dtsi
  • am335x-boneblack.dts
  • am33xx.dtsi

  • Note: The .dtsi files are equivalent to .h files in C or C++ because they get included (therefore the 'i' at the end) by .dts files



    它们都描述了与处理器有关的设备,Beaglebone平台上的常见设备或仅适用于Beaglebone Black的设备。

    您提到了覆盖物,那是什么?

    好问题,我看到你仍然在我身边。就像我之前说过的那样,内核启动时会解析设备树blob。因此,当您的系统启动并运行时,整个魔力已经结束。在带有大量扩展板( Capes)的BBB之类的平台上,这将要求您每次使用其他披肩时都重新编译设备树。

    因此,您具有覆盖机制,可让您在运行时在设备树中添加或修改设备!惊人。

    Note: to be able to compile device tree overlays make sure to install the appropriate package like above (dtc-overlay)



    我将如何使用所有这些?

    我举一个例子。由于BBB没有实时时钟(rtc),这对于生成测量等的时间戳很有用,因此我们将对其进行修复。

    我们将使用 ds1307实时时钟芯片(实际上我有 ds1308 rtc,但驱动程序兼容),并通过BBB上的I2C1总线与之通信。从设备树源中可以看到,默认情况下,BBB上的总线是禁用的。

    i2c1 node in am33xx.dtsi

    该代码段中的重要信息是:
  • 定义了一个名为“i2c1”的节点
  • ,它被定义为与omap4-i2c驱动程序
  • 兼容
  • 根据处理器reference manual(第181页),为设备分配了内存映射地址(0x4802a000)和适当的地址范围(0x1000)
  • 设备状态已禁用

  • 现在,我们将创建一个覆盖图,以配置i2c1总线的GPIO引脚,激活该总线,然后添加rtc设备i2c1总线,以便自动加载适当的驱动程序,并在 /dev中创建rtc设备。

    BBB上P8和P9接头连接器上的GPIO引脚具有多种功能,这些功能被混合在一起,因此我们必须调整pinmux设置以将其用于I2C通信。正如在I2C1总线的 this table中看到的那样,我们必须在多路复用器模式2中使用排针17和18。要获取有关BBB上GPIO处理的更多信息,请看 here
    /dts-v1/;
    /plugin/;

    /{ /* this is our device tree overlay root node */

    compatible = "ti,beaglebone", "ti,beaglebone-black";
    part-number = "BBB-I2C1"; // you can choose any name here but it should be memorable
    version = "00A0";

    fragment@0 {
    target = <&am33xx_pinmux>; // this is a link to an already defined node in the device tree, so that node is overlayed with our modification

    __overlay__ {
    i2c1_pins: pinmux_i2c1_pins {
    pinctrl-single,pins = <
    0x158 0x72 /* spi0_d1.i2c1_sda */
    0x15C 0x72 /* spi0_cs0.i2c1_sdl */
    >;
    };
    };
    };
    }; /* root node end */

    天哪,刚才发生了什么?

    乍一看,overlay语法看起来很怪异,但它基本上是由所谓的片段组成的,这些片段针对一个已经存在的设备节点并修改该节点(及其子节点)。

    在这种情况下,我们以在处理器设备树( am33xx_pinmux)中定义的 am33xx.dtsi设备节点为目标。在该节点内,我们添加了一个新的子节点,称为pinmux_i2c1_pins,该子节点以前不存在(请查看 am335x-bone-common.dtsi进行验证),并添加标签i2c1_pins。

    下一部分要复杂一些,如果您有兴趣,请阅读 this。每个GPIO引脚都由一个具有多个位的寄存器配置,以控制其行为,所有寄存器均由 pinctrl-single驱动程序控制。要设置特定的引脚,只需使用其相对于基地址的地址偏移量即可(您可以在上面的P9标题表中找到该地址),并将其引脚配置作为第二个参数。

    BBB gpio settings

    我从 Derek Molloy借用了此概述以解释pin模式。由于 0x7201110010b等效,因此我们将两个引脚都配置为输入,并具有启用的上拉电阻和复用模式2中的有效转换控制。

    这些引脚的复用器模式2表示插头P9上的引脚17是时钟线SCL,插头P9上的引脚18是数据线SDA。

    但是我们仍然必须启用I2C1吗?

    绝对正确,因此让我们如下扩展覆盖。
    /dts-v1/;
    /plugin/;

    /{ /* this is our device tree overlay root node */

    compatible = "ti,beaglebone", "ti,beaglebone-black";
    part-number = "BBB-I2C1"; // you can choose any name here but it should be memorable
    version = "00A0";

    fragment@0 {
    target = <&am33xx_pinmux>; // this is a link to an already defined node in the device tree, so that node is overlayed with our modification

    __overlay__ {
    i2c1_pins: pinmux_i2c1_pins {
    pinctrl-single,pins = <
    0x158 0x72 /* spi0_d1.i2c1_sda */
    0x15C 0x72 /* spi0_cs0.i2c1_sdl */
    >;
    };
    };
    };

    fragment@1 {
    target = <&i2c1>;

    __overlay__ {
    pinctrl-0 = <&i2c1_pins>;

    clock-frequency = <100000>;
    status = "okay";

    rtc: rtc@68 { /* the real time clock defined as child of the i2c1 bus */
    compatible = "dallas,ds1307";
    #address-cells = <1>;
    #size-cells = <0>;
    reg = <0x68>;
    };
    };
    };
    }; /* root node end */

    在上面的代码中,我们添加了一个针对i2c1设备节点的新片段,并告诉它使用我们先前定义的引脚配置。我们将I2C时钟频率设置为100kHz,然后激活设备。

    此外,rtc时钟作为子代添加到i2c1节点。内核的重要信息是可兼容的语句,该语句指定要使用的驱动程序( ds1307)和I2C总线上的设备地址( 0x68)。可以从数据表中获取rtc的I2C地址。

    以及如何将这些代码导入内核?

    首先,必须编译设备树源。通过以下调用使用dtc编译器。
    dtc -O dtb -o <filename>-00A0.dtbo -b 0 -@ <filename>.dts

    Caution! The filename must be a concatenation of the name you desire plus the version tag as seen above (-00A0) otherwise you'll have a hard time.



    生成的 .dtbo文件应该复制到 /lib/firmware中,我真的不知道“-00A0”命名约定来自何处,但是固件目录中也有其他文件正在使用它。

    从现在开始,您可以使用Capemgr动态加载叠加层。为此,请移至 /sys/devices/platform/bone_capemgr/中,然后执行。
    echo <filename> > slots

    Capemgr然后将在固件目录中查找您的 .dtbo文件,并在可能的情况下加载它。通过查看插槽文件,您可以查看该过程是否成功。它应该看起来像这样。

    enter image description here

    检查Beaglebone使用的设备树。
    dtc -f -I fs /proc/device-tree | less

    您会在叠加层中找到所有条目。

    enter image description here

    enter image description here

    此外,文件系统中应该有一个新的I2C设备( /dev/i2c-1)和一个新的rtc设备( /dev/rtc1)。

    要查看i2c总线,请安装软件包 i2c-tools并使用。
    i2cdetect -r 1

    输出应该是这样的。

    enter image description here

    如您所见,地址0x68被设备占用。

    查询您的rtc使用。
    hwclock -r -f /dev/rtc1

    但这还不是全部,不是吗?

    不,您还有其他选择,可以在引导时加载设备树覆盖。 真棒!

    为此,请打开 /boot/uEnv.txt并将 bone_capemgr.enable_partno=<filename>添加到 optargs语句中。那就是我BBB的样子
    optargs=coherent_pool=1M bone_capemgr.enable_partno=bbb-i2c1

    令人困惑的是,文件名用在optargs中,而不是设备树覆盖图中定义的 part-number标记。

    如果愿意,可以将我的示例代码放在 github上有用的Makefile旁。

    抱歉,很长的帖子。

    最佳答案

    这是非常有用和有值(value)的信息。我编写了一个i2c内核驱动程序,可以动态加载该驱动程序以与地址0x77的自定义芯片通信。过去,我通过手动实例化设备来成功与芯片进行通信,如下所示:echo act2_chip 0x77> / sys / bus / i2c / devices / i2c-1 / new_device。
    实例化设备后,我可以使用i2cdetect工具看到它,并且我的可加载内核驱动程序可以与芯片通信。

    现在,我尝试使用设备树方法实例化设备。因此,按照您的指导,我更改了dtsi文件中的一些参数,如下所示:

    fragment@1 {
    target = <&i2c1>;

    __overlay__ {
    pinctrl-0 = <&i2c1_pins>;

    clock-frequency = <100000>;
    status = "okay";

    act2_chip: act2_chip@77 { /* the real time clock defined as child of the i2c1 bus */
    compatible = "xx,act2_chip";
    #address-cells = <1>;
    #size-cells = <0>;
    reg = <0x77>;
    };

    我将芯片连接到scl和sda的针脚17和18。这是我在echo> slot之后得到的dmesg输出:
    image

    但是在将驱动程序插入内核时,我看到了被调用的探测功能。这意味着驾驶员能够尽我所能看到设备。

    当我尝试写入内核驱动程序时,我收到以下消息:
    omap_i2c 4802a000.i2c: Controller 超时

    关于beagleboneblack - 如何使用设备树覆盖在Beaglebone Black上添加i2c设备?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/33549211/

    29 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com