使用jlink烧写uboot

时间:2022-02-02 08:48:11
我想标题应该写成”使用jlink启动uboot,通过uboot烧写uboot进nand“,这么写太长了,所以写短些,这里补充下,让大家明白意思
笔者最近使用S3C2410做一些开发工作,对于新买的核心板(无uboot),如何把uboot、内核、文件系统烧写进去呢?
初步分析如下
1.uboot已经支持烧写nand
2.uboot暂未支持烧写yaffs
3.如何通过jlink启动uboot

第一步已经支持,没问题
第二步,yaffs是由mkyaffsimage生成,这种yaffs文件系统是有带oob信息的,所以要将yaffs的oob信息一起写入,同时要注意oob的格式要一致,查了下内核的oob,修改下mkyaffsimage的oob,然后再uboot中添加支持烧写yaffs文件系统的接口,这一步ok
第三步,这些天花了些功夫在这个步骤上,uboot一直无法启动起来,后来发现其中有一个步骤被我忽略了,硬件接触不好,就是核心板和底板没接触好,导致uboot一直无法启动,严谨说是有启动,但是串口没输出,只有启动一部分,后来程序就跑飞了,启动的部分是由于uboot载入0地址的那段跑起来,所以导致一些奇怪的错误现象
我们分析下uboot的启动文件start.S
@ Start of executable code
@

ENTRY(_start)
ENTRY(ResetEntryPoint)
@#define CONFIG_PM
@#define CONFIG_TEST
#define CONFIG_S3C2410_NAND_BOOT
@#define CONFIG_DEBUG_LL
@ Exception vector table (physical address = 0x00000000)
@
.globl  reset_cpu
reset_cpu:
@ 0x00: Reset
        b       Reset                                     @复位
ldr     pc, _undefined_instruction              @异常地址
        ldr     pc, _software_interrupt          
        ldr     pc, _prefetch_abort
        ldr     pc, _data_abort
        ldr     pc, _not_used
        ldr     pc, _irq
        ldr     pc, _fiq

_undefined_instruction: .word undefined_instruction
_software_interrupt:    .word software_interrupt
_prefetch_abort:        .word prefetch_abort
_data_abort:            .word data_abort
_not_used:              .word not_used
_irq:                   .word irq
_fiq:                   .word fiq


@
@ VIVI magics
@

@ 0x20: magic number so we can verify that we only put
        .long   0
@ 0x24:
        .long   0
@ 0x28: where this vivi was linked, so we can put it in memory in the right place
        .long   _start
@ 0x2C: this contains the platform, cpu and machine id
        .long   ARCHITECTURE_MAGIC
@ 0x30: vivi capabilities
        .long   0
#ifdef CONFIG_PM
@ 0x34:
        b       SleepRamProc
#endif
#ifdef CONFIG_TEST
@ 0x38:
        b       hmi
#endif
.globl  _armboot_end_data
_armboot_end_data:
        .word   armboot_end_data
.globl  _armboot_end
_armboot_end:
        .word   armboot_end
.globl  IRQ_STACK_START
IRQ_STACK_START:
        .word   0x0badc0de
.globl  _armboot_real_end
_armboot_real_end:
        .word 0x0badc0de
.globl  _armboot_start
_armboot_start:
        .word _start
.globl  FIQ_STACK_START
FIQ_STACK_START:
        .word   0x0badc0de
@
@ Start VIVI head
@
Reset:                                      @复位后跳转到这里执行
        @ disable watch dog timer
        mov     r1, #0x53000000
        mov     r2, #0x0
        str     r2, [r1]
        @ bl led_on
#ifdef CONFIG_S3C2410_MPORT3                @未定义,不执行
        mov     r1, #0x56000000
        mov     r2, #0x00000005
        str     r2, [r1, #0x70]
        mov r2, #0x00000001
        str     r2, [r1, #0x78]
        mov     r2, #0x00000001
        str r2, [r1, #0x74]
#endif

        @ disable all interrupts
        mov     r1, #INT_CTL_BASE                              @屏蔽中断
        mov     r2, #0xffffffff
        str     r2, [r1, #oINTMSK]
        ldr     r2, =0x7ff
        str     r2, [r1, #oINTSUBMSK]  

        @ initialise system clocks
        mov     r1, #CLK_CTL_BASE
        mvn     r2, #0xff000000
        str     r2, [r1, #oLOCKTIME]

        @ldr    r2, mpll_50mhz
        @str    r2, [r1, #oMPLLCON]
#ifndef CONFIG_S3C2410_MPORT1
        @ 1:2:4
        mov     r1, #CLK_CTL_BASE
        mov     r2, #0x3
        str     r2, [r1, #oCLKDIVN]
    mrc p15, 0, r1, c1, c0, 0       @ read ctrl register                     想问具体的,这个可以百度下为什么
    orr r1, r1, #0xc0000000     @ Asynchronous
    mcr p15, 0, r1, c1, c0, 0       @ write ctrl register

    @ now, CPU clock is 100 Mhz
    mov r1, #CLK_CTL_BASE
    ldr r2, mpll_200mhz
    str r2, [r1, #oMPLLCON]
#endif

.globl backlight_off
        @ All LED on
backlight_off:
        mov     r1, #GPIO_CTL_BASE
        add     r1, r1, #oGPIO_G
        ldr     r2,=0x100
        str     r2, [r1, #oGPIO_CON]
        mov     r2, #0xff
        str     r2, [r1, #oGPIO_UP]
        mov     r2, #0x00
        str     r2, [r1, #oGPIO_DAT]

        bl      memsetup                @dram初始化

#ifdef CONFIG_PM
        @ Check if this is a wake-up from sleep
        ldr     r1, PMST_ADDR
        ldr     r0, [r1]
        tst     r0, #(PMST_SMR)
        bne     WakeupStart
#endif


/*#ifdef CONFIG_S3C2410
led_light_on:
        @ All LED on
        mov     r1, #GPIO_CTL_BASE
        add     r1, r1, #oGPIO_F
        ldr     r2,=0x55aa
        str     r2, [r1, #oGPIO_CON]
        mov     r2, #0xff
        str     r2, [r1, #oGPIO_UP]
        mov     r2, #0x00
        str     r2, [r1, #oGPIO_DAT]
#endif*/

#if 0
        @ SVC
        mrs     r0, cpsr
        bic     r0, r0, #0xdf
        orr     r1, r0, #0xd3
        msr     cpsr_all, r1
#endif

        @ set GPIO for UART
        mov     r1, #GPIO_CTL_BASE       @配置串口
        add     r1, r1, #oGPIO_H
        ldr     r2, gpio_con_uart
        str     r2, [r1, #oGPIO_CON]
        ldr     r2, gpio_up_uart
        str     r2, [r1, #oGPIO_UP]    
        bl      InitUART
#ifdef CONFIG_DEBUG_LL
        @ Print current Program Counter
        ldr     r1, SerBase
        mov     r0, #'\r'
        bl      PrintChar
        mov     r0, #'\n'
        bl      PrintChar
        mov     r0, #'@'
        bl      PrintChar
        mov     r0, pc
        bl      PrintHexWord
#endif
#ifdef CONFIG_BOOTUP_MEMTEST
        @ simple memory test to find some DRAM flaults.
        bl      memtest
#endif
#ifdef CONFIG_S3C2410_NAND_BOOT
#if 0
        bl      copy_myself
#else
        adr r0, _start
        ldr r1, =0x33f00000
        cmp r0, r1
        blne copy_myself                @将代码从nand拷贝到dram的0x33f0 0000
#endif

        @ jump to ram
        mov     r1, #GPIO_CTL_BASE      @板上的led灯指示
        add     r1, r1, #oGPIO_F
        ldr     r2,=0x55aa
        str     r2, [r1, #oGPIO_CON]
        mov     r2, #0xff
        str     r2, [r1, #oGPIO_UP]
        mov     r2, #0xb0
        str     r2, [r1, #oGPIO_DAT]

        ldr     r1, =on_the_ram        @这个指令时重定位的关键,汇编代码可以看到这个不是基于pc的,它是一个固定值,指向dram的相应位置
        add     pc, r1, #0                  @跳转到dram执行,
        nop
        nop
1:      b       1b              @ infinite loop
on_the_ram:
#endif

#ifdef CONFIG_DEBUG_LL
        ldr     r1, SerBase
        ldr     r0, STR_STACK
        bl      PrintWord
        ldr     r0, DW_STACK_START
        bl      PrintHexWord
#endif

我们就看这部分,我直接在代码加些注释了
在看下u-boot.lds
OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
/*OUTPUT_FORMAT("elf32-arm", "elf32-arm", "elf32-arm")*/
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS
{
        . = 0x33f00000;

        . = ALIGN(4);
        .text      :
        {
          cpu/arm920t/start.o   (.text)
          *(.text)
        }

        . = ALIGN(4);
        .rodata : { *(.rodata) }

        . = ALIGN(4);
        .data : { *(.data) }

        . = ALIGN(4);
        .got : { *(.got) }

  __u_boot_cmd_start = .;
  .u_boot_cmd : { *(.u_boot_cmd) }
  __u_boot_cmd_end = .;


        armboot_end_data = .;
        __bss_start     =.;

        . = ALIGN(4);
        .bss : { *(.bss) }
        _end    =.;
        armboot_end = .;

}
可以看出start.S优先链接,就放在启动地址下

从上可以看出,要通过jlink启动uboot,只要分两步
1.将uboot载入0地址,启动它,以下是在jlink输入的内容
loadbin E:\yr\tmp\u-boot.bin 0     //uboot路径
setpc 0
g
2. 将uboot载入0x33f0 0000地址,启动它,以下是在jlink输入的内容
loadbin E:\yr\tmp\u-boot.bin 0x33f00000
setpc 0x33f00000
g
通过以上两个步骤,串口即可正常输出