文章目录
一、前言
前节中,已经将整个eclipse在线调试BBB程序做了详细介绍,其实从上节开始,已经可以进行一定的应用程序编译及调试,但是对于BBB这物联网设备而言,我们更重要的是要使用它的硬件接口,如I2C、spi。此时自然会有两个疑问:
- 如果我用I2C接口,但实际开机后该接口是普通IO怎么办?能否一开机,该接口便已经初始化成i2C接口。
- 当我在BBB上做项目开发,以BBB当作核心板时,BBB能否根据不同的扩展板作出特定的IO初始化操作,比如同样的接口,一个扩展板用I2C,另一个用作普通IO口。BBB可以识别这两个扩展板作不同的初始化操作。
接下来的几节内容中将解决以上两个问题。
二、 Device Tree介绍
对于本节前言中提到的两个问题在BBB上已经有了合适的解决办法:
- 通过linux本身device tree机制可以实现对硬件的基本配置
- 通过合适的方式加载device tree即可完成配置
- 在BBB上通过相关shell命令可以实现device tree加载
- 在BBB上已有相关脚本在开机时自动加载相应device tree.
- 在BBB上已经有相关脚本在开机时会读取扩展板上的eeprom内信息,根据里面的信息加载不同的device tree,从而实现开机针对特定扩展板进行不同配置。
通过这些信息我们可以看出,BBB实际项目的开发离不开device tree,相关特殊操作都是基于这个设备树来操作的。
2.1 什么是device tree
device tree直译过来就是设备树,什么是设备树呢,其实就是描述硬件信息的树形结构,比如GPIO的配置、外设的配置等,这些信息要以一定的语法结构呈现,以方便编写,该语法结构为树形结构。这是linux-3.x版本提供的新功能,当linux内核启动时,device tree文件地址由bootloader传送到内核,内核根据device tree中设备信息对芯片进行初始化,并加载相应驱动。
2.2 device tree文件
如同C语言一样,首先要写xx.c文件,以C语言的语法来编写程序,再以C编译器、链接器、汇编器等编译,最终生成可以运行的C程序。device tree也是一样,首先要编写DTS文件,语法结构为树形结构,可以参考官网的说明,编写的文件为DTS文件,经过编译器DTC编译后可以生成DTB文件,内核可以识别该文件。其主要名称缩写:
- DTS: device tree source
- DTC: device tree compile
- DTB: device tree blob
- DTBO: device tree blob overlay
这里多了一个DTBO文件,overlay是意思是覆盖,就是说内核已经加载了DTB的基础上,还需要对其他硬件进行配置,此时就要用DTBO文件对其进行覆盖,开发BBB的cape时,DTBO是经常用到的文件,因此在实际学习中只需要掌握生成DTBO的DTS文件即可。
2.3 device tree语法结构
可以看下整个的例子,如下图
2.3.1 结点名称@单元地址
可以看出 每个结点的结构为:
node-name@unit-address
结点名称@单元地址
结构名称是指当前需要设置的模块的名称,单元地址是指这个模块在总线上的地址,通过这个地址可以设置它的寄存器,从而达到配置的目的。如果没有地址,则不需要标示出来。
官网中结点名称推荐用以下名称:
- adc
- accelerometer
- atm
- audio-codec
- audio-controller
- backlight
- bluetooth
- bus
- cache-controller
- camera
- can
- charger
- clock
- clock-controller
- compact-flash
- can
- cpu
- cpus
- crypto
- disk
- display
- dma-controller
- dsp
- eeprom
- efuse
- endpoint
- ethernet
- ethernet-phy
- fdc
- flash
- gpio
- gpu
- gyrometer
- hdmi
- i2c
- ide
- interrupt-controller
- isa
- keyboard
- key
- keys
- lcd-controller
- led
- leds
- led-controller
- light-sensor
- magnetometer
- mailbox
- mdio
- memory
- memory-controller
- mmc
- mmc-slot
- mouse
- nand-controller
- nvram
- oscillator
- parallel
- pc-card
- pci
- pcie
- phy
- pinctrl
- pmic
- pmu
- port
- ports
- pwm
- regulator
- reset-controller
- rtc
- sata
- scsi
- serial
- sound
- spi
- sram-controller
- ssi-controller
- syscon
- temperature-sensor
- timer
- touchscreen
- usb
- usb-hub
- usb-phy
- video-codec
- vme
- watchdog
- wifi
2.3.2 结点属性
属性名称+属性值的方式
那么一个结点可以有哪些属性呢,这个在官方文档中已经有清楚的定义,常用的有compatible, model, phandle, status, reg, device_type,name,interrupts
。
通过属性值可以设置该接口的相关属性,比如寄存器设置,设置中断属性等。
例如compatible,官方文档解释如下:
简要的意思是说:
compatible是由一个或多个字符串构成的,是用来定义设备的编程模型的,客户程序可以根据这里面的字符串来选择设备驱动。其形式建议是"manufacturer,model"
,即 厂家+模型的方式,例如:
compatible = "fsl,mpc8641", "ns16550";
3. BBB device tree实例
3.1 BBB dts文件分析
在BBB上最主要的是开发DTBO文件,系统开机时已经加载了基本的devicetree文件,只需要将dtbo文件加载,即可以完成相关端口初始化。
/*
* Copyright (C) 2013 CircuitCo
*
* Virtual cape for UART2 on connector pins P9.21 P9.22
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/dts-v1/;
/plugin/;
/ {
compatible = "ti,beaglebone", "ti,beaglebone-black";
/* identification */
part-number = "DVK551-RS232-01";
version = "00A0";
/* state the resources this cape uses */
exclusive-use =
/* the pin header uses */
"P9.21", /* uart2_txd */
"P9.22", /* uart2_rxd */
/* the hardware ip uses */
"uart2";
fragment@0 {
target = <&am33xx_pinmux>;
__overlay__ {
bb_uart2_pins: pinmux_bb_uart2_pins {
pinctrl-single,pins = <
0x150 0x21 /* spi0_sclk.uart2_rxd | MODE1 */
0x154 0x01 /* spi0_d0.uart2_txd | MODE1 */
>;
};
};
};
fragment@1 {
target = <&uart3>; /* really uart2 */
__overlay__ {
status = "okay";
pinctrl-names = "default";
pinctrl-0 = <&bb_uart2_pins>;
};
};
};
文件中:
/dts-v1/;
/plugin/;
这两行是声明,声明了dts采用的版本号是v1,同时声明了这个文件的内容是一个plugin。
compatible = "ti,beaglebone", "ti,beaglebone-black";
这个属性是根节点下面的一行,为了说明了它的适用平台。意思是TI的厂家,采用beaglebone模型。
/* identification */
part-number = "DVK551-RS232-01";
version = "00A0";
part-number
是一般是说文件名称,version
是指版本号是00A0,整个dts文件名就是part-number
+version
形式,因此这个例子的名称就是DVK551-RS232-01-00A0.dts
。
再下面的部分说明了要使用的引脚和硬件设备
/* state the resources this cape uses */
exclusive-use =
/* the pin header uses */
"P9.21", /* uart2_txd */
"P9.22", /* uart2_rxd */
/* the hardware ip uses */
"uart2";
fragment@0 {
target = <&am33xx_pinmux>;
__overlay__ {
bb_uart2_pins: pinmux_bb_uart2_pins {
pinctrl-single,pins = <
0x150 0x21 /* spi0_sclk.uart2_rxd | MODE1 */
0x154 0x01 /* spi0_d0.uart2_txd | MODE1 */
>;
};
};
};
以上部分是根结点下的一个子结点主要是为了定义引脚的地址及初始化值,对于我们修改而言,只需要知道引脚该怎样配置即可,这就要用我们前面提到的查表来看。
上面结点信息中0x150
是指引脚地址,通过查表可以看到其地址,如下图:
上在结点信息中0x21
是指配置引脚属性转换为二进制为0010 0001
,对就以下表可以看出主要初始化功能为:选择模式1,即串口功能,使能接收功能,使能端口下拉。具体查表方法可以查看前节相关内容。
针对以上信息的简要介绍,可以手动对设备树文件进行简要修改,实际中相关端口的dts文件基本在BBB中都有了,我们只需要参考,并进行相关复制就可以了。