您的位置:首页 > 其它

从零移植uboot 2017 到nuc970(第十四天)

2017-03-14 16:46 381 查看
昨天的灯,稍后再比较。反汇编了官方的自带的uboot2013spl
u-boot-spl:     file format elf32-littlearm

Disassembly of section .text:

00000200 <_start>:
200:   ea000013        b       254 <reset>
204:   e59ff014        ldr     pc, [pc, #20]   ; 220 <_hang>
208:   e59ff010        ldr     pc, [pc, #16]   ; 220 <_hang>
20c:   e59ff00c        ldr     pc, [pc, #12]   ; 220 <_hang>
210:   e59ff008        ldr     pc, [pc, #8]    ; 220 <_hang>
214:   e59ff004        ldr     pc, [pc, #4]    ; 220 <_hang>
218:   e59ff000        ldr     pc, [pc]        ; 220 <_hang>
21c:   e51ff004        ldr     pc, [pc, #-4]   ; 220 <_hang>
  入口地址为200,换句话说执行地址必须为200。

  我自己的生产的:
00000000 <_start>:
0:       ea000016        b       60 <reset>
4:       e59ff014        ldr     pc, [pc, #20]   ; 20 <_undefined_instruction>
8:       e59ff014        ldr     pc, [pc, #20]   ; 24 <_software_interrupt>
c:       e59ff014        ldr     pc, [pc, #20]   ; 28 <_prefetch_abort>
10:       e59ff014        ldr     pc, [pc, #20]   ; 2c <_data_abort>
14:       e59ff014        ldr     pc, [pc, #20]   ; 30 <_not_used>
18:       e59ff014        ldr     pc, [pc, #20]   ; 34 <_irq>
1c:       e59ff014        ldr     pc, [pc, #20]   ; 38 <_fiq>
  这就是区别之一, 之后看我点灯的程序。根据官方芯片手册
Set OUTEN (GPIOx_DIR
) to 1 as the Px.n pin is in output mode and the I/O pin reflects the value
written in DATAOUT (GPIOx_DATAOUT
).
writel(readl(REG_PCLKEN0) | 0x8, REG_PCLKEN0);  // 开gpio的时钟
writel(readl(0xB8003200) | 0x01, 0xB8003200); //设置方向output 1
writel(readl(0xB8003204) | 0x01, 0xB8003204); //输出寄存器输出 1   此时pi.0应该为高电平 led 串了电阻,连接到地,此时应该亮
658:       e3a0320b        mov     r3, #-1342177280        ; 0xb0000000
674:       e5932218        ldr     r2, [r3, #536]  ; 0x218
678:       e3822008        orr     r2, r2, #8
67c:       e5832218        str     r2, [r3, #536]  ; 0x218
680:       e59f3028        ldr     r3, [pc, #40]   ; 6b0 <spl_board_init+0x5c>
684:       e5932200        ldr     r2, [r3, #512]  ; 0x200 //r2 是gpio i out的寄存器值
688:       e3822001        orr     r2, r2, #1               //置搞第一位
68c:       e5832200        str     r2, [r3, #512]  ; 0x200  //gpio i out寄存器 第一位置高
690:       e5932204        ldr     r2, [r3, #516]  ; 0x204   //与上面类似
694:       e3822001        orr     r2, r2, #1
698:       e5832204        str     r2, [r3, #516]  ; 0x204

   显然680出了问题,这里不应该是pc指针+偏移,最后改变一下,不知道为什么会出现这种问题,为了确定这是个问题,

我的思路是,在13版 相应位置加入亮灯代码,如果不能达到效果说明,确实有问题。如果到达效果说明 反汇编有问题,

经过交叉测试,首先端口拉高,灯亮,端口拉低灯灭。说明实现预期功能,然后看反汇编

15bc:       e59f3028        ldr     r3, [pc, #40]   ; 15ec <board_init_f+0x5c>
15c0:       e5932200        ldr     r2, [r3, #512]  ; 0x200
15c4:       e3822001        orr     r2, r2, #1
15c8:       e5832200        str     r2, [r3, #512]  ; 0x200
15cc:       e5932204        ldr     r2, [r3, #516]  ; 0x204
15d0:       e5832204        str     r2, [r3, #516]  ; 0x204


   这个汇编是不争取的,因为r3 此时是15ec+512(10进制),怎么都不能等于gpio 0xb80032000的地址,所以可能是我理解

的问题 或者有个概念(笔者认为要理解下执行地址,下载地址了,也许是pc此时在sram中的地址+#40确实和0xb80032000

一样呢,总之先滞后这个问题,最后再查阅下)此时先测试自己的2017uboot是否可以正常点灯。

   没成功,接着把点灯代码放置在最先调用的c函数里面,灯亮了,此时我再将程序反过来,灯灭。
   第二次灯确实没亮,那么到现在可以确定的是从start.S开始到main,再到第一个调用的函数board_init_f_alloc_reserve 都是

确实进行了。 第二轮测试,将灯程序放到board_init_f_init_reserve,特意放在最后

×××××××××××××××××××××××××××××××××××××

   这里是源程序代码:
/*
* Set up initial C runtime environment and call board_init_f(0).
*/

#if defined(CONFIG_SPL_BUILD) && defined(CONFIG_SPL_STACK)
ldr    sp, =(CONFIG_SPL_STACK)
#else
ldr    sp, =(CONFIG_SYS_INIT_SP_ADDR)
#endif
#if defined(CONFIG_CPU_V7M)    /* v7M forbids using SP as BIC destination */
mov    r3, sp
bic    r3, r3, #7
mov    sp, r3
#else
bic    sp, sp, #7    /* 8-byte alignment for ABI compliance */
#endif
mov    r0, sp
bl    board_init_f_alloc_reserve
mov    sp, r0
/* set up gd here, outside any C code */
mov    r9, r0
bl    board_init_f_init_reserve

mov    r0, #0

bl    board_init_f

   灯亮了,我是在board_init_f初始化串口的,所以这就是关键了。终于发现了问题,这个函数的反汇编,和

我给定的代码不一样,我虽然看到链接了arm/lib/spl.c但是那里的函数被_weak标记。等会再查下weak的问题,

而我在自己的函数里面有重新定义过这个函数,现在删除这个函数,看看结果如何灯亮了,那么现在我可以断定

串口是可以用了,再试试成功了!

   


   串口调通了,真是一波三折,以后的debug将轻松很多,这是spl的uboot,单单是spl,但是既然串口通了,其他都是时间问题

了。距离成功已经不太远了。bl0->bl1->bl2,bl1的一半成功了,

   现在解决两个问题,第一 加载地址,运行地址,及反汇编时,pc的指针问题

                                       第二 _weak函数问题,不会提示被重复定义的错误

    第一个问题:1.http://blog.chinaunix.net/uid-29399573-id-4385708.html

    按照这篇文章思想我找到了一个定义CONFIG_SYS_TEXT_BASE=0x80000000,我的链接文件

ENTRY(_start)
SECTIONS
{
. = 0x00000000;
. = ALIGN(4);
.text :
{
__image_copy_start = .;
*(.vectors)
arch/arm/cpu/arm926ejs/start.o (.text*)
*(.text*)
}
  再看命令行的详细版  

arm-linux-gcc -Wp,-MD,spl/arch/arm/lib/.crt0.o.d  -nostdinc -isystem /usr/local/arm_linux_4.8/lib/gcc/arm-nuvoton-linux-uclibceabi/4.8.4/include -Iinclude   -I./arch/arm/include -include ./include/linux/kconfig.h -D__KERNEL__ -D__UBOOT__ -DCONFIG_SPL_BUILD -D__ASSEMBLY__ -g -DCONFIG_ARM_ASM_UNIFIED -D__ARM__ -marm -mno-thumb-interwork -mabi=aapcs-linux -ffunction-sections -fdata-sections -fno-common -ffixed-r9 -msoft-float -pipe -march=armv5te -D__LINUX_ARM_ARCH__=5   -c -o spl/arch/arm/lib/crt0.o arch/arm/lib/crt0.S
  我没有找到链接的地址在哪里制定,以及生成的文件,这个问题,到最后回过头来再重新审视,今天到这里

   2.__weak是一个宏,和__packed是同一种东西都是gcc的扩展属性:

#define __packed __attribute__((packed))
#define __weak __attribute__((weak))
   如果这个关键字用在函数定义上面,一般情况下和一般函数没有两样。但是当有一个同名函数但是不带__weak被定义时,所有

对这个函数的调用都是指向后者(不带__weak那个), 如果有两个一样的函数都用了__weak,那么真正调用那个,就要看连接器了。

以上话转自http://blog.csdn.net/adaptiver/article/details/6695637。和我想的一样,今天就到这里吧,还要学习其他的东西

                         
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: