目录
序
毕业也有两年了,从大一接触嵌入式以来快六年了,这六年学到的东西也有很多。以前都是看别人的博客,自有写博客想法以来也有一段时间,此博客作为博客的开端,接下来的工作学习中会把所见所学记录在博客中。希望以后能够多写博客,很多疏漏的地方还望大家指正,共同进步
驱动概括
以前在学校大多数嵌入式都是裸机跑起来,驱动非常简单;然后就是一些简单的嵌入式操作系统,比如说freeRtos,这些也都是裸机的驱动;linux驱动就比较复杂,有它自己的驱动框架,并且这个框架十分庞大。这个linux驱动程序就是:
裸机驱动 + linux驱动框架
即按照linux框架来组织驱动程序,所以学好裸机驱动之后,就需要画大功夫去学习linux驱动框架
驱动框架演变
1,设备和驱动在一起
设备相关的信息,比如寄存器地址、大小等信息都是在一个源文件中;以韦东山视频中最简单的led程序为例耦合性比较强。
2,设备和驱动分离
设备和驱动分离开来,设备信息放在一个文件中,驱动程序放在一个文件中;两个文件分别加载,在内核启动的时候根据名字匹配,匹配成功后就调用probe()函数,进行相关的初始化。
3,设备树的引入
由于之前的设备和驱动都是编译进内核中,且没修改一下设备地址就需要重新编译一下内核。并且平台信息太乱,所以后面就把设备信息单独放到一个文件中以文本的形式组织起来。并且单独编译,不与内核一起编译
设备树
1)前面的总线设备驱动模型中,硬件资源来自于leds_dev.c里面的信息,这样会导致不同的板子,会添加不同的硬件资源信息,造成内核的臃肿。
2)使用设备树后,内核不再包含硬件的描述,硬件描述放在单独的DTS里面,然后编译成二进制的DTB,在U-Boot启动的时候加载进去,然后内核进行解析。
3)DTS、DTC和DTB之间的关系:
DTS经过DTC编译得到DTB,DTB通过DTC反编译得到DTS.
4)ARM中,所有的DTS文件放在arch/arm/boot/dts目录中,为了简化,将Soc公用部分提取了出来作为dtsi,类似头文件。
5)DTC编译工具的源代码在scripts/dtc目录中,编译内核时,编译内核时,需要使能才能将源码编译成工具,对应于scripts/dtc/Makefile中"hostprogs-y:=dtc"。Ubuntu也可直接安装DTC工具:
例:
/include/ “skeleton.dtsi”
/ {
compatible = “xlnx,zynq-7000”;
cpus {
#address-cells = <1>;
#size-cells = <0>;
cpu@0 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <0>;
clocks = <&clkc 3>;
clock-latency = <1000>;
cpu0-supply = <®ulator_vccpint>;
operating-points = <
/* kHz uV */
666667 1000000
333334 1000000
>;
};
cpu@1 {
compatible = "arm,cortex-a9";
device_type = "cpu";
reg = <1>;
clocks = <&clkc 3>;
};
};
pmu {
compatible = "arm,cortex-a9-pmu";
interrupts = <0 5 4>, <0 6 4>;
interrupt-parent = <&intc>;
reg = < 0xf8891000 0x1000 0xf8893000 0x1000 >;
};
regulator_vccpint: fixedregulator@0 {
compatible = "regulator-fixed";
regulator-name = "VCCPINT";
regulator-min-microvolt = <1000000>;
regulator-max-microvolt = <1000000>;
regulator-boot-on;
regulator-always-on;
};
amba: amba {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&intc>;
ranges;
adc: adc@f8007100 {
compatible = "xlnx,zynq-xadc-1.00.a";
reg = <0xf8007100 0x20>;
interrupts = <0 7 4>;
interrupt-parent = <&intc>;
clocks = <&clkc 12>;
};
can0: can@e0008000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <&clkc 19>, <&clkc 36>;
clock-names = "can_clk", "pclk";
reg = <0xe0008000 0x1000>;
interrupts = <0 28 4>;
interrupt-parent = <&intc>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
can1: can@e0009000 {
compatible = "xlnx,zynq-can-1.0";
status = "disabled";
clocks = <&clkc 20>, <&clkc 37>;
clock-names = "can_clk", "pclk";
reg = <0xe0009000 0x1000>;
interrupts = <0 51 4>;
interrupt-parent = <&intc>;
tx-fifo-depth = <0x40>;
rx-fifo-depth = <0x40>;
};
gpio0: gpio@e000a000 {
compatible = "xlnx,zynq-gpio-1.0";
#gpio-cells = <2>;
#interrupt-cells = <2>;
clocks = <&clkc 42>;
gpio-controller;
interrupt-controller;
interrupt-parent = <&intc>;
interrupts = <0 20 4>;
reg = <0xe000a000 0x1000>;
};
i2c0: i2c@e0004000 {
compatible = "cdns,i2c-r1p10";
status = "disabled";
clocks = <&clkc 38>;
interrupt-parent = <&intc>;
interrupts = <0 25 4>;
reg = <0xe0004000 0x1000>;
#address-cells = <1>;
#size-cells =