硬件平台:tiny4412
系统:linux-4.4
文件系统:busybox-1.25
编译器: arm-none-linux-gnueabi-gcc(gcc version 4.8.3 20140320)
uboot:友善自带uboot.
一、DTS引入
1.什么是DTS?为什么要引入DTS?
DTS即Device Tree Source设备树源码,DeviceTree是一种描述硬件的数据结构,它起源于OpenFirmware (OF)。
在Linux2.6中,ARM架构的板极硬件细节过多地被硬编码在arch/arm/plat-xxx和arch/arm/mach-xxx,比如板上的platform设备、resource、i2c_board_info、spi_board_info以及各种硬件的platform_data,这些板级细节代码对内核来讲只不过是垃圾代码。而采用DeviceTree后,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。
2.ARM平台的相关code做出如下相关规范调整
•ARM的核心代码仍然保存在arch/arm目录下
•ARM SoC corearchitecture code保存在arch/arm目录下
•ARMSOC的周边外设模块的驱动保存在drivers目录下
•ARMSOC的特定代码在arch/arm/mach-xxx目录下
•ARM SOCboard specific的代码被移除,由DeviceTree机制来负责传递硬件拓扑和硬件资源信息。
本质上,Device Tree改变了原来用hardcode方式将HW配置信息嵌入到内核代码的方法,改用bootloader传递一个DB的形式。
3.DTS的加载过程
如果要使用DeviceTree,首先用户要了解自己的硬件配置和系统运行参数,并把这些信息组织成DeviceTree source file。通过DTC(DeviceTree Compiler),可以将这些适合人类阅读的DeviceTree source file变成适合机器处理的DeviceTree binary file(DTB,devicetree blob)。在系统启动的时候,bootprogram(例如:firmware、bootloader)可以将保存在flash中的DTB copy到内存(当然也可以通过其他方式,例如可以通过bootloader的交互式命令加载DTB),并把DTB的起始地址传递给OSkernel。对于计算机系统(computersystem),一般是firmware->bootloader->OS,对于嵌入式系统,一般是bootloader->OS。
4.DTS的描述信息
Device Tree由一系列被命名的结点(node)和属性(property)组成,而结点本身可包含子结点。所谓属性,其实就是成对出现的name和value。在DeviceTree中,可描述的信息包括(原先这些信息大多被hardcode到kernel中):
•CPU的数量和类别
•内存基地址和大小
•总线和桥
•外设连接
•中断控制器和中断使用情况
•GPIO控制器和GPIO使用情况
•Clock控制器和Clock使用情况
它基本上就是画一棵电路板上CPU、总线、设备组成的树,Bootloader会将这棵树传递给内核,然后内核可以识别这棵树,并根据它展开出Linux内核中的platform_device、i2c_client、spi_device等设备,而这些设备用到的内存、IRQ等资源,也被传递给了内核,内核会将这些资源绑定给展开的相应的设备。
一个.dts文件对应一个ARM的machine,一般放置在内核的arch/arm/boot/dts/目录。由于一个SoC可能对应多个machine(一个SoC可以对应多个产品和电路板),势必这些.dts文件需包含许多共同的部分,Linux内核为了简化,把SoC公用的部分或者多个machine共同的部分一般提炼为.dtsi。所有的ARMSoC的.dtsi都引用了skeleton.dtsi,即#include"skeleton.dtsi“或者 /include/ "skeleton.dtsi"
5.变化
platform之前:
现在:
二、设备树文件
1、修改设备树文件支持GPIO按键中断
(/work/linux-4.4.0/linux-4.4/arch/arm/boot/dts/exynos4412-tiny4412.dts)
interrupt_demo: interrupt_demo {
compatible = "tiny4412,interrupt_demo";
tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>;
tiny4412,int_gpio2 = <&gpx3 3 GPIO_ACTIVE_HIGH>;
tiny4412,int_gpio3 = <&gpx3 4 GPIO_ACTIVE_HIGH>;
tiny4412,int_gpio4 = <&gpx3 5 GPIO_ACTIVE_HIGH>;
};
2、完整的设备树文件:
Device Tree有自己的独立的语法,它的源文件为.dts,编译后得到.dtb,Bootloader在引导Linux内核的时候会将.dtb地址告知内核。之后内核会展开Device Tree并创建和注册相关的设备,因此arch/arm/mach-xxx和arch/arm/plat-xxx中大量的用于注册platform、I2C、SPI板级信息的代码被删除,而驱动也以新的方式和.dts中定义的设备结点进行匹配。
/*
* FriendlyARM's Exynos4412 based TINY4412 board device tree source
*
* Copyright (c) 2013 Alex Ling * * Device tree source file for FriendlyARM's TINY4412 board which is based on * Samsung's Exynos4412 SoC. * * 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/; #include "exynos4412.dtsi" #include / { //root结点"/" model = "FriendlyARM TINY4412 board based on Exynos4412"; //root结点"/"的属性compatible,组织形式为: //Linux内核透过root结点"/"的compatible 属性即可判断它启动的是什么machine //compatible 属性是一个字符串的列表,列表中的第一个字符串表征了结点代表的确切设备, //形式为" //可以说前面的是特指,后面的则涵盖更广的范围。 compatible = "friendlyarm,tiny4412", "samsung,exynos4412", "samsung,exynos4"; //以下开始为子节点 //子结点的命名,它们遵循的组织形式为: //<>中的内容是必选项,[]中的则为可选项。name是一个ASCII字符串,用于描述结点对应的设备类型,如memory; //多个相同类型设备结点的name可以一样,只要unit-address不同即可 //chosen节点并不代表一个真正的设备,而是用来在Firmware与操作系统间传递数据,如启动参数。 chosen { //子结点"chosen" stdout-path = &serial_0; bootargs = "root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc earlyprintk"; }; memory { //子结点"memory" reg = <0x40000000 0x40000000>; }; leds { //子结点"leds" compatible = "gpio-leds"; led1 { //子子结点"led1" label = "led1"; gpios = <&gpm4 0 GPIO_ACTIVE_LOW>; default-state = "off"; linux,default-trigger = "heartbeat"; }; led2 { label = "led2"; gpios = <&gpm4 1 GPIO_ACTIVE_LOW>; default-state = "off"; }; led3 { label = "led3"; gpios = <&gpm4 2 GPIO_ACTIVE_LOW>; default-state = "off"; }; led4 { label = "led4"; gpios = <&gpm4 3 GPIO_ACTIVE_LOW>; default-state = "off"; linux,default-trigger = "mmc0"; }; }; fixed-rate-clocks { xxti { compatible = "samsung,clock-xxti"; clock-frequency = <0>; }; xusbxti { compatible = "samsung,clock-xusbxti"; clock-frequency = <24000000>; }; }; interrupt_demo: interrupt_demo { compatible = "tiny4412,interrupt_demo"; tiny4412,int_gpio1 = <&gpx3 2 GPIO_ACTIVE_HIGH>; tiny4412,int_gpio2 = <&gpx3 3 GPIO_ACTIVE_HIGH>; tiny4412,int_gpio3 = <&gpx3 4 GPIO_ACTIVE_HIGH>; tiny4412,int_gpio4 = <&gpx3 5 GPIO_ACTIVE_HIGH>; }; }; &rtc { status = "okay"; }; &sdhci_2 { bus-width = <4>; pinctrl-0 = <&sd2_clk &sd2_cmd &sd2_cd &sd2_bus4>; pinctrl-names = "default"; #status = "okay"; status = "disabled"; }; &serial_0 { status = "okay"; }; &serial_1 { status = "okay"; }; &serial_2 { status = "okay"; }; &serial_3 { status = "okay"; }; 三、设备树驱动 设备树引来的驱动变化 #include #include #include #include #include #include #include typedef struct { int gpio; int irq; char name[20]; }int_demo_data_t; static irqreturn_t int_demo_isr(int irq, void *dev_id) { int_demo_data_t *data = dev_id; printk("%s enter, %s: gpio:%d, irq: %dn", __func__, data->name, data->gpio, data->irq); return IRQ_HANDLED; } static int int_demo_probe(struct platform_device *pdev) { struct device *dev = &pdev->dev; int irq_gpio = -1; int irq = -1; int ret = 0; int i = 0; int_demo_data_t *data = NULL; printk("%s enter.n", __func__); if (!dev->of_node) { dev_err(dev, "no platform data.n"); goto err1; } data = devm_kmalloc(dev, sizeof(*data)*4, GFP_KERNEL); if (!data) { dev_err(dev, "no memory.n"); goto err0; } #if 1 for (i = 3; i >= 0; i--) { sprintf(data[i].name, "tiny4412,int_gpio%d", i+1); #else for (i = 0; i < 4; i++) { #endif irq_gpio = of_get_named_gpio(dev->of_node, data[i].name, 0);//通过名字获取gpio if (irq_gpio < 0) { dev_err(dev, "Looking up %s property in node %s failed %dn", data[i].name, dev->of_node->full_name, irq_gpio); goto err1; } data[i].gpio = irq_gpio; irq = gpio_to_irq(irq_gpio); //将gpio转换成对应的中断号 if (irq < 0) { dev_err(dev, "Unable to get irq number for GPIO %d, error %dn", irq_gpio, irq); goto err1; } data[i].irq = irq; printk("%s: gpio: %d ---> irq (%d)n", __func__, irq_gpio, irq); //注册中断 ret = devm_request_any_context_irq(dev, irq, int_demo_isr, IRQF_TRIGGER_FALLING, data[i].name, data+i); if (ret < 0) { dev_err(dev, "Unable to claim irq %d; error %dn", irq, ret); goto err1; } } return 0; err1: devm_kfree(dev, data); err0: return -EINVAL; } static int int_demo_remove(struct platform_device *pdev) { printk("%s enter.n", __func__); return 0; } static const struct of_device_id int_demo_dt_ids[] = { { .compatible = "tiny4412,interrupt_demo", },
上一篇:ARM9时钟体系结构
下一篇:tiny4412学习(二)之移植linux-4.x支持设备树
推荐帖子
- 基于MSP430的MODBUS通信程序
- 版主可以帮我看看我的程序还有什么欠缺么,有些地方实在不知道怎么写了,能帮忙改一下。谢谢#includemsp430x14x.h#defineucharunsignedchar#defineuintunsignedint/****************************************************************************/#defineP3_0_WDI0x01//WDT#defineP3_1_BEEP0
- hygk stm32/stm8
- “运放”/“运算放大器”技术问答精粹
- 转自:电子工程专辑运放是运算放大器的简称。在实际电路中,通常结合反馈网络共同组成某种功能模块。由于早期应用于模拟计算机中,用以实现数学运算,故得名“运算放大器”,此名称一直延续至今。运放是一个从功能的角度命名的电路单元,可以由分立的器件实现,也可以实现在半导体芯片当中。现今运放的种类繁多,广泛应用于几乎所有的行业当中。在这里,我们整理出了《电子工程专辑》论坛的一些精华贴,希望前人的问题能帮助到遇到同样问题的你,也希望高手们能常来看看,为新进菜鸟们指点思路并提升自己的价
- 安_然 模拟电子
- 谁有protel DXP2004的教程
- 谁有protelDXP2004的教程共享共享谢谢!谁有protelDXP2004的教程ProtelDXP教程下载这里有呢我有可是那文件很大1G传不了呀Re:谁有protelDXP2004的教程看不懂,我有一个。还系去学院学好。Re:谁有protelDXP2004的教程
- ekson PCB设计
- 电路故障分析
- 大家好!遇到一个故障问题,请教各位。产品是一个零火线的灯光控制设备(使用ZigBee)。硬件电路设计为两路灯光控制。现在使用一段时间后出现故障,故障现象:两路控制开关同时打开后,灯光由亮一下熄灭。分别只打开一路,灯光均可正常亮起。只要两张灯一起亮起,1S内两张灯同时熄灭。还有一个故障:部分设备单路控制灯光也不会亮起,但是继电器有动作。个人感觉两个故障都是同一个问题。给大家看看设计原理图(见附件),看看是否有不合理的地方?如何故障分析?谢谢!电路故障分析先替楼主把图贴
- nicole088 电源技术
- 天然气泄漏无线报警系统
- 希望高手指导,有不完善得请提问,自己是刚开始学得,不可能给自己太多得功能和太复杂得任务,一步一步来吧,以后我会做更进一步得改进!!这只是一个初步得想法。受教了!!!天然气泄漏无线报警系统我咋看不到别人的回复呢??原帖由fxw451于2011-1-2215:17发表我咋看不到别人的回复呢??有人回复才能看到回复呀!我先顶一下吧!32/4有回复的。回复板凳maylove的帖子顶,写的很详细,计划也很仔细
- fxw451 微控制器 MCU
- 信号调理电路输出电压问题
- 如图所示上半部分是是一路开关信号的调理电路,输入SW_IN是数字量输入,低电平有效,VCC是12伏特调理出来的信号SW_OUT,直接送至MCU(下半部分图),MCU是CYT2B7系列的问题是:当输入信号为高电平时,调理电路的输出为:VCC(R3/(R1+R2+R3))=6.9伏特而MCU的供电电压才3.3伏特,这样信号能输入到MCU中去吗?信号调理电路输出电压问题个人理解,那个电源有问题,已经快到芯片端了,为什么还要设置这么高的电压,而且没有钳位电路;否则就是那几个电阻
- shaorc 单片机
设计资源 培训 开发板 精华推荐
- 非常见问题解答第223期:如何在没有软启动方程的情况下测量和确定软启动时序?
- 兆易创新GD25/55全系列车规级SPI NOR Flash荣获ISO 26262 ASIL D功能安全认证证书
- 新型IsoVu™ 隔离电流探头:为电流测量带来全新维度
- 英飞凌推出简化电机控制开发的ModusToolbox™电机套件
- 意法半导体IO-Link执行器电路板为工业监控和设备厂商带来一站式参考设计
- Melexis采用无磁芯技术缩小电流感测装置尺寸
- 千丘智能侍淳博:用数字疗法,点亮“孤独症”儿童的光
- 数药智能冯尚:ADHD数字疗法正为儿童“多动症”提供更有效便捷服务
- Vicor高性能电源模块助力低空航空电子设备和 EVTOL的发展
- 创实技术electronica 2024首秀:加速国内分销商海外拓展之路