u-boot移植总结(一)start.S分析

发布时间:2024-07-25  

本次移植u-boot-2010.09是基于S3C2440的FL440板子,板子自带NANDFLASH而没有NORFLASH,所以在U-BOOT启动的过程中必须实现从NANDFLASH到SDRAM的重定向。


其中最重要的就是在U-BOOT开始的start.S汇编代码,这段代码要完成工作:


1,异常中断向量表,复位后异常向量处理


2, 跳转到代码实际执行处start_code


3,关闭看门狗WATCHDOG


3,关闭所有中断INTERRUPT


4,设置时钟分频,主要设置寄存器CLKDVN,MPLLCON,UPLLCON


5,关闭MMU和CACHE,并调用lowlevel_init.S完成SDRAM和NANDFLASH的初始化,为代码的重定向做准备


6,设置堆栈,并且跳入第二阶段的C代码


7,异常向量处理代码


以下为start.S的分析:


1,异常中断向量表,复位后异常向量处理


//声明一个全局标量,在cpu/arm920t/u-boot.lds中有定义,即代码的入口地址,也是编译地址

_start: b   start_code

   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  //.word 定义一个32位的地址标识

_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


   .balignl 16,0xdeadbeef//将地址偏移为16的整数倍,空余的内容填上0xdeadbeef,这个数即“Magic Number”,可用判断当前u-boot执行位置



_TEXT_BASE:

   .word   TEXT_BASE    //在config.mk中有定义,即u-boot自启时flash从定向到sdram的地址

.globl _armboot_start   //声明一个全局变量,之后要调用

_armboot_start:

   .word _start


/*

 * These are defined in the board-specific linker script.

 */


.globl _bss_start                   //连接脚本u-boot.lds中有定义

_bss_start:

   .word __bss_start


.globl _bss_end //连接脚本u-boot.lds中有定义

_bss_end:

  .word _end


#ifdef CONFIG_USE_IRQ           //堆栈设置

/* IRQ stack memory (calculated at run-time) */


.globl IRQ_STACK_START

IRQ_STACK_START:

  .word   0x0badc0de


/* IRQ stack memory (calculated at run-time) */


.globl FIQ_STACK_START

FIQ_STACK_START:

   .word 0x0badc0de


#endif

2, 跳转到代码实际执行处(设置管理模式=>关闭看门狗=>关闭所有中断=>设置时钟分频)


/*

 * the actual start code

 */


start_code:

    /*

     * set the cpu to SVC32 mode  

     */

                              //设置管理模式  31  30  29  28      7   6   4    3    2    1    0  

    mrs r0, cpsr              //    CPSR      N   Z   C   V       I   F   M4   M3   M2   M1   M0

    bic r0, r0, #0x1f         //                                          1    0    0    1    1

    orr r0, r0, #0xd3  

    msr cpsr, r0           // CPSR为状态寄存器,用于设置系统运行状态,只能用MSR MRS指令


#if defined(CONFIG_AT91RM9200DK) || defined(CONFIG_AT91RM9200EK)   //系统中断重定向于RAM中,以便快速响应中断,搬运的代码为4*16bytes

/*  relocate exception table */

    ldr r0, =_start

    ldr r1, =0x0

    mov r2, #16

copyex: 

    subs r2, r2, #1

    ldr r3, [r0], #4 

    str r3, [r1], #4 

    bne copyex

#endif


//关闭看门狗

#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) || defined(CONFIG_S3C2440)

    /* turn off the watchdog */


#if defined(CONFIG_S3C2400)    

#define pWTCON    0x15300000

#define INTMSK    0x14400008  /* Interupt-Controller base addresses */

#define CLKDIVN   0x14800014  /* clock divisor register */

#else //查阅s3c2440的datesheet中指出寄存器地址

#define pWTCON    0x53000000 

#define INTMSK    0x4A000008  /* Interupt-Controller base addresses */

#define INTSUBMSK 0x4A00001C

#define CLKDIVN   0x4C000014  /* clock divisor register */

#endif


#define CLK_CTL_BASE 0x4C000000    //添加时钟分频寄存器地址,用于时钟分频设置

#define MDIV_405 0x7f<<12

#define PSDIV_405 0x21

#define MDIV_200 0xa1<<12

#define PSDIV_200 0x31

    ldr r0, =pWTCON

    mov r1, #0x0

    str r1, [r0] /*  mask all IRQs by setting all bits in the INTMR - default */

    mov r1, #0xffffffff                                //ARM920T有32个中断源,禁止所有中断,32位中断屏蔽寄存器置位 

    ldr r0, =INTMSK 

    str r1, [r0]

#if defined(CONFIG_S3C2440)||defined(CONFIG_S3C2410) /* add by zhou */ 

    ldr r1, =0x7ff //屏蔽所有的中断源,S3C2440中寄存器只有前15位有效,故0x7ff置位INTSUNMSK 

    ldr r0, =INTSUBMSK 

    str r1, [r0]

#endif

//设置时钟频率

#if defined(CONFIG_S3C2440)

    mov  r1, #5

    str  r1, [r0]


    mrc  p15, 0, r1, c1, c0, 0 

    orr  r1, r1, #0xc0000000

    mcr  p15, 0, r1, c1, c0, 0 


    mov  r1, #CLK_CTL_BASE //S3C2440系统主频为405MHZ,USB为48MHZ,要求MPLLCON = (0x7f<<12) | (0x02<<4) | (0x01) = 0x7f021

    mov  r2, #MDIV_405

    add  r2, r2, #PSDIV_405

    str  r2, [r1, #0x04]   

#else


    /* FCLK:HCLK:PCLK = 1:2:4 */

    /* default FCLK is 120 MHz ! */

    ldr r0, =CLKDIVN

    mov r1, #3

    str r1, [r0]


    mrc p15, 0, r1, c1, c0, 0

    orr r1, r1, #0xc0000000

    mcr p15, 0, r1, c1, c0, 0



    mov r1, #CLK_CTL_BASE

    mov r2, #MDIV_200

    add r2, r2,#PSDIV_200

    str r2, [r1,#0x04]


#endif

#endif /* (CONFIG_S3C2400) || (CONFIG_S3C2410) || (CONFIG_S3C2440) */


3,关闭MMU和CACHE,并调用lowlevel_init.S完成SDRAM和NANDFLASH的初始化,为代码的重定向做准备

   /*******************************************

     * we do sys-critical inits only at reboot,

     * not when booting from ram!

     ******************************************/


#ifndef CONFIG_SKIP_LOWLEVEL_INIT

    bl  cpu_init_crit  //关闭MMU和CACHE,并调用lowlevel_init.S完成SDRAM和NANDFLASH的初始化

#endif

...........

...........

...........

/*

 *************************************************************************

 *

 * CPU_init_critical registers

 *

 * setup important registers

 * setup memory timing

 *

 *************************************************************************

 */


#ifndef CONFIG_SKIP_LOWLEVEL_INIT

cpu_init_crit:

    /*

     * flush v4 I/D caches

     */

    mov r0, #0       //具体设置看下图,详细参考CP15指令:http://blog.csdn.net/gooogleman/article/details/3635238

    mcr p15, 0, r0, c7, c7, 0 //向c7写入0将使ICache与DCache 无效flush v3/v4 cache 

    mcr p15, 0, r0, c8, c7, 0  //向c8写入0将使TLB失效 flush v4 TLB 


    /*

     * disable MMU stuff and caches     //协处理器CP15的C1处理器可以设置MMU和caches,具体参考下图

     */

    mrc p15, 0, r0, c1, c0, 0  

    bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)

    bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)

    orr r0, r0, #0x00000002 @ set bit 2 (A) Align

    orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache

    mcr p15, 0, r0, c1, c0, 0


    /*

     * before relocating, we have to setup RAM timing

     * because memory timing is board-dependend, you will

     * find a lowlevel_init.S in your board directory.

     */

    mov ip, lr       //由于有两层调用,需要把lr保存到ip,以防止破坏


    bl  lowlevel_init //调用c函数,初始化FLASH和SDRAM,为代码重定向做准备


    mov lr, ip 

    mov pc, lr      //返回

#endif /* CONFIG_SKIP_LOWLEVEL_INIT */

代码重定向基本思路:


1.内存运行与否,是则设置堆栈,跳入c函数阶段


2.若不在内存运行,判断是在norflash还在nandflash运行


//代码重定向部分

/***************CHECK_CODE_POSITION******************************/


    adr r0, _start      /* r0 <- current position of code   */   //检查代码是否在已经SDRAM中运行,是则设置堆栈,并跳入c代码部分

    ldr r1, _TEXT_BASE      /* test if we run from flash or RAM */  //_start为u-boot的真正运行地址,_TEXT_BASE为FLASH加载到SDRAM的地址,在config.mk中定义为0x33f80000

    cmp r0, r1          /* don't reloc during debug         */      //若相等,说明已经在SDRAM中运行,设置堆栈,并且调转到第二阶段的C函数

    beq stack_setup //若不相等,则要判断是从NORFLASF或NANDFLASH启动


/***************CHECK_CODE_POSITION******************************/


/***************CHECK_BOOT_FLASH********************************/


    ldr r1, =((4<<28)|(3<<4)|(3<<2))  /*address in 4000003c*/

    mov r0, #0     //NANDFLASH的启动原理,启动时4K SRAM,即Stepping Stone,会映射到nGCS0,0x0000 0000地址,同时它还是会被映射到0x4000 0000地址 

    str r0,[r1]    //而NORFLASH支持片上运行,并会被一直挂载到nGCS0,0x0000 0000,具体可以参照NANDFLASH启动原理


    mov r1, #0x3c   /*address in 0x3c*/ //NANDFLASH启动时,因为地址为16倍数对齐,此时0x0000 003c 和 0x4000 003c都为唯一确定的0xdeadbeef,即"Magic Mumber"

    ldr r0, [r1]    //当0x4000 003c清零,若0x0000 003c读出也是零,则u-boot代码从NANDFLASH启动,否则从NORFLASH

    cmp r0, #0

    bne relocate



    /*recover 0x4000003c */

    ldr r0, =(0xdeadbeef)     //若在NANDFLASH启动,必须保证代码和前4K拷贝到SRAM一致,否则会进入死循环

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。

我们与500+贴片厂合作,完美满足客户的定制需求。为品牌提供定制化的推广方案、专属产品特色页,多渠道推广,SEM/SEO精准营销以及与公众号的联合推广...详细>>

利用葫芦芯平台的卓越技术服务和新产品推广能力,原厂代理能轻松打入消费物联网(IOT)、信息与通信(ICT)、汽车及新能源汽车、工业自动化及工业物联网、装备及功率电子...详细>>

充分利用其强大的电子元器件采购流量,创新性地为这些物料提供了一个全新的窗口。我们的高效数字营销技术,不仅可以助你轻松识别与连接到需求方,更能够极大地提高“闲置物料”的处理能力,通过葫芦芯平台...详细>>

我们的目标很明确:构建一个全方位的半导体产业生态系统。成为一家全球领先的半导体互联网生态公司。目前,我们已成功打造了智能汽车、智能家居、大健康医疗、机器人和材料等五大生态领域。更为重要的是...详细>>

我们深知加工与定制类服务商的价值和重要性,因此,我们倾力为您提供最顶尖的营销资源。在我们的平台上,您可以直接接触到100万的研发工程师和采购工程师,以及10万的活跃客户群体...详细>>

凭借我们强大的专业流量和尖端的互联网数字营销技术,我们承诺为原厂提供免费的产品资料推广服务。无论是最新的资讯、技术动态还是创新产品,都可以通过我们的平台迅速传达给目标客户...详细>>

我们不止于将线索转化为潜在客户。葫芦芯平台致力于形成业务闭环,从引流、宣传到最终销售,全程跟进,确保每一个potential lead都得到妥善处理,从而大幅提高转化率。不仅如此...详细>>