tiny4412 linux-4.2 移植(一)编译运行linux-4.2

简介

本文基于前面移植好的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/

0、生成ramdisk

解压从我资源下载的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

1、编译

由于我之前烧录到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

2、发现问题

以上步骤执行完毕后发现只走到以下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";
    };

3、重新烧录运行

烧录之后运行,发现出现

[    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。

你可能感兴趣的:(Tiny4412,Linux_4.2移植)