基于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中用滴。已经在我的开发板上实现了滴。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值