NXP从linux官网下载内核,然后移植到自己的CPU,我们的移植是基于NXP,再移植到自己的开发板。
制作一个sh:
#!/bin/sh
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- all -j16
需要关注的文件夹和文件如下:
Linux顶层Makefile主要就是生成vmlinux并压缩成zImage。
关于几个编译出来的文件:
①vmlinux:最原始的内核文件,未压缩的。
②Image:Linux内核镜像文件,仅包含可执行的二进制数据。
③zImage:zImage是gzip压缩后的Image。
④uImage:老版本uboot专用的镜像文件。比zImage多一些头部信息。
查看linux内核的链接脚本文件arch/arm/kernel/vmlinux.lds:
ENTRY(stext) /*指明Linux内核入口为stext*/
stext在arch/arm/kernel/head.S中,简单概括一下其流程:
①__lookup_processor_type:找到对应处理器的procinfo结构。
②__vet_atags:验证设备树的合法性。
③__create_page_tables:创建页表。
④__mmap_switched:调用start_kernel函数。
⑤__enable_mmu:使能MMU,执行__mmap_switched。
start_kernel函数最终调用了rest_init(init/main.c),简单流程概括为:
①rcu_scheduler_starting:启动RCU锁调度器。
②kernel_thread:创建kernel_init内核进程,PID=1。实现内核态到用户态的转变。
③kernel_thread:创建kthreadd内核进程,PID=2。负责进行所有内核进程的调度管理。
④cpu_startup_entry:进入idle(空闲)进程,PID=0。
ps -A /*在linux终端输入该命令以查看当前所有进程(不显示内核态进程)*/
Linux内核构建完成后挂载rootfs根文件系统,执行根文件系统中的init程序进入用户态。
根文件系统存放是有uboot的bootargs环境变量指定的。这里bootargs如下,根文件系统存储在/dev/mmcblk1p2也就是EMMC的分区2。
console=ttymxc0,115200 root=/dev/mmcblk1p2 rootwait rw
实际做产品的话新硬件是没有对应的根文件系统的,在这之前linux内核没有rootfs,启动时会报根文件系统缺失错误。提示内核崩溃,VFS虚拟文件系统不能挂载根文件系统(内核依然是启动的)。
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)
编译了NXP的evk板子对应内核,可以在正点原子EMMC板上启动,所以基于NXP的imx_v7_mfg_config添加自己的开发板。
复制imx_v7_mfg_config为imx_alientek_emmc_defconfig,做如下修改:注释掉“CONFIG_ARCH_MULTI_V6=y”。6ULL是V7架构,所以要屏蔽掉V6相关选项。
复制imx6ull-14x14-evk.dts为imx6ull-alientek-emmc.dts,修改对应层级Makefile,在“dtb-
$(CONFIG_SOC_IMX6ULL)”配置项中加入imx6ull-alientek-emmc.dtb,确保dts可以编译为dtb。
这里编译了一下,成功启动了linux,说明开发板添加上去了,但是还要修改一些配置。
启动linux内核并查看一下cpu信息,如下,MogoMIPS代表处理器性能:
上面看不到主频,进入一下目录中查看,CPU频率为792MHz。
使用如下命令查看CPU在各频率下的工作时长:
查看CPU调频策略,这里performance表示一直运行在最高频,但是实际开发中建议切换为ondemand模式,根据负载自动切换频率。
**1)使能8线EMMC驱动:**将imx6ull-alientek-emmc.dts中“&usdhc2”的内容修改为:
&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;
no-1-8-v;
status = "okay";
};
2)关闭EMMC 1.8V供电选项:
正点原子emmc板EMMC工作电压为3.3V,所以要关闭1.8V选项避免驱动出现问题。在上面的“&usdhc2”加入“no-1-8-v;”
NXP的板子和我们的板子不是一个PHY芯片,它将SR8201F需要的引脚给spi4用了,所以先在dts文件里去除相关配置。然后在dts的“iomuxc_snvs”节点里添加如下网络引脚复位信息。
然后修改fec1和fec2节点的pinctrl-0属性,在里面加上&pinctrl_enetx_reset。接下来修改SR8201F的PHY地址,在fec1和2节点中添加以下内容:
phy-reset-gpios = <&gpio5 8 GPIO_ACTIVE_LOW>; /*ENET1为GPIO5_IO07,ENET2为08*/ /*低电平有效*/
phy-reset-duration = <200>; /*复位电平信号持续时间200ms*/
smsc,disable-energy-detect; /*表明PHY芯片时SMSC公司的,内核就会找到相应驱动驱动LAN8720A*/
在fec_main.c文件中的fec_reset_phy函数最后再加一句“msleep(200)”,因为复位结束后至少还要再过150ms才可以继续操作SR8201F。
测试:
linux启动后,输入ifconfig -a查看所有网卡。然后输入ifconfig eth0 up启动ENET2,有ip地址说明开启了。可以使用ifconfig eth0 xxx配置其ip地址。