本文基于前面移植好的uboot进行的实验的。
工具链:https://github.com/rockchip-toybrick/prebuilts-gcc-linux-x86-arm-gcc-linaro-6.3.1-2017.05-x86_64_arm-linux-gnueabihf.git
源码:去官网下载4.2的源码 https://mirrors.edge.kernel.org/pub/linux/kernel/v4.x/
解压从我资源下载的rootfs.tar.gz(这个好像没有办法弄个免费的。。。。)
#!/bin/sh
dd if=/dev/zero of=ramdisk bs=1k count=15000
mkfs.ext4 -F ramdisk
mkdir -p ./initrd
sudo mount -t ext4 ramdisk ./initrd
cp rootfs/* ./initrd -raf
sudo mknod initrd/dev/console c 5 1
sudo mknod initrd/dev/null c 1 3
sudo umount ./initrd
sudo gzip --best -c ramdisk > ramdisk.gz
sudo mkimage -n "ramdisk" -A arm -O linux -T ramdisk -C gzip -d ramdisk.gz ramdisk.img
由于我之前烧录到emmc的uboot是没有dnw命令的,所以我先从sd卡启动,然后烧录系统,再切到emmc启动,使用我们自己移植的uboot启动内核
1)官方下载4.20源码
2)修改顶层Makefile
+ARCH = arm
+CROSS_COMPILE = arm-linux-gnueabihf-
3)make exynos_defconfig
4)编译 uImage
make uImage LOADADDR=0x40008000 -j8 ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf-
5)编译dtbs
make dtbs
6)解压从我资源下载并编译出来的ramdisk.img
7) sd卡启动uboot(前面《tiny4412 uboot 2018移植(二)移植》安装的uboot_tiny4412_0726.tar.gz),进入命令行模式,ubuntu 配合使用以下命令下载uImage ramdisk.img exynos4412-tiny4412.dtb 到4412的内存中
dnw 0x40600000
sudo dnw arch/arm/boot/uImage
dnw 0x42000000
sudo dnw …/ramdisk.img
dnw 0x43000000
sudo dnw arch/arm/boot/dts/exynos4412-tiny4412.dtb
8)切到emmc启动
9) 启动内核
bootm 0x40600000 0x42000000 0x43000000
以上步骤执行完毕后发现只走到以下log
## Booting kernel from Legacy Image at 40600000 ...
Image Name: Linux-4.20.0-ga579a36-dirty
Image Type: ARM Linux Kernel Image (uncompressed)
Data Size: 6797600 Bytes = 6.5 MiB
Load Address: 40008000
.........省略
Loading Device Tree to 4fd79000, end 4fd871a7 ... OK
Starting kernel ...
一般来说是串口没设置对,在arch/arm/boot/dts/exynos4412-tiny4412.dts中添加下面这一行,然后去menuconfig中把earlyprintk的开关打开(为了调试)
chosen {
stdout-path = &serial_0;
+ bootargs = "root=/dev/ram0 rw rootfstype=ext4 console=ttySAC0,115200 init=/linuxrc earlyprintk";
};
烧录之后运行,发现出现
[ 1.295199] Unhandled fault: imprecise external abort (0x1406) at 0x00000000
[ 1.302075] pgd = (ptrval)
[ 1.304765] [00000000] *pgd=00000000
[ 1.308328] Internal error: : 1406 [#1] PREEMPT SMP ARM
[ 1.313532] Modules linked in:
[ 1.316572] CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.20.0-ga579a36-dirty #2
[ 1.323774] Hardware name: SAMSUNG EXYNOS (Flattened Device Tree)
[ 1.329863] PC is at exynos_sysmmu_probe+0x240/0x30c
[ 1.334807] LR is at __sysmmu_enable_clocks+0xa0/0xd8
用工具反汇编vmlinux,查看是crash在哪里
arm-linux-gnueabihf-objdump -S vmlinux >vmlinux.S
__sysmmu_enable_clocks(data);
c0f33ce0: e1a00006 mov r0, r6
c0f33ce4: ebd7d54d bl c0529220 <__sysmmu_enable_clocks>
ver = readl(data->sfrbase + REG_MMU_VERSION);
c0f33ce8: e596300c ldr r3, [r6, #12]
c0f33cec: e5933034 ldr r3, [r3, #52] ; 0x34
c0f33cf0: f57ff04f dsb sy
if (ver == 0x80000001u)
c0f33cf4: e3530106 cmp r3, #-2147483647 ; 0x80000001
dev_dbg(data->sysmmu, "hardware version: %d.%d\n",
c0f33cf8: e3030c08 movw r0, #15368 ; 0x3c08
data->version = MMU_RAW_VER(ver);
c0f33cfc: 11a03aa3 lsrne r3, r3, #21
data->version = MAKE_MMU_VER(1, 0);
c0f33d00: 03a03080 moveq r3, #128 ; 0x80
可以看出是崩溃在__sysmmu_get_version函数的if (ver == 0x80000001u)这一行代码之前,在这里添加打印,发现是使用data->sfrbase这个虚拟地址造成的crash。这个地址是在exynos_sysmmu_probe中使用data->sfrbase = devm_ioremap_resource(dev, res);去remap的,在这一行添加打印,打印出res(也就是struct resource)的成员resource_size_t start的地址,结合__sysmmu_get_version中的打印,发现是使用remap起始物理地址为0x122a0000和 122b0000之后的虚拟物理地址出现crash。经查找,物理地址0x122a0000和122b0000对应的组件在exynos4412.dtsi中,这两个组件是sysmmu_fimc相关的,目前还不用用到,我直接先disable。
sysmmu_fimc_fd: sysmmu@122a0000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x122A0000 0x1000>;
interrupt-parent = <&combiner>;
interrupts = <16 4>;
power-domains = <&pd_isp>;
clock-names = "sysmmu";
clocks = <&isp_clock CLK_ISP_SMMU_FD>;
+ status = "disabled";
#iommu-cells = <0>;
};
sysmmu_fimc_mcuctl: sysmmu@122b0000 {
compatible = "samsung,exynos-sysmmu";
reg = <0x122B0000 0x1000>;
interrupt-parent = <&combiner>;
interrupts = <16 5>;
power-domains = <&pd_isp>;
clock-names = "sysmmu";
clocks = <&isp_clock CLK_ISP_SMMU_ISPCX>;
+ status = "disabled";
#iommu-cells = <0>;
};
修改之后重新编译运行,就好了。这个修改方式属于临时修改,后面移植camera的时候已修复这个bug。