基于S3C2410A的WINCE下Stepldr程序移植详细分析[二]

前面分析STEPLDR.BIB文件,现在分析的是NAND FLASH驱动部分。至于startup.s文件,主要是进行初始化:看门狗。配置MPLL和UPLL以及待机和休眠。还有的就是上电,还是复位等,在移植到STEPLDR到S3C2410A的时候需要修改的地方就是NAND FLASH驱动部分,代码如下:

; NAND code...
;
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

 EXPORT __RdPage512
__RdPage512
 ;input:a1(r0)=pPage
 stmfd sp!, {r1-r11}

 ldr r1, =0x4E00000C  ;NFDATA
 mov r2, #0x200

 LDR4STR1 r1, r4, r3
 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}
 subs r2, r2, #32
 bne %B1

 ldmfd sp!, {r1-r11}
 mov pc, lr

这段代码是已经修改过的在S3C2410A可以正常运行的CODE。直接复制到S3C2440A的Stepldr下的startup.s覆盖这段代码即可。这是因为S3C2410A的寄存器和S3C2440A的寄存器不一样引起的问题。上面这段代码是直接可以用滴。

下面来移植S3C2410A的NAND FLASH的STEPLDR驱动吧:

#define NF_CMD(cmd)    {rNFCMD=cmd;}
#define NF_ADDR(addr)   {rNFADDR=addr;} 

// for S3C2410aNAND
//  For flash chip that is bigger than 32 MB, we need to have 4 step address
#define NEED_EXT_ADDR               1

#define NF_nFCE_L()    {rNFCONF &= ~(1<<11);}
#define NF_nFCE_H()    {rNFCONF |=  (1<<11);}
#define NF_RSTECC()    {rNFCONF |=  (1<<12);}

#define NF_MECC_UnLock()  {do{}while( 0 );}
#define NF_MECC_Lock()   {do{}while( 0 );}

#define NF_CLEAR_RB()   {rNFSTAT |=  (1 << 2);}
#define NF_DETECT_RB()   {while(!(rNFSTAT&(1<<0)));}
#define NF_WAITRB()       {while(!(rNFSTAT&(1<<0)));}


#define NF_RDDATA()    (rNFDATA)
#define NF_WRDATA(data)   {rNFDATA=data;}

#define NF_ECC()         (rNFECC)

#define ID_K9S1208V0M   0xEC76

// HCLK=133Mhz
#define TACLS  7
#define TWRPH0  7
#define TWRPH1  7

typedef union _ECCRegVal
{
 DWORD dwECCVal;
 BYTE bECCBuf[4];
} ECCRegVal;


void __RdPage512(BYTE *bufPt);


int NF_ReadPage(UINT32 block,UINT32 page,UINT8 *buffer)
{
    volatile int i;
    register UINT8 * bufPt=buffer;
    unsigned int blockPage;
// ULONG MECC;
    BYTE   ecc0,ecc1,ecc2;
    ECCRegVal eccRegVal;
 

    blockPage=(block<<5)+page;

    NF_RSTECC();    // Initialize ECC
   
    NF_nFCE_L();   
    NF_CMD(0x00);   // Read command
    NF_ADDR(0);     // Column = 0
    NF_ADDR(blockPage&0xff);     //
    NF_ADDR((blockPage>>8)&0xff);   // Block & Page num.
    NF_ADDR((blockPage>>16)&0xff);  //

    for(i=0 ; i<50 ; i++); //wait tWB(100ns)
   
    NF_WAITRB();    // Wait tR(max 12us)

    __RdPage512(bufPt);

 eccRegVal.dwECCVal = NF_ECC();
 
 // Skip first 8 bytes
 for(i=0; i<8; i++)
 {
  ecc0 = NF_RDDATA(); //必须保留读取8个字节,这里是OEM配置用途
 }

 ecc0 = NF_RDDATA();
 ecc1 = NF_RDDATA();
 ecc2 = NF_RDDATA(); 
 
 NF_nFCE_H();

 if( ecc0 != eccRegVal.bECCBuf[0] ||
  ecc0 != eccRegVal.bECCBuf[0] ||
  ecc0 != eccRegVal.bECCBuf[0] ) {
 // Uart_SendString("ECC mismatch for Sector: ");
 // Uart_SendDWORD(blockPage, TRUE);
 }

 return 1;

} //由于NAND FLASH在生产时,必须确保BLOCK0是OK滴。同时在引导时,是不需要校验ECC。因此。不做ECC校验。


void NF_Reset(void)
{
    volatile int i;
  
    NF_nFCE_L();

    NF_CMD(0xFF);              // reset command.

    for(i=0 ; i<10 ; i++);     // tWB = 100ns.

    NF_WAITRB();               // wait 200~500us.
    
    NF_nFCE_H();
}


void NF_Init(void)
{

    rNFCONF =  (1  << 15) | /* Enable/Disable      */
    (1   << 14) | /* Page Size : 512Bytes      */
    (1   << 13) | /* 4 Step Address        */
    (1   << 12) | /* Initialize ECC        */
    (1   << 11) | /* nFCE control nFCE = HIGH     */
    (TACLS  <<  8) | /* CLE & ALE = HCLK * (TACLS + 1)   */
    (TWRPH0 <<  4) | /* TWRPH0    = HCLK * (TWRPH0 + 1)   */
    (TWRPH1 <<  0);
    NF_Reset();
}

上面这段代码是直接可以在S3C2410A的stepldr中用滴。已经在我的开发板上实现了滴。

你可能感兴趣的:(c,cmd,Flash,buffer,byte,WinCE)