1.linux 内核包含七大子系统
1、内存管理子系统 负责 寻找空闲的虚拟地址 和 物理地址进行映射 一旦系统启动 程序都是面想虚拟地址编程 。寄存器地址指针 操作物理地址的方式将不复存在。
如果没有操作系统,内存是需要程序自己来管理的。譬如在uboot中要使用内存的哪里是自己随便用的,没有注册也没有限制。这时候如果程序自己不小心把同一块内存重复用了就会出现程序逻辑错误。系统大了之后(内存多了)内存管理非常麻烦;有了操作系统之后,操作系统负责管控所有的内存,所有的应用程序需要使用内存时都要向操作系统去申请和注册,由操作系统的内存管理模块来分配内存给你使用,这样好处是可以保证内存使用不会冲突
2、进程管理子系统 负责 多进程多任务处理 提高 CPU的处理能力 ,宏观上的并行就是操作系统提供的分时复用机制,提高 CPU的使用率 和 即时处理能力,完成 每个进程的。
调度 管理,销毁,PCB资源记录。 进程就是人 PCB就是户口本,对每个人进行管理。
操作系统下支持多个应用程序同时运行(所以可以一边聊QQ一边看电影···),这是宏观上的并行。实际上在单核心CPU上微观上是不能并行的,宏观上的并行就是操作系统提供的分时复用机制。操作系统的进程调度模块负责在各个进程之间进行切换。
3、设备管理系统 负责 和 每个硬件 设备进行 通过通信交互的 接口 ,它将以 文件 的方式 ,被用户程序进行访问。
没有操作系统时要控制任何硬件都要自己写代码,有了操作系统后操作系统本身会去控制各个硬件,应用程序就不用考虑硬件的具体细节了。操作系统的硬件设备管理模块就是驱动模块。
4、网络管理系统 负责 网络协议栈 网络设备的 管理,通过它能和 其他计算机 设备进行 通信。牛不牛逼。
5、文件管理系统 将系统里的一切静态存放的东西 抽象成目录 和 文件的方式 可以被用户直观的进行 交互。
文件系统是管理存储设备的一种方式。存储设备是由很多个扇区组成的,每个扇区有512/1024/2048/4096字节,存储设备要以扇区为单位进行读写。如果没有文件系统,程序要自己去读写扇区,就得记得哪个文件在哪个扇区。有了文件系统之后我们人不用再关注扇区,人只用关注文件系统中的目录和文件名,而不用管这个文件在物理磁盘的哪个扇区。
6、系统调用 提供 用户层与 linux 内核 交互的接口,也是和系统交互的唯一方式,没有之一。
7、平台相关 支持芯片架构相关 多种不同的硬件架构。
2、linux 内核编译流程
2.1 修改源码目录
mv linux-imx-rel_imx_4.1.15_2.1.0_ga linux-imx-test
2.2 修改顶层 Makefile 里面的 ARCH 和 CROSS_COMPILE
ARCH=arm
CROSS_COMPILE=arm-linux-gnueabihf-
2.3 make clean
清理一下linux 内核之前的文件
2.4 配置 Linux 内核
make imx_v7_mfg_defconfig
2.5 编译内核
make -j4
2.6 编译输出文件
①、
arch/arm/boot/
:
zImage
。
②、
arch/arm/boot/dts
:
imx6ull-alientek-emmc.dtb
。
3. 移植到目标板
3.1 添加开发板默认配置文件
cd arch/arm/configs
cp imx_v7_mfg_defconfig imx_alientek_emmc_defconfig
3.2 配置目标板的配置文件
make imx_alientek_emmc_defconfig
3.3 添加设备树
cd arch/arm/boot/dts
cp imx6ull-14x14-evk.dts imx6ull-alientek-emmc.dts
3.4 vim Makefile
imx6ull
-
14x14
-
evk
-
usb
-
certi
.
dtb \ 后面添加下面这行
imx6ull-alientek-emmc.dtb \
3.5 制作编译脚本
imx6ull_alientek_emmc.sh
,
#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_alientek_emmc_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
chmod 777 imx6ull_alientek_emmc.sh
//
给予可执行权限
./imx6ull_alientek_emmc.sh
//
执行
shell
脚本编译内核
3.6 调整主频策略
cd arch/arm/boot/dts vim imx_alientek_emmc_defconfig
屏蔽 41 CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
=
y
在 44
CONFIG_CPU_FREQ_GOV_INTERACTIVE
=
y
后面添加 CONFIG_CPU_FREQ_GOV_ONDEMAND
=
y
验证:cat /sys/devices/system/cpu/cpu0/cpufreq/ cpuinfo_cur_freq
文件 792000
图形化文档进行配置
3.7 修改 EMMC 驱动 EMMC 是 8线驱动 但是 linux 内核默认的是 4线模式
直接修改设备树
usdhc2 改为 make dtbs 重新编译一下设备树
&usdhc2 {
pinctrl-names = "default", "state_100mhz", "state_200mhz";
pinctrl-0 = <&pinctrl_usdhc2_8bit>;
pinctrl-1 = <&pinctrl_usdhc2_8bit_100mhz>;
pinctrl-2 = <&pinctrl_usdhc2_8bit_200mhz>;
bus-width = <8>;
non-removable;
status = "okay";
};
3.8 修改网络驱动
imx6ull-alientek-emmc.dts
网络
PHY
芯片由
KSZ8081
换为了
LAN8720A
,两个网络
PHY
芯片的复位
IO
也不同。
所以
Linux
内核自带的网络驱动是驱动不起来
I.MX6U-ALPHA
开发板上的网络的。
ENET1 复位引脚 ENET1_RST 连接在 I.M6ULL 的 SNVS_TAMPER7 这个引脚上。
ENET2 的复位引脚 ENET2_RST 连接在 I.MX6ULL 的 SNVS_TAMPER8 上。
584
pinctrl_spi4
:
spi4grp
{ 中
删除
MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07
0x70a1
MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08
0x80000000
129
pinctrl
-
assert
-
gpios
= <&
gpio5
8
GPIO_ACTIVE_LOW
>;
133
cs
-
gpios
= <&
gpio5
7 0
>;
第
129
行,设置
GPIO5_IO08
为
SPI4
的一个功能引脚
(
我也不清楚具体作为什么功能用
)
,
而
GPIO5_IO08
就是
SNVS_TAMPER8
的
GPIO
功能引脚。
第
133
行,设置
GPIO5_IO07
作为
SPI4
的片选引脚,而
GPIO5_IO07
就是
SNVS_TAMPER7
的
GPIO
功能引脚。
pinctrl_enet1_reset: enet1resetgrp {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER7__GPIO5_IO07 0x10B0
>;
};
pinctrl_enet2_reset: enet2resetgrp {
fsl,pins = <
MX6ULL_PAD_SNVS_TAMPER8__GPIO5_IO08 0x10B0
>;
};
增加配置菱角
309
pinctrl_enet1
:
enet1grp
{
317
MX6UL_PAD_ENET1_TX_DATA1__ENET1_TDATA01
0x1b0b0
318 MX6UL_PAD_ENET1_TX_CLK__ENET1_REF_CLK1 0x4001b009
322
pinctrl_enet2
:
enet2grp
{
332
MX6UL_PAD_ENET2_TX_DATA1__ENET2_TDATA01
0x1b0b0
333 MX6UL_PAD_ENET2_TX_CLK__ENET2_REF_CLK2 0x4001b009
&
fec1
{
pinctrl
-
names
=
"default"
;
pinctrl-0 = <&pinctrl_enet1
&pinctrl_enet1_reset>;
pinctrl-0 = <&pinctrl_enet2
&pinctrl_enet2_reset>;
171
&
fec1
{
172
pinctrl
-
names
=
"default"
;
173
pinctrl
-
0
= <&
pinctrl_enet1
174
&
pinctrl_enet1_reset
>;
175
phy
-
mode
=
"rmii"
;
176
phy
-
handle
= <&
ethphy0
>;
177 phy-reset-gpios = <&gpio5 7 GPIO_ACTIVE_LOW>;
178 phy-reset-duration = <200>;
179
status
=
"okay"
;
180
};
182
&
fec2
{
183
pinctrl
-
names
=
"default"
;
184
pinctrl
-
0
= <&
pinctrl_enet2
185
&
pinctrl_enet2_reset
>;
186
phy
-
mode
=
"rmii"
;
187
phy
-
handle
= <&
ethphy1
>;
188 phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>;
189 phy-reset-duration = <200>;
190
status
=
"okay"
;
196
ethphy0
:
ethernet
-
phy@
0
{
197
compatible
=
"ethernet-phy-ieee802.3-c22"
;
198 smsc,disable-energy-detect;
199
reg
= <
0
>;
200
};
202
ethphy1
:
ethernet
-
phy@1
{
203
compatible
=
"ethernet-phy-ieee802.3-c22"
;
204 smsc,disable-energy-detect;
205
reg
= <
1
>;
206
};
修改
drivers/net/ethernet/freescale/fec_main.c
,
函数
fec_probe
void __iomem *IMX6U_ENET1_TX_CLK;
void __iomem *IMX6U_ENET2_TX_CLK;
IMX6U_ENET1_TX_CLK = ioremap(0X020E00DC, 4);
writel(0X14, IMX6U_ENET1_TX_CLK);
IMX6U_ENET2_TX_CLK = ioremap(0X020E00FC, 4);
writel(0X14, IMX6U_ENET2_TX_CLK);
LAN8720A
的驱动文件是
drivers/net/phy/smsc.c
,
#include <linux/of_gpio.h>
#include <linux/io.h>
smsc_phy_reset 函数
int err, phy_reset;
int msec = 1;
struct device_node *np;
int timeout = 50000;
if(phydev->addr == 0) /* FEC1 */ {
np = of_find_node_by_path("/soc/aips-bus@02100000/ethernet@02188000");
if(np == NULL) {
return -EINVAL;
}
}
if(phydev->addr == 1) /* FEC2 */ {
np = of_find_node_by_path("/soc/aips-bus@02000000/ethernet@020b4000");
if(np == NULL) {
return -EINVAL;
}
}
err = of_property_read_u32(np, "phy-reset-duration", &msec);
/* A sane reset duration should not be longer than 1s */
if (!err && msec > 1000)
msec = 1;
phy_reset = of_get_named_gpio(np, "phy-reset-gpios", 0);
if (!gpio_is_valid(phy_reset))
return;
gpio_direction_output(phy_reset, 0);
gpio_set_value(phy_reset, 0);
msleep(msec);
gpio_set_value(phy_reset, 1);
输入命令“
make menuconfig
”,打开图形化配置界面
选择使能
LAN8720A
的驱动
-> Device Drivers
-> Network device support
-> PHY Device support and infrastructure
-> Drivers for SMSC PHYs
勾选这个以后就会编译 LAN8720 驱动
3.9 网络驱动测试:
修改好设备树和
Linux
内核以后重新编译一下,得到新的
zImage
镜像文件和
imx6ull
alientek-emmc.dtb
设备树文件
查看网卡设备
ifconfig -a
打开网卡
ifconfig eth0 up
ifconfig eth1 up
SMSC LAN8710/LAN8720 当前的
网络驱动使用的 就是我们前面使能的 SMSC 驱动
。
ping 一下能ping成功说明 网络驱动修改成功。
保存修改后的图形化配置文件
.config
CONFIG_SMSC_PHY=y
drivers/net/phy/Makefile
,
obj
-
$
(
CONFIG_SMSC_PHY
)
+=
smsc
.
o
直接将
.config
文件另 存为 imx_alientek_emmc_defconfig
imx_alientek_emmc_defconfig
3.linux 系统移植终极总结
①、在 Linux 内核中查找可以参考的板子,一般都是半导体厂商自己做的开发板。
②、编译出参考板子对应的 zImage 和.dtb 文件。
③、使用参考板子的 zImage 文件和.dtb 文件在我们所使用的板子上启动 Linux 内核,看能
否启动。
④、如果能启动的话就万事大吉,如果不能启动那就悲剧了,需要调试 Linux 内核。不过
一般都会参考半导体官方的开发板设计自己的硬件,所以大部分情况下都会启动起来。启动
Linux 内核用到的外设不多,一般就 DRAM(Uboot 都初始化好的)和串口。作为终端使用的串口
一般都会参考半导体厂商的 Demo 板。
⑤、修改相应的驱动,像 NAND Flash、EMMC、SD 卡等驱动官方的 Linux 内核都是已经
提供好了,基本不会出问题。重点是网络驱动,因为 Linux 驱动开发一般都要通过网络调试代
码,所以一定要确保网络驱动工作正常。如果是处理器内部 MAC+外部 PHY 这种网络方案的
话,一般网络驱动都很好处理,因为在 Linux 内核中是有外部 PHY 通用驱动的。只要设置好复
位引脚、PHY 地址信息基本上都可以驱动起来。
⑥、Linux 内核启动以后需要根文件系统,如果没有根文件系统的话肯定会崩溃,所以确定 Linux
内核移植成功以后就要开始根文件系统的构建。