Just Do It

imx287A uboot2017.09移植

Linux4.14初步移植
http://blog.centerking.top/index.php/2020/02/02/imx287a-linux4-14/

u-boot源码下载 https://ftp.denx.de/pub/u-boot/
在这里选用的时zlg提供的交叉编译器,由于版本原因uboot2018之后需要使用新的版本,所以选择uboot2017.09这一版本
下载完成后将ARCH=arm CROSS_COMPILE=arm-fsl-linux-gnueabi-这部分填进Makefile里面
这样之后的编译就不用在附带那么长的参数

make distclean
make mx28evk_nand_defconfig
make

在编译时可能出现报错

tools/mxsimage.c:18:10: fatal error: openssl/evp.h: No such file or directory

该错误是由于缺少OpenSSL直接apt安装就可以了

sudo apt-get install libssl-dev

编译完成后烧录进去会卡死在DRAM:
追踪源码发现是在board_f的dram_init
该函数的实现在board/freescale/mx28evk/mx28evk.c

int dram_init(void)
{
    return mxs_dram_init();
}

追踪在arch/arm/cpu/arm926ejs/mxs/mxs.c添加一行如下(下面有注释的一行)

int mxs_dram_init(void)
{
    struct mxs_spl_data *data = (struct mxs_spl_data *)
        ((CONFIG_SYS_TEXT_BASE - sizeof(struct mxs_spl_data)) & ~0xf);

    if (data->mem_dram_size == 0) {
        printf("MXS:\n"
            "Error, the RAM size passed up from SPL is 0!\n");
        hang();
    }
    <strong>data->mem_dram_size = 128*1024*1024;//由于使用imx287A 内存128M 这里直接写死 如果需要支持不同板卡参考zlg源码</strong>
    gd->ram_size = data->mem_dram_size;
    return 0;
}

到这里编译烧入uboot已经能够正常运行了
接下来需要做的就是引导内核(这里使用的是zlg提供的Linux2.6.35)
直接更改环境参数在include/configs/mx28evk.h
找到

/* Extra Environment */
#define CONFIG_EXTRA_ENV_SETTINGS \

在下面添加

"bootargs_nand=setenv bootargs gpmi=g console=ttyAM0,115200n8 ubi.mtd=5 root=ubi0:rootfs rootfstype=ubifs ro\0"\
"nand_boot=set bootargs_nand;setenv;nand read.jffs2 0x42000000 0x200000 0x400000;bootm 0x42000000;\0"\


同时将CONFIG_BOOTCOMMAND宏更改为下面这样

#define CONFIG_BOOTCOMMAND "run nand_boot"

以上这些命令可以不添加在源码直接在uboot中输入执行
######################################################

nand read.jffs2 0x42000000 0x200000 0x400000;bootm 0x42000000

将nandflash的0x200000地址处的0x400000字节拷贝到0x42000000,并用bootm引导。其中bootm后可不加参数,会默认从程序中规定的base地址执行(在这里也就是该地址)
关于nand read命令的一些差别如下

nand write:向Nand Flash写入数据,如果NandFlash相应的区域有坏块,则直接报错。
nand write.jffs2:向Nand Flash写入数据,如果NandFlash相应的区域有坏块,可以跳过坏块。
nand read:读取Nand Flash相应区域的数据,如果NandFlash相应的区域有坏块,则直接报错。
nand read.jffs2s:读取Nand Flash相应区域的数据,如果NandFlash相应的区域有坏块,将对应坏块区域的缓冲填充0xff,然后跳过此坏块继续读取。
nand read.jffs2:读取Nand Flash相应区域的数据,如果NandFlash相应的区域有坏块,直接跳过坏块

编译烧录发现在打印完下面字符后会卡死

Loading Kernel Image ...

下面这一部分是一些调试过程,能力有限没能解决,做个记录。如有大佬解决且愿意指点下可发送邮件到leiyifan98@163.com。
可跳过下面一部分直接看解决方案

追踪源码发现是common/bootm.c在调用memmove_wd出了问题,该函数调用lib/string.c下的memmove

void * memmove(void * dest,const void *src,size_t count)
{
    char *tmp, *s;

    if (dest <= src) {
        memcpy(dest, src, count);
    } else {
        tmp = (char *) dest + count;
        s = (char *) src + count;
        while (count--)
            *--tmp = *--s;
        }

    return dest;
}

最终执行的是memcpy分支,该memcpy在arch/arm/lib/memcpy.S下定义,由于本人太菜汇编玩不转,在这里将memcpy(dest, src, count);替换成下面代码方便打印观察

tmp = (char *) dest;
s = (char *) src;
while (count--){
    *tmp++ = *s++;
}

最后发现在写内存到0x400155aa附近的时候卡死,并且在uboot中使用nand read命令像该部分写入也会导致卡死。
在这里尝试查看内存数据

md [内存地址] [长度]
md.d 0x02000000 128
表示显示0x02000000的内存数据,长度为128个8bit.
mw [内存地址] [值] [长度]
mw.d 0x02000000 0 128
表示修改地址为0x02000000~0x02000000+128的内存值为0.
命令后面的参数意义如下
b:8位
w:16位
l:32位(默认值)

期间碰到以下问题(这里由于当时没有记录,复制的别人博客的报错)

data abort
pc : [<7fe50764>]   lr : [<7fe73cf8>]
sp : 76ddfa58  ip : 00000000 fp : 4a0009b0
r10: 4a019540  r9 : 76df7e40 r8 : 000001e0
r7 : 00000500  r6 : 78a08df0 r5 : 7fedc238  r4 : 78108db0
r3 : 78108da8  r2 : 9b969796 r1 : 13a7253e  r0 : 00000001
Flags: nzCv  IRQs on  FIQs off  Mode SVC_32
Resetting CPU ...

反编译uboot,查看具体出错在哪

arm-linux-objdump -D u-boot>u-boot.s

能力有限,没能解决将内核拷贝到0x40008000的bug

在uboot下解决不了该问题只好从内核下手了。
uImage是在zImage前加上了64字节的头部,在头部里有着一些信息。
在这里我们需要更改内核需要解压到的地址以及启动地址
这里为了方便我直接将地址改为从nand flash读取到内存的位置
可以在编译uImage时添加一个参数如下

make uImage LOADADDR=42000000

或者直接使用mkimage工具对zImage进行操作如下
mkimage命令格式如下:

# mkimage [-x] -A arch -O os -T type -C comp -a addr -e ep -n name -d data_file[:data_file...] image

其中各字段含义

-x 指定内核就在Flash中运行,即XIP(execute in place)
-T 指定输入文件的类型,如“kernel”、“filesystem”、“firmware”、“ramdisk”
-A 指定处理器体系架构
-O 指定操作系统类型名字,如“linux”、“vxworks”、“psos”等
-C 指定压缩模式,可能设置为“none”、“bzip2”、“gzip”
-a 指定程序被解压缩或复制到RAM中的地址
-e 指定程序(内核)的入口地址
-n 指定image文件的名字
-d 指定输入的程序文件,可是有多个文件,如内核或/和根文件系统二进制文件
image 输出文件名

比如这里我使用如下命令

mkimage -A arm -O linux -T kernel -C none -a 0x42000000 -e 0x42000000 -n imx287A -d zImage uImage

到这里将uboot uImage 文件系统烧录即可

本人自己编译的源码地址https://github.com/CenterKing/imx287A-uboot2017.09

Linux4.14初步移植
http://blog.centerking.top/index.php/2020/02/02/imx287a-linux4-14/

To Be Continued…

点赞

发表评论

电子邮件地址不会被公开。 必填项已用*标注