ILD

uboot移植学习1:编译与start.S
作者:Herbert Yuan 邮箱:yuanjp@hust.edu.cn
发布时间:2017-11-28 站点:Inside Linux Development

本文,使用开发板JZ2240配套的u-boot-1.1.6学习uboot移植,但是使用之前编译的toolchain。其eabi为新的EABI,老的toolchian为old eabi。


1 配置

主Makefile添加:

1
2
100ask24x0_config   :   unconfig
     @$(MKCONFIG) $(@:_config=) arm arm920t 100ask24x0 NULL s3c24x0zh

MKCONFIG是一个脚本mkconfig。


执行:

1
make O=/work/s3c2440/object/u-boot-1.1.6 100ask24x0_config


O选项,配置编译目录,不在源码目录编译,mkconfig脚本,创建几个文件:

1
2
3
4
5
6
7
8
9
10
11
12
13
herbert@herbert-pc:/work/s3c2440/object/u-boot-1.1.6$ tree
.
├── include
│   ├── asm -> asm-arm
│   ├── asm-arm
│   │   ├── arch -> ../../include2/asm/arch-s3c24x0
│   │   └── proc -> ../../include2/asm/proc-armv
│   ├── config.h
│   └── config.mk
└── include2
    └── asm -> /work/s3c2440/u-boot-1.1.6/include/asm-arm
 
7 directories, 2 files


config.h头文件,包含真正的配置文件。

1
2
3
herbert@herbert-pc:/work/s3c2440/object/u-boot-1.1.6$ cat include/config.h
/* Automatically generated - do not edit */
#include <configs/100ask24x0.h>


config.mk的内容:

1
2
3
4
5
herbert@herbert-pc:/work/s3c2440/object/u-boot-1.1.6$ cat include/config.mk 
ARCH   = arm
CPU    = arm920t
BOARD  = 100ask24x0
SOC    = s3c24x0


2 编译

因为主Makefile使用CROSS_COMPILE变量来存储交叉编译工具的前缀,arm默认为arm-linux-,和我自己的编译工具不同,所以,添加CROSS_COMPILE定义到config.mk

1
2
echo "CROSS_COMPILE := /work/toolchain/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-" \
 > ../object/u-boot-1.1.6/include/config.mk


执行编译:

1
make O=/work/s3c2440/object/u-boot-1.1.6 2>&1 | tee ../make.u-boot-1.1.6.log


编译,最后链接阶段报错:

1
/work/toolchain/arm-unknown-linux-gnueabi/bin/arm-unknown-linux-gnueabi-ld.bfd: error: Source object /work/toolchain/arm-unknown-linux-gnueabi/bin/../lib/gcc/arm-unknown-linux-gnueabi/6.3.0/libgcc.a(_udivdi3.o) has EABI version 5, but target u-boot has EABI version 0

EABI和libgcc.a的EABI不匹配,查看log发现,编译时有:-march=armv4 -mabi=apcs-gnu选项,这个选项导致不匹配,去掉这个选项,


往lib_arm/div0.c添加raise(),编译还是报错。可能是链接使用lib_arm.a导致的,后续在来学习ld符号解析的过程。

添加cpu/arm920t/raise.c,在里面添加raise()函数,Makefile添加 OBJS += cpu/$(CPU)/raise.o可正常编译。然而烧录后,起来无反应,后续来解决。


编译的目标:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
cpu/arm920t/start.o
cpu/arm920t/raise.o
lib_generic/libgeneric.a 
board/100ask24x0/lib100ask24x0.a 
cpu/arm920t/libarm920t.a 
cpu/arm920t/s3c24x0/libs3c24x0.a 
lib_arm/libarm.a 
fs/cramfs/libcramfs.a 
fs/fat/libfat.a 
fs/fdos/libfdos.a 
fs/jffs2/libjffs2.a 
fs/reiserfs/libreiserfs.a 
fs/ext2/libext2fs.a 
net/libnet.a 
disk/libdisk.a 
rtc/librtc.a 
dtt/libdtt.a 
drivers/libdrivers.a 
drivers/nand/libnand.a 
drivers/nand_legacy/libnand_legacy.a 
drivers/usb/libusb.a 
drivers/sk98lin/libsk98lin.a 
common/libcommon.a


接下来分析源码。


3 start.S

相关初始化如下:


reset执行的操作

1 设置CPU模式为SVC模式。

2 关闭看门狗

3  屏蔽所有中断

5 cpu_init_crit

    清除cache,disable MMU,跳转到lowlevel_init

    lowlevel_init.S 初始化sdram

6 设置栈

7 clock_init (board/100ask24x0/boot_init.c)

8 CopyCode2Ram (board/100ask24x0/boot_init.c)

    初始化nand,拷贝数据

9 bss段清0

10 跳到_start_armboot() c代码执行


4 切换新toolchain起不来问题

定位到是韦东山同学添加的下述函数导致的:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
int bBootFrmNORFlash(void)
{
 
    volatile unsigned int *pdw = (volatile unsigned int *)0;
    unsigned int dwVal;
     
    /*
     * 无论是从NOR Flash还是从NAND Flash启动,
     * 地址0处为指令"b  Reset", 机器码为0xEA00000B,
     * 对于从NAND Flash启动的情况,其开始4KB的代码会复制到CPU内部4K内存中,
     * 对于从NOR Flash启动的情况,NOR Flash的开始地址即为0。
     * 对于NOR Flash,必须通过一定的命令序列才能写数据,
     * 所以可以根据这点差别来分辨是从NAND Flash还是NOR Flash启动:
     * 向地址0写入一个数据,然后读出来,如果没有改变的话就是NOR Flash
     */
 
    dwVal = *pdw;
 
 
    *pdw = 0x12345678;
 
 
    if (*pdw != 0x12345678)
    {
        return 1;
    }
    else
    {
        *pdw = dwVal;
        return 0;
    }
}


这个函数向0地址写数据,在读出来比较。编译时使用的-Os选项,编译器把这个函数给优化了,反汇编结果如下:

1
2
3
4
000003b4 <bBootFrmNORFlash>:
 3b4:  e3a03000   mov r3, #0
 3b8:  e5933000   ldr r3, [r3]
 3bc:  e7f000f0   udf #0

这样判断从nor启动了,导致启动失败。


google后,针对该函数不优化。这是gcc的新特性,在函数前添加一行:

1
int bBootFrmNORFlash(void)  __attribute__ ((optimize("-O0")));


个人认为判断启动方式,应该读取启动strap引脚的电平来判断。韦东山同学的这种方法不可取。用导致错误的方式(向nor写入数据)来判断,可移植性等比较差。


Copyright © linuxdev.cc 2017-2024. Some Rights Reserved.