“第六课:在LCD驱动中使用设备树”的版本间的差异
第13行: | 第13行: | ||
实际上涉及设备树的修改并不多,那我怎么知道修改那些呢? | 实际上涉及设备树的修改并不多,那我怎么知道修改那些呢? | ||
− | + | 我使用最笨的方法——添加打印。在发现内核启动卡住后,就沿着内核启动流程调用的函数添加打印,比如在`init.c`函数添加了一系列打印,看它卡在哪个函数,再进入该函数添加打印。 | |
这里打印使用的是<code>early_print()</code>,因为<code>printk()</code>很可能还不能使用,<code>early_print()</code>直接把数据写到串口里面,和硬件驱动没有什么关系。 | 这里打印使用的是<code>early_print()</code>,因为<code>printk()</code>很可能还不能使用,<code>early_print()</code>直接把数据写到串口里面,和硬件驱动没有什么关系。 | ||
+ | |||
= 第01节_使用设备树给DM9000网卡_触摸屏指定中断= | = 第01节_使用设备树给DM9000网卡_触摸屏指定中断= | ||
在上一课我们把中断体系讲得很清楚了,我们先看一下内核里的网卡驱动程序,所在路径为: | 在上一课我们把中断体系讲得很清楚了,我们先看一下内核里的网卡驱动程序,所在路径为: | ||
− | + | <syntaxhighlight lang="c" > | |
drivers/net/ethernet/davicom/dm9dev9000.c | drivers/net/ethernet/davicom/dm9dev9000.c | ||
− | + | </syntaxhighlight> | |
− | 在这里做了一件非常取巧的事情,以前中断号和硬件绑定时,它的中断号是 | + | 在这里做了一件非常取巧的事情,以前中断号和硬件绑定时,它的中断号是<code>IRQ_EINT7</code>,现在我直接偷懒将其赋值为7,实际上这种方法是非常不保险的。 |
+ | |||
从原理上我们可以知道网卡使用的是EINT7,对于EINT7它的hwirq是7,它就会从bit7开始查找,bit7如果没有被占用,那么它的虚拟中断号就等于7。万一有其它中断程序使用了上一级的第7号中断,后面EINT7的虚拟中断号就不会等于7,所以我们在驱动程序里指定中断号存在风险,因此我们需要改正这种做法。 | 从原理上我们可以知道网卡使用的是EINT7,对于EINT7它的hwirq是7,它就会从bit7开始查找,bit7如果没有被占用,那么它的虚拟中断号就等于7。万一有其它中断程序使用了上一级的第7号中断,后面EINT7的虚拟中断号就不会等于7,所以我们在驱动程序里指定中断号存在风险,因此我们需要改正这种做法。 | ||
+ | == 网卡设备树节点 == | ||
我们可以先在设备树里声明使用哪一个中断,在网卡中指定中断: | 我们可以先在设备树里声明使用哪一个中断,在网卡中指定中断: | ||
− | + | <syntaxhighlight lang="c" > | |
srom-cs4@20000000 { | srom-cs4@20000000 { | ||
compatible = "simple-bus"; | compatible = "simple-bus"; | ||
第44行: | 第47行: | ||
}; | }; | ||
}; | }; | ||
− | + | </syntaxhighlight> | |
− | 节点 | + | |
+ | 节点<code>srom-cs</code>位于根目录下面,它的<code>compatible</code>是<code>simple-bus</code>,对于<code>simple-bus</code>下面的子节点它也会创建为一个平台设备,它的<code>compatible</code>是<code>davicom,dm9000</code>,我们以后将根据这个值找到对应的驱动程序,在这个节点里面它指定了中断的信息,我们需要修改驱动程序为这个设备节点添加一个<code>platform_driver</code>,在<code>platform_driver</code>的<code>probe()</code>函数里面,把这个中断号确定下来。 | ||
修改代码过程参考视频。 | 修改代码过程参考视频。 | ||
− | + | == 触摸屏设备树节点 == | |
触摸屏的设备树节点如下: | 触摸屏的设备树节点如下: | ||
− | + | <syntaxhighlight lang="c" > | |
jz2440ts@5800000 { | jz2440ts@5800000 { | ||
compatible = "jz2440,ts"; | compatible = "jz2440,ts"; | ||
第62行: | 第66行: | ||
clock-names = "adc"; | clock-names = "adc"; | ||
}; | }; | ||
− | + | </syntaxhighlight> | |
− | 该节点没有指定 | + | |
+ | 该节点没有指定<code>interrupt-parent</code>,中断将发给它的父节点(也就是根节点),在根节点有<code>interrupt-parent = <0x1>;</code>,根据<code>0x01</code>找到<code>phandle</code>。 | ||
+ | |||
触摸屏使用了两个中断,一个是按下/松开时产生的中断,另外一个是ADC的中断。一但触摸屏产生信号,就传给子中断控制器(sub interrupt),再由子中断控制器发给顶级的中断控制器(interrupt controller)。 | 触摸屏使用了两个中断,一个是按下/松开时产生的中断,另外一个是ADC的中断。一但触摸屏产生信号,就传给子中断控制器(sub interrupt),再由子中断控制器发给顶级的中断控制器(interrupt controller)。 | ||
− | + | ||
+ | <code>interrupts</code>后面的4个32位数字含义如下: | ||
+ | |||
第一个表示是发给主控制器还是子控制器,为1表示发给子控制器; | 第一个表示是发给主控制器还是子控制器,为1表示发给子控制器; | ||
+ | |||
第二个表示子中断控制器发给主控制器的哪一个; | 第二个表示子中断控制器发给主控制器的哪一个; | ||
+ | |||
第三个表示是这个中断控制器里的哪一个中断; | 第三个表示是这个中断控制器里的哪一个中断; | ||
+ | |||
第四个表示中断的触发方式; | 第四个表示中断的触发方式; | ||
+ | |||
通过第三个数字可以知道该节点的第0个中断资源是TC,第1个中断是ADC。 | 通过第三个数字可以知道该节点的第0个中断资源是TC,第1个中断是ADC。 | ||
− | + | == 测试 == | |
− | |||
− | |||
两个驱动程序修改完后,分别上传到内核如下目录: | 两个驱动程序修改完后,分别上传到内核如下目录: | ||
− | + | <syntaxhighlight lang="c" > | |
drivers/net/ethernet/davicom | drivers/net/ethernet/davicom | ||
drivers/input/touchscreen | drivers/input/touchscreen | ||
− | + | </syntaxhighlight> | |
+ | |||
测试步骤如下: | 测试步骤如下: | ||
+ | |||
a. 编译内核 | a. 编译内核 | ||
+ | |||
b. 使用新的uImage启动 | b. 使用新的uImage启动 | ||
+ | |||
c. 测试网卡: | c. 测试网卡: | ||
− | + | <syntaxhighlight lang="c" > | |
ifconfig eth0 192.168.1.101 | ifconfig eth0 192.168.1.101 | ||
ping 192.168.1.1 | ping 192.168.1.1 | ||
− | + | </syntaxhighlight> | |
+ | |||
d. 测试触摸屏: | d. 测试触摸屏: | ||
− | + | <syntaxhighlight lang="c" > | |
hexdump /dev/evetn0 // 然后点击触摸屏 | hexdump /dev/evetn0 // 然后点击触摸屏 | ||
− | + | </syntaxhighlight> | |
=第02节_在设备树中时钟的简单使用= | =第02节_在设备树中时钟的简单使用= | ||
=第03节_在设备树中pinctrl的简单使用= | =第03节_在设备树中pinctrl的简单使用= |
2018年11月15日 (四) 11:36的版本
按照计划,本课会讲解修改uboot和内核让JZ2440支持设备树。
但前面修改uboot已经讲解完了,修改内核也没必要单独讲,可以直接看内核补丁,修改的方法也并不复杂。
内核补丁路径:
doc_and_sources_for_device_tree/source_and_images/第5,6课的源码及映像文件(使用了完全版的设备树)/第5课第4节_内核补丁及设备树/linux-4.19-rc3_device_tree_for_irq_jz2440.patch
对内核的修改并不多,里面大部分是移植yaffs,yaffs是一个文件系统,他适合在nand flash上使用,要是对移植yaffs感兴趣的话,可以看看毕业班的视频。
实际上涉及设备树的修改并不多,那我怎么知道修改那些呢?
我使用最笨的方法——添加打印。在发现内核启动卡住后,就沿着内核启动流程调用的函数添加打印,比如在`init.c`函数添加了一系列打印,看它卡在哪个函数,再进入该函数添加打印。
这里打印使用的是early_print()
,因为printk()
很可能还不能使用,early_print()
直接把数据写到串口里面,和硬件驱动没有什么关系。
目录
第01节_使用设备树给DM9000网卡_触摸屏指定中断
在上一课我们把中断体系讲得很清楚了,我们先看一下内核里的网卡驱动程序,所在路径为:
drivers/net/ethernet/davicom/dm9dev9000.c
在这里做了一件非常取巧的事情,以前中断号和硬件绑定时,它的中断号是IRQ_EINT7
,现在我直接偷懒将其赋值为7,实际上这种方法是非常不保险的。
从原理上我们可以知道网卡使用的是EINT7,对于EINT7它的hwirq是7,它就会从bit7开始查找,bit7如果没有被占用,那么它的虚拟中断号就等于7。万一有其它中断程序使用了上一级的第7号中断,后面EINT7的虚拟中断号就不会等于7,所以我们在驱动程序里指定中断号存在风险,因此我们需要改正这种做法。
网卡设备树节点
我们可以先在设备树里声明使用哪一个中断,在网卡中指定中断:
srom-cs4@20000000 {
compatible = "simple-bus";
#address-cells = <1>;
#size-cells = <1>;
reg = <0x20000000 0x8000000>;
ranges;
ethernet@20000000 {
compatible = "davicom,dm9000";
reg = <0x20000000 0x2 0x20000004 0x2>;
interrupt-parent = <&gpf>;
interrupts = <7 IRQ_TYPE_EDGE_RISING>;
local-mac-address = [00 00 de ad be ef];
davicom,no-eeprom;
};
};
节点srom-cs
位于根目录下面,它的compatible
是simple-bus
,对于simple-bus
下面的子节点它也会创建为一个平台设备,它的compatible
是davicom,dm9000
,我们以后将根据这个值找到对应的驱动程序,在这个节点里面它指定了中断的信息,我们需要修改驱动程序为这个设备节点添加一个platform_driver
,在platform_driver
的probe()
函数里面,把这个中断号确定下来。
修改代码过程参考视频。
触摸屏设备树节点
触摸屏的设备树节点如下:
jz2440ts@5800000 {
compatible = "jz2440,ts";
reg = <0x58000000 0x100>;
reg-names = "adc_ts_physical";
interrupts = <1 31 9 3>, <1 31 10 3>;
interrupt-names = "int_ts", "int_adc_s";
clocks = <&clocks PCLK_ADC>;
clock-names = "adc";
};
该节点没有指定interrupt-parent
,中断将发给它的父节点(也就是根节点),在根节点有interrupt-parent = <0x1>;
,根据0x01
找到phandle
。
触摸屏使用了两个中断,一个是按下/松开时产生的中断,另外一个是ADC的中断。一但触摸屏产生信号,就传给子中断控制器(sub interrupt),再由子中断控制器发给顶级的中断控制器(interrupt controller)。
interrupts
后面的4个32位数字含义如下:
第一个表示是发给主控制器还是子控制器,为1表示发给子控制器;
第二个表示子中断控制器发给主控制器的哪一个;
第三个表示是这个中断控制器里的哪一个中断;
第四个表示中断的触发方式;
通过第三个数字可以知道该节点的第0个中断资源是TC,第1个中断是ADC。
测试
两个驱动程序修改完后,分别上传到内核如下目录:
drivers/net/ethernet/davicom
drivers/input/touchscreen
测试步骤如下:
a. 编译内核
b. 使用新的uImage启动
c. 测试网卡:
ifconfig eth0 192.168.1.101
ping 192.168.1.1
d. 测试触摸屏:
hexdump /dev/evetn0 // 然后点击触摸屏