S3C2410的BOOT程序流程

来源:互联网 发布:内核linux 编辑:程序博客网 时间:2024/05/29 19:30

 

一、      硬件结构

主要涉及的芯片:S3C2410K9S120874LVC16245

采用NAND FLASH做为BOOT程序的存储载体,所以OM[1..0]的值为0b00

系统上电或者复位后,S3C2410K9S1208芯片内读取4KB数据到内部名为SteppingstoneSRAM存储区中,然后芯片执行读取到的指令段,实现全部程序的加载。(BOOT程序可以小于4KB,但是要求FLASH8页只能保存BOOT LOADER程序,多余的存储空间理论上不相关。)

芯片读取指令数据时,每次读取512B,分为8次读取。若打开校验(ECC)功能,则每次只能读取512B

由于NAND FLASH产商保证芯片block0不可能是坏块,所以数值写入时,无需考虑坏块的绕过问题,但BOOT LOADER程序必须建立坏块表来进行正确读写。

S3C2410NAND FLASH接口,无需考虑访问规则的建立,命令、地址、数据各自对应特定的寄存器,在初始化时序等相关寄存器之后就可以直接访问,实现了无缝连接。

二、      BOOT程序功能分析

功能需求方面,程序应该包括以下几点:

(1)       初始化系统。

(2)       提示用户当前状态为程序Loading

(3)       读取主题程序指令数据到特定的存储区。

(4)       运行主体程序。

下面对程序读取NAND FLASH页数据的程序作一分析,代码如下。

int NF_ReadPage(U32 block,U32 page,U8 *buffer)

{

    int i;

    register U8 * bufPt=buffer;                 //指令数据存储区。

    unsigned int blockPage;

    U8 ecc0,ecc1,ecc2;                                   //用于程序校验。

   

    U8 se[16];        

   

    //page=page&0x1f;

    blockPage=(block<<5)+page;                     //块页地址->得到物理地址。

    NF_RSTECC();                              // Initialize ECC,将寄存器的bit121

   

    NF_nFCE_L();                                //改变nFCE电平,使能芯片。

    NF_CMD(0x00);                             //发送读命令到NAND FLASH

    NF_ADDR(0);                                // Column = 0

    NF_ADDR(blockPage&0xff);           //数据线为8位,地址需分多次写入

    NF_ADDR((blockPage>>8)&0xff);   // Block & Page num.

    NF_ADDR((blockPage>>16)&0xff);  //

 

    for(i=0;i<5;i++); //wait tWB(100ns)

   

    NF_WAITRB();                               // Wait tR(max 12us)

//NAND FLASH在收到读取要求后,还需要等待约200us时间,将数据准备好。

 

#if 0

    i=512;

    while(i--!=0)

    {

           *bufPt++=NF_RDDATA();    // Read one page

    }

#elif 0

    //DMA doens't work.

    rSRCPND=BIT_DMA0;

    rDISRC0=0x4e00000c; //NF_RDDATA()

    rDISRCC0=(1<<0); //arc=AHB,src_addr=fix

    rDIDST0=(unsigned)bufPt;

    rDIDSTC0=(0<<0); //dst=AHB,dst_addr=inc;

   rDCON0=(1<<31)|(1<<30)|(1<<29)|(1<<28)|(1<<27)|(0<<23)|(1<<22)|(0<<20)|(512/4);

          //Handshake,AHB,interrupt,(4-burst),whole,S/W,no_autoreload,byte,count=512;

    rDMASKTRIG0=(1<<1)|(1<<0);

 

    while(!(rSRCPND & BIT_DMA0));

    rSRCPND=BIT_DMA0;

//上面的#if 0 … #elif 0 …的功能是什么?理论上应该是必定不会被执行的。

//Answer:屏蔽之

#elif 1

    __RdPage512(bufPt);           //读取一页数据,汇编指令在下面分析。

#endif

 

    ecc0=rNFECC0;

    ecc1=rNFECC1;

    ecc2=rNFECC2;                  //读取校验数值

 

    se[0]=NF_RDDATA();

    se[1]=NF_RDDATA();

    se[2]=NF_RDDATA();          //读取数据写入时获得的ECC校验值,与当前值比较。

    NF_RDDATA();

    NF_RDDATA();

    se[5]=NF_RDDATA();          //这里应该是获得0xff

 

    NF_nFCE_H();                 //将芯片使能关闭。

 

    if(ecc0==se[0] && ecc1==se[1] && ecc2==se[2] && se[5]==0xff)

    {

       //Uart_Printf("[ECC OK:%x,%x,%x]/n",se[0],se[1],se[2]);

           return 1;

    }

    else

    {

       //Uart_Printf("[ECC ERROR(RD):read:%x,%x,%x, reg:%x,%x,%x]/n",

              //se[0],se[1],se[2],ecc0,ecc1,ecc2);

           return 0;

    }        

}

其中“__RdPage512(bufPt);”读取一页数据,汇编指令如下。

;*************************************************************

; NAME : NAND FLASH Subroutine for a410 bootstrap

; DATE : 18.FEB.2002

; DESC :

;  02.18.2002:purnnamu: modified for A410

;  04.24.2002:purnnamu: optimized for NAND flash bootstrap

;*************************************************************

 

A410_BASE_ADDR      EQU       0x2000000

 

       MACRO                //宏程序

       LDR4STR1 $src,$tmp1,$tmp2    

       ldrb  $tmp1,[$src]

       ldrb  $tmp2,[$src]

       orr   $tmp1,$tmp1,$tmp2,LSL #8

       ldrb  $tmp2,[$src]

       orr   $tmp1,$tmp1,$tmp2,LSL #16

       ldrb  $tmp2,[$src]

       orr   $tmp1,$tmp1,$tmp2,LSL #24

       MEND

 

       AREA |C$$code|, CODE, READONLY

      

       EXPORT __RdPage512

__RdPage512

       ;input:a1(r0)=pPage

       stmfd      sp!,{r1-r11}   //保护r1—r11寄存器。

 

       ldr   r1,=0x4e00000c  //NFDATA即将r1指向NAND FLASH的数据寄存器。

       mov r2,#0x200              //一共要读取的字节数。

0    

       LDR4STR1 r1,r4,r3      //r1寄存器中读取4B数据,依次保存在r4寄存器中,

                                          //保存的顺序为D C B A。以下类推。

       LDR4STR1 r1,r5,r3

       LDR4STR1 r1,r6,r3

       LDR4STR1 r1,r7,r3

       LDR4STR1 r1,r8,r3

       LDR4STR1 r1,r9,r3

       LDR4STR1 r1,r10,r3

       LDR4STR1 r1,r11,r3

       stmia       r0!,{r4-r11}    //将数据保存到C程序提供的存储区中。

       subs r2,r2,#32

       bne  %B0                     //是否读取完毕?

 

       ldmfd      sp!,{r1-r11}   //出栈

       mov pc,lr                      //返回

 

       END


from:http://jianli9188.bokee.com/viewdiary.13737210.html

 

原创粉丝点击