博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
arm:启动代码判断是从nand启动还是从norflash启动,拷贝程序到内存的过程
阅读量:4946 次
发布时间:2019-06-11

本文共 6612 字,大约阅读时间需要 22 分钟。

一、nand启动和nor启动:[1]

  CPU从0x00000000位置开始运行程序。

  1、nand启动:

  如果将S3C2440配置成从NANDFLASH启动(将开发板的启动开关拔到nand端,此时OM0管脚拉低)S3C2440的Nand控制器会自动把Nandflash中的前4K代码数据搬到内部SRAM中(地址为0x40000000),同时还把这块SRAM地址映射到了0x00000000地址。CPU从0x00000000位置开始运行程序。 

  2、如果将S3C2440配置成从Norflash启动(将开发的启动开关拔到nor端,此时OM0管脚拉高),0x00000000就是norflash实际的起始地址,norflash中的程序就从这里开始运行,不涉及到数据拷贝和地址映射

  3、总结:

  nand启动时,地址0x00000000为内部SRAM映射的地址;

  nor启动时,地址0x00000000为norflash的实际起始地址。

  向Norflash中写数据需要特定的命令时序,而向内存中写数据可以直接向内存地址赋值。

 

二、判断是从nand启动还是从norflash启动:

1.根据硬件接线,

  引脚OM1、OM0  :  00: Nand-boot 01: 16-bit 10: 32-bit 11: Test mode

  

  总线宽度和等待控制寄存器(BWSCON)0x48000000      BWSCON_bit[2:1] Indicate data bus width for bank 0 (read only).

  The states are selected by OM[1:0] pins 。(01 = 16-bit, 10 = 32-bit  ...)

 

what's done before copy?

ResetHandler    ;WTCON  watch dog disable    ;INTMSK    ;INTSUBMSK    ;To reduce PLL lock time, adjust the LOCKTIME register.    ;Setting value Fclk:Hclk:Pclk    ;Configure UPLL     ;Configure MPLL    ;Check if the boot is caused by the wake-up from SLEEP mode.      ;In case of the wake-up from SLEEP mode, go to SLEEP_WAKEUP handler.    ;Set memory control registers    ;Initialize stacks    bl    InitStacks  ; Setup IRQ handler    ldr r0,=HandleIRQ ;This routine is needed    ldr    r1,=IsrIRQ    ;if there isn t 'subs pc,lr,#4' at 0x18, 0x1c    str    r1,[r0]

now copy:

;===========================================================;// 判断是从nor启动还是从nand启动;===========================================================    ldr    r0, =BWSCON    ldr    r0, [r0]    ands    r0, r0, #6                ;0110    bne    NORRoCopy                  ;BWSCON的[2:1]反映了外部引脚OM[1:0].                                    ;bne:若OM[1:0] != 00, 是从NOR FLash启动.                                      ;若OM[1:0]==00,则为Nand Flash Mode.NandFlashMode    adr    r0, ResetEntry        ;注意adr得到的是相对地址,非绝对地址.    Cpu刚启动时,ResetEntry==0.    cmp    r0, #0                ;再比较入口是否为0地址处     bne    InitRamZero           ;如果不是0,直接初始化bss段,进入CEntry.    ;nop        ;===========================================================;如果ResetEntry==0,说明是cpu刚启动(注意此处是nand启动),那就应该将nand中的代码搬运到sdram中。;===========================================================nand_boot_beg    bl    ClearSdram             ;将内存清零。从内存起始地址--->指定的足够大的范围,不超过内存的实际大小。        mov    r5, #NFCONF            ;nand控制器初始化        ;set clk value    ldr    r0,    =(7<<12):OR:(7<<8):OR:(7<<4)    str    r0,    [r5]    ;enable control    ldr    r0, =(0<<13):OR:(0<<12):OR:(0<<10):OR:(0<<9):OR:(0<<8):OR:(1<<6):OR:(1<<5):OR:(1<<4):OR:(1<<1):OR:(1<<0)    str    r0, [r5, #4]        bl    ReadNandID            ;读nandId,从而判断nand芯片的种类. r5 = nandId    mov    r6, #0    ldr    r0, =0xecF1    cmp    r5, r0    beq    %F1                    ;if(nandId==0xecf1){r6=0;//addr_cycle=4}else{r6=1;//addr_cycle=5}    mov    r6, #1                ;Nandaddr(寻址周期 0:4  1:5)1        bl    ReadNandStatus        ;r1 = ret_of_ReadNandStatus ,这里似乎没有用。        mov        r8, #0                ;page_addr = r8 = 0;    ldr        r9, =ResetEntry        ;r9 = size_copyed = pBuff = 0;    mov        r10,#64             ;+081010 feiling     nPages_need_to_copy=64(128KB);2        ands    r0, r8, #0x3f        ;R0 = R8 & 0X3F ; 如果是第一页(mov r8, #0),本式子equal 0;    bne        %F3                      mov        r0, r8                ;如果是第一页,则检测坏块    bl        CheckBadBlk            ;unsigned int CheckBadBlk(unsigned int    page_addr)    cmp        r0, #0            addne    r8, r8, #64            ;每块的页数 r8 同时也做计数用。     addne    r10,r10,#64         ;+081010 feiling  if(is_bad_block){page_addr+=64;nPages_need_to_copy+=64;}    bne        %F43        mov    r0, r8    mov    r1, r9           ;r1 = r9 = size_copyed     bl    ReadNandPage     add    r9, r9, #2048    ;size_copyed+=2048    add    r8, r8, #1       ;page_addr+14        cmp    r8, r10           ;要拷贝的页数 081010 pht .  if(page_addr < nPages_need_to_copy ){copy_loop;}    bcc    %B2        mov    r5, #NFCONF        ;DsNandFlash    ldr    r0, [r5, #4]    bic r0, r0, #1    str    r0, [r5, #4]        ldr    pc, =InitRamZero    ;此处跳转到内存空间 LDR 装载数据,寻址灵活。 但不改变PSR                            ;要装载一个被存储的‘状态’并正确的恢复它 可以这样写:ldr r0, [base] 换行  moves pc, r0;=============================================================================================;若是从NAND启动,则先清零内存,再从nand[0 ~ user_set_size]拷贝到内存(ro 和.data),再初始化bss段,进入main。;若是从NOR启动,同样是先清零,后拷贝,再初始化bss段,进入main。为了考虑jlink等调试的情况,避免二次拷贝,才使代码显得复杂。 ;其实可以不管,直接全部拷贝过来,nor拷贝比nand拷贝更简单,逐个字节复制即可。;=============================================================================================NORRoCopy                    ;copy_proc_from_nor_to_sdram    bl    ClearSdram            ;clear all sdram needed    adr    r0, ResetEntry        ;判断是否在ROM中运行,ROM即RO指定的地址,从NOR启动时ResetEntry为0    ldr    r2, BaseOfROM         ;如果相等,说明是jlink调试,调试器将程序.ro段直接下载到了内存,就不需再拷贝。    cmp    r0, r2                ;pFrom = r0 = ResetEntry(活的) ; pTo = r2 = BaseOfROM(链接文件写死的) ;pEnd = TopOfROM(链接文件写死的)    beq    NORRwCopy             ;if(ResetEntry==BaseOfROM){skip RoCopyLoop ,directly do RwCopy;}    RoCopyLoop                    ldr r3, TopOfROM             ;0                                ldmia    r0!, {r4-r7}        stmia    r2!, {r4-r7}        ;mem_ResetEntry----> mem_BaseOfROM ; pFrom+=4;pTo+=4;    cmp    r2, r3                ;if(pTo

 

ClearSdram:在拷贝程序到内存之前,先清内存。

;=========================================================ClearSdram    mov r1,#0    mov r2,#0    mov r3,#0    mov r4,#0    mov r5,#0    mov r6,#0    mov r7,#0    mov r8,#0        ldr    r9,=0x00700000   ;size of ram to clear    ldr    r0,=0x300000000        stmia    r0!,{r1-r8}    subs    r9,r9,#32     bne    %B0    BX lr

 

 2、根据 “向norflash写入数据需要一定的命令序列,而向内存中写数据可以直接向内存地址赋值” 这一点来区别:

//int bBootFrmNORFlash(void) : 判断是否从norflash启动。//ret==1 :norflash启动//ret==0 :nandflash启动。(或者是jlink调试的情况。)//说明:该函数应用范围有限,只针对于bootloader最初的stage1。int bBootFrmNORFlash(void){    volatile unsigned int *pdw = (volatile unsigned int *)0;  //volatile    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     * 这仅仅针对于初始阶段,norflash启动时,最终也要将程序加载到SDRAM中运行。因此该函数应用范围是有局限性的。     */    dwVal = *pdw;           *pdw = 0x12345678;    if (*pdw != 0x12345678)    {        return 1;    }    else    {        *pdw = dwVal;//测试完后要还原数据。        return 0;    }}

 参考:

1、 http://blog.chinaunix.net/uid-22030783-id-3347621.html

转载于:https://www.cnblogs.com/mylinux/p/4180577.html

你可能感兴趣的文章
servlet(一)
查看>>
异常实验
查看>>
python \r与\b的应用、光标的含义
查看>>
深拷贝 vs 浅拷贝 释放多次
查看>>
Java环境变量PATH和CLASSPATH
查看>>
ERROR:bokeh.core.validation.check:E-1001 (BAD_COLUMN_NAME) 就是补存在这个列名
查看>>
assert 的作用是什么?
查看>>
收藏夹(持续更新)
查看>>
iOS中的#import和class区别
查看>>
节约内存,请使用标签页管理工具:onetab、better onetab
查看>>
jQuery中的事件与动画
查看>>
页面加载骨架
查看>>
关于android系统不关屏设置
查看>>
SONY VPCS138EC降级安装XP
查看>>
[luogu4201][bzoj1063]设计路线【树形DP】
查看>>
手机抓包-手机劫持域名到指定服务器
查看>>
被放逐的皇后 金建云
查看>>
Javascript 有用参考函数
查看>>
点群的判别(三)
查看>>
gradle
查看>>