2416下Umon和nand的实现过程 [原创 2011-6-8 16:33:41]

来源:互联网 发布:原生js click事件 编辑:程序博客网 时间:2024/06/05 10:12

我顶 字号:  
  有网友来信要介绍一下Umon和nand在2416上的移植,时间有点久了,大概如下:

一. 需要实现三个文件:
    SD卡启动的boot、Nand上启动的Boot、Umon。

二. SD-boot启动文件:
 sd-boot主要代码如下,其中加载是利用了2416内置Irom提供的加载函数:

 void Lcd_Off(void);
void Clk0_Enable(int clock_sel);    
void Clk1_Enable(int clock_sel);
void Clk0_Disable(void);
void Clk1_Disable(void);
void ClearMemory(void);
volatile U32 downloadAddress; 
void Uart_SendString(char *str);

volatile U8 dma_done=0;
int download_run=0;
volatile U32 tempDownloadAddress;
int menuUsed=0;

extern char Image$$RW$$Limit[];
U32 *pMagicNum=(U32 *)Image$$RW$$Limit;
int consoleNum;

/** 
 * This Function copies a block of page to destination memory.( 8-Bit ECC only ) 
 * @param uint32 block : Source block address number to copy. 
 * @param uint32 page : Source page address number to copy. 
 * @param uint8 *buffer : Target Buffer pointer. 
 * @return int32 - Success or failure. 
 */  
#define NF8_ReadPage(a,b,c) (((int(*)(uint32, uint32, uint8*))(*((uint32 *)0x40004000)))(a,b,c)) 
/** 
 * This Function copies a block of page to destination memory( 8-Bit ECC only ) 
 * @param u32 block : Source block address number to copy. 
 * @param u32 page : Source page address number to copy. 
 * @param u8 *buffer : Target Buffer pointer. 
 * @return int  - Success or failure. 
 */  
#define NF8_ReadPage_Adv(a,b,c) (((int(*)(uint32, uint32, uint8*))(*((uint32 *)0x40004004)))(a,b,c)) 
/** 
  * This Function copy MMC(MoviNAND/iNand) Card Data to memory. 
  * Always use EPLL source clock. 
  * This function works at 25Mhz. 
  * @param u32 StartBlkAddress : Source card(MoviNAND/iNand MMC)) Address.(It must block address.) 
  * @param u16 blockSize : Number of blocks to copy. 
  * @param u32* memoryPtr : Buffer to copy from. 
* @param u32 extClockSpeed : External clock speed(per HZ) 
* @param bool with_init : determined card initialization. 
  * @return bool(u8) - Success or failure. 
  */ 

#define GLOBAL_VAL_BASE 0x40004000
// Card Information 
#define globalSDHCInfoBit   *((volatile unsigned int*) GLOBAL_VAL_BASE -0x8)) 
// SD/MMC Card Block Size. 
#define globalBlockSizeHide  *((volatile unsigned int*)( GLOBAL_VAL_BASE -0x4)) 
// Nand ECC Fail Counter 
#define globalNandECCfailureCount *((volatile unsigned int*)(GLOBAL_VAL_BASE-0x10)) 
// O/S kernel loading… 
//CopyMovitoMem( globalBlockSizeHide - 100, 80, (unsigned int*)0x50200000, 12000000, false); 

typedef unsigned char BOOL;
typedef unsigned int DWORD;
/*
CopyMovitoMem(HSMMC_CHANNEL, MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, MOVI_INIT_REQUIRED);
  HSMMC_CHANNEL这是SD/MMC通道号,手上板子运用的是CH1,而默认是CH0,所以须要对这个实行修改。
  MOVI_BL2_POS 是须要 copy 的数据位于SD的起始扇区,其计算要领 是这样的,
先得到这个SD的总扇区数TOTAL,再减去256K的BL2和8K的BL1所占的扇区数,
结尾减去0.5K 的eFuse和0.5K的保存区所占的扇区数,
而这里还解释SD的扇区为512B。从这里能够看到和IROM_Fusing_tools对SD卡的处理是完全对应的。
这里还有一个疑问,总扇区数TOTAL是如何得到的?从程序来看是从(TCM_BASE - 0x4)这个地址读取到的,
至于TOTAL是如何 被放到这里的就只好从BL0的代码找答案了。
  MOVI_BL2_BLKCNT是须要复制的扇区数目,这里就是解释为256K,
这也是为什么必须把u-boot.bin转换成256K的文件
  BL2_BASE是目标地址,也就是SDRAM中的地址。这里解释为0x57E0000?
是128M 的SDRAM的结尾 2M,因为到这里为止MMU尚未打开,因此这里运用的是物理地址。*/

#define BLOCK_SIZE 512
#define UMON_SIZE 256*1024
#define UMON_BLOCKS  (UMON_SIZE/BLOCK_SIZE)
#define KEPT_BLOCKS    2    //保留区
#define BL1_BLOCKS    16
#define UMON_ROBASE 0x33fb0000

#define CopyMovitoMem(a,b,c,d,e) (((bool(*)(u32,u16,u32*,u32,bool))(*((u32 *)0x40004008))) (a,b,c,d,e)) 

void (*restart)(void)=(void (*)(void))0x0;
void (*run)(void)=(void (*)(void))UMON_ROBASE;

BOOL CopyMMCtoMem(uint32 StartBlkAddr, uint16 BlocksNum,uint32 * MemPtr, BOOL With_Init)
{
    return CopyMovitoMem(StartBlkAddr,BlocksNum,MemPtr,12000000,With_Init);
}
//====================================================================
char *hex2char(unsigned int val)
{
    static char str[2];

    str[1]='\0';    
    
    if(val<=9)
        str[0]='0'+val;
    else 
        str[0]=('a'+val-10);
        
    return str;
}
//====================================================================
void Uart_SendDWORD(DWORD d, BOOL cr)
{
    Uart_SendString("0x");
    Uart_SendString(hex2char((d & 0xf0000000) >> 28));
    Uart_SendString(hex2char((d & 0x0f000000) >> 24));
    Uart_SendString(hex2char((d & 0x00f00000) >> 20));    
    Uart_SendString(hex2char((d & 0x000f0000) >> 16));
    Uart_SendString(hex2char((d & 0x0000f000) >> 12));
    Uart_SendString(hex2char((d & 0x00000f00) >> 8));
    Uart_SendString(hex2char((d & 0x000000f0) >> 4));
    Uart_SendString(hex2char((d & 0x0000000f) >> 0));
    if (cr)
        Uart_SendString("\n");
}

void Uart_SendString(char *str)
{
    while(*str)
        Uart_putc(*str++);
}
void MyDelay(int i)
{
    unsigned int j,k;
    for(;i;i--)
        for(j=0;j<120000/5;j++) k=i;
}
int main(void)
{
    
    register int i, block, blockcopy_count;

    block=1;
       blockcopy_count=1860;   
       SystemCLK();
    
    if(PCLK!=0x1cf7c58)
    {
        rGPCUDP=0x00000400;    
        rGPCDAT=0;
        while(1);
    }
    
    Console(1);    //开发板只提供了Uart1
    Isr_Init();    
    MyDelay(50);    
#if 0    
    for(i=0;i<10;i++)    //Just for debug
    {
        rGPCUDP=0x00000400;    
        rGPCDAT=0;
        MyDelay(500);
        printf("start");
        rGPCUDP=0x00000800;            
        rGPCDAT=0x020;
        MyDelay(500);        
    }
#endif    
    Uart_SendString("HuaTian sd boot.Compile @"__DATE__ ""__TIME__"\n");
    Uart_SendString("Total Blocks:");
    Uart_SendDWORD(UMON_BLOCKS,1);
    if(CopyMMCtoMem(globalBlockSizeHide-UMON_BLOCKS-KEPT_BLOCKS-BL1_BLOCKS,UMON_BLOCKS,(uint32 *)UMON_ROBASE,TRUE))
    {
        Uart_SendString("Load Umon from MMC ok!\n");
        run();
    }
    else
    {
        Uart_SendString("Load Umon from MMc failed!\n");
        while(1);
    }
    
}

三. Nand-boot代码,和sd-boot差不多。
extern char Image$$RW$$Limit[];
U32 *pMagicNum=(U32 *)Image$$RW$$Limit;
int consoleNum;

/** 
 * This Function copies a block of page to destination memory.( 8-Bit ECC only ) 
 * @param uint32 block : Source block address number to copy. 
 * @param uint32 page : Source page address number to copy. 
 * @param uint8 *buffer : Target Buffer pointer. 
 * @return int32 - Success or failure. 
 */  
#define NF8_ReadPage(a,b,c) (((int(*)(uint32, uint32, uint8*))(*((uint32 *)0x40004000)))(a,b,c)) 
/** 
 * This Function copies a block of page to destination memory( 8-Bit ECC only ) 
 * @param u32 block : Source block address number to copy. 
 * @param u32 page : Source page address number to copy. 
 * @param u8 *buffer : Target Buffer pointer. 
 * @return int  - Success or failure. 
 */  
#define NF8_ReadPage_Adv(a,b,c) (((int(*)(uint32, uint32, uint8*))(*((uint32 *)0x40004004)))(a,b,c)) 
/** 
  * This Function copy MMC(MoviNAND/iNand) Card Data to memory. 
  * Always use EPLL source clock. 
  * This function works at 25Mhz. 
  * @param u32 StartBlkAddress : Source card(MoviNAND/iNand MMC)) Address.(It must block address.) 
  * @param u16 blockSize : Number of blocks to copy. 
  * @param u32* memoryPtr : Buffer to copy from. 
* @param u32 extClockSpeed : External clock speed(per HZ) 
* @param bool with_init : determined card initialization. 
  * @return bool(u8) - Success or failure. 
  */ 

#define GLOBAL_VAL_BASE 0x40004000
// Card Information 
#define globalSDHCInfoBit   *((volatile unsigned int*) GLOBAL_VAL_BASE -0x8)) 
// SD/MMC Card Block Size. 
#define globalBlockSizeHide  *((volatile unsigned int*)( GLOBAL_VAL_BASE -0x4)) 
// Nand ECC Fail Counter 
#define globalNandECCfailureCount *((volatile unsigned int*)(GLOBAL_VAL_BASE-0x10)) 
// O/S kernel loading… 
//CopyMovitoMem( globalBlockSizeHide - 100, 80, (unsigned int*)0x50200000, 12000000, false); 

typedef unsigned char BOOL;
typedef unsigned int DWORD;
/*
CopyMovitoMem(HSMMC_CHANNEL, MOVI_BL2_POS, MOVI_BL2_BLKCNT, (uint *)BL2_BASE, MOVI_INIT_REQUIRED);
  HSMMC_CHANNEL这是SD/MMC通道号,手上板子运用的是CH1,而默认是CH0,所以须要对这个实行修改。
  MOVI_BL2_POS 是须要 copy 的数据位于SD的起始扇区,其计算要领 是这样的,
先得到这个SD的总扇区数TOTAL,再减去256K的BL2和8K的BL1所占的扇区数,
结尾减去0.5K 的eFuse和0.5K的保存区所占的扇区数,
而这里还解释SD的扇区为512B。从这里能够看到和IROM_Fusing_tools对SD卡的处理是完全对应的。
这里还有一个疑问,总扇区数TOTAL是如何得到的?从程序来看是从(TCM_BASE - 0x4)这个地址读取到的,
至于TOTAL是如何 被放到这里的就只好从BL0的代码找答案了。
  MOVI_BL2_BLKCNT是须要复制的扇区数目,这里就是解释为256K,
这也是为什么必须把u-boot.bin转换成256K的文件?
  BL2_BASE是目标地址,也就是SDRAM中的地址。这里解释为0x57E0000?
是128M 的SDRAM的结尾 2M,因为到这里为止MMU尚未打开,因此这里运用的是物理地址。*/

#define BYTES_PERPAGE    (2048)
#define PAGES_PERBLOCK    (64)
#define BYTES_PERBLOCK    (2048*64)
#define NK_SIZE     (8*1024*1024)        //NK 8M
#define NK_BLOCKS    (NK_SIZE/BYTES_PERBLOCK)
#define BL1_PAGES    2        //BOOT size
#define NK_ROBASE 0x30100000
#define NK_STARTBLOCK    (1)
#define BLOCKS_INNAND    (2048)

#define CopyMovitoMem(a,b,c,d,e) (((bool(*)(u32,u16,u32*,u32,bool))(*((u32 *)0x40004008))) (a,b,c,d,e)) 

void (*restart)(void)=(void (*)(void))0x0;
void (*run)(void)=(void (*)(void))NK_ROBASE;

BOOL CopyMMCtoMem(uint32 StartBlkAddr, uint16 BlocksNum,uint32 * MemPtr, BOOL With_Init)
{
    return CopyMovitoMem(StartBlkAddr,BlocksNum,MemPtr,12000000,With_Init);
}
//====================================================================
char *hex2char(unsigned int val)
{
    static char str[2];

    str[1]='\0';    
    
    if(val<=9)
        str[0]='0'+val;
    else 
        str[0]=('a'+val-10);
        
    return str;
}
//====================================================================
void Uart_SendString(char *str)
{
#ifdef    DEBUG_MODE
    while(*str)
        Uart_putc(*str++);
#endif        
}

void Uart_SendDWORD(DWORD d, BOOL cr)
{
#ifdef    DEBUG_MODE
    Uart_SendString("0x");
    Uart_SendString(hex2char((d & 0xf0000000) >> 28));
    Uart_SendString(hex2char((d & 0x0f000000) >> 24));
    Uart_SendString(hex2char((d & 0x00f00000) >> 20));    
    Uart_SendString(hex2char((d & 0x000f0000) >> 16));
    Uart_SendString(hex2char((d & 0x0000f000) >> 12));
    Uart_SendString(hex2char((d & 0x00000f00) >> 8));
    Uart_SendString(hex2char((d & 0x000000f0) >> 4));
    Uart_SendString(hex2char((d & 0x0000000f) >> 0));
    if (cr)
        Uart_SendString("\n");
#endif    
}

void MyDelay(int i)
{
    unsigned int j,k;
    for(;i;i--)
        for(j=0;j<120000/5;j++) k=i;
}
u16    *BlockMap;
int main(void)
{
    
    unsigned int i,j,k;
    u8 *p,*p1;
    BlockMap=(u16 *)0x32000000;
       SystemCLK();
       
    if(0)
    if(PCLK!=0x1cf7c58)
    {
        rGPCUDP=0x00000400;    
        rGPCDAT=0;
        while(1);
    }
    
    Console(1);    //开发板只提供了Uart1
    Isr_Init();    
    MyDelay(50);    
#if 0    
    for(i=0;i<10;i++)    //Just for debug
    {
        rGPCUDP=0x00000400;    
        rGPCDAT=0;
        MyDelay(500);
        printf("start");
        rGPCUDP=0x00000800;            
        rGPCDAT=0x020;
        MyDelay(500);        
    }
#endif    
    Uart_SendString("HuaTian nand boot.Compile @"__DATE__ ""__TIME__"\n");
    Uart_SendString("Total Blocks:");
    Uart_SendDWORD(NK_BLOCKS,1);
    if(0)
    {
        Uart_SendString("\nBoot cont:\n");
        for(p=(u8 *)0x40000000;p<(u8 *)(0x40000000+8*1024);p++)
        {
            Uart_SendString(hex2char((*p)>>4));
            Uart_SendString(hex2char((*p)&0x0f));
            if(((u32)p&0x0f)==0x0f) 
                Uart_SendString("\n");
            else
                Uart_SendString(" ");
        }        
    }
    
//    NF8_ReadPage_Adv(0,4,(u8 *)BlockMap);
//    NF8_ReadPage_Adv(0,5,(u8 *)BlockMap+(BLOCKS_INNAND/2));
    NF8_Init();
    Adv_NF8_ReadPage(0,4,(u8 *)BlockMap);
    Adv_NF8_ReadPage(0,5,(u8 *)&BlockMap[BLOCKS_INNAND/2]);
    
    p=(u8 *)NK_ROBASE;
    for(j=0;j<NK_BLOCKS;j++)
    {
        p1=p;
        k=BlockMap[j+NK_STARTBLOCK];
        for(i=0;i<PAGES_PERBLOCK;i++)
        {
            //NF8_ReadPage_Adv(k,i,p);
            Adv_NF8_ReadPage(k,i,p);
            p+=BYTES_PERPAGE;
        }
        for(i=0;i<BYTES_PERBLOCK;i++)
        {
            if((*p1)!=0xff)
                break;
            p1++;
        }
        if(i>=BYTES_PERBLOCK)
            break;
        Uart_SendString("\n Block:");
        Uart_SendDWORD(k,0);
    }
    Uart_SendString("\nkernel:\n");
    
    if(0)
    for((u32)p=NK_ROBASE;u32(p)<(NK_ROBASE+2048);p++)
    {
            Uart_SendString(hex2char((*p)>>4));
            Uart_SendString(hex2char((*p)&0x0f));
            if(((u32)p&0x0f)==0x0f) 
                Uart_SendString("\n");
            else
                Uart_SendString(" ");
    }
    Uart_SendString("To boot kernel...\n");
    run();
}

四. Umon的代码就好说了,把开发板上的拿过来修改下就行了,我这个做了一些有关nand的扩充。另外预定义__NANDBL不要设,现在代码上还有是没来得及删除这些东西。

主程序:
/**
* Project Name : S3C2450 verification project
*
* Copyright 2008 by Samsung Electronics, Inc.
* All rights reserved.
*
* Project Description :
* This software is only for verifying functions of the S3C2443. 
* Anybody can use this code without our permission.
*/

/**
* File Name    : 2450mon.cpp
* Description  : S3C2450 USB monitor main code
* Author       : Cha gyu hwan
* Dept         : Mobile solution, AP
* Created Date : 2008.02.21
* Version      : 0.0
* History
*   R0.0 (2008.02.): Cha gyu hwan draft
*/


#include "System.h"
#include "memtest.h"
#include "profile.h"
#include "usbdev.h"
#include "uartdown.h" 
#include "Movinand.h"
#include "nand.h"

//#define S3C2450onSMDK2443
#define USBDMA

#ifdef        __NANDBL
    volatile unsigned char *downPt;
    // Normal NAND :    1page = 256B or 512B, 1block = 32pages, total ? blocks..
    // Advanced NAND :    1page = 1K or 2KB, 1block = 32pages, total ? blocks..                       
    //#define    OS_IMAGE_SIZE 0x20            // block quantity for USB monitor : 512Kbyte(page=512B), 
    #define OS_IMAGE_SIZE 1860        // block quantity for WinCE : 32Mbyte(page=512B), 

    //#define    OS_START_ADDR_OFFSET (0x00000000)  // Mon start address
    //#define    OS_START_ADDR_OFFSET (0x00200000)  // OS start address
    #define    OS_START_ADDR_OFFSET (0x20)  // F/W Code start address
    //#define DOWNLOAD_ADDRESS (_NONCACHE_STARTADDRESS+OS_START_ADDR_OFFSET) //for debugging
    #define DOWNLOAD_ADDRESS (_RAM_STARTADDRESS+OS_START_ADDR_OFFSET)
#endif 

void Lcd_Off(void);
void Clk0_Enable(int clock_sel);    
void Clk1_Enable(int clock_sel);
void Clk0_Disable(void);
void Clk1_Disable(void);
void ClearMemory(void);
volatile U32 downloadAddress; 


#ifndef        __NANDBL
    void TestDownLoading(void);
    void WaitDownload(void);
    void Menu(void);
    void UsbMon(void);
    static void __irq Isr_Usb(void);
    void Vbus_detect_init(void);
    void Usb_power_en(void);
    void Usb_power_dis(void);
    void Usb_Reset(void);
    void Usb_Init(void);
    void USB_OnOff(void);
    static void __irq Vbus_detect(void);
    void WhichMemory(void);
    void Reset_Status_Check(void);
#endif

void (*restart)(void)=(void (*)(void))0x0;
void (*run)(void);

volatile U8 dma_done=0;
int download_run=0;
int download_promgram=0;
int g_TagetNandBlock=0;
volatile U32 tempDownloadAddress;
int menuUsed=0;
uint16 g_PhBlockNum[BLOCKS_INNAND];
t_strInfo    g_SysInfo;
extern char Image$$RW$$Limit[];
U32 *pMagicNum=(U32 *)Image$$RW$$Limit;
int consoleNum;

#ifdef USBDMA
    static USB_OP eOpMode = USB_DMA;
#else
    static USB_OP eOpMode = USB_CPU;
#endif

int main(void)
{
#ifdef        __NANDBL
    register int i, block, blockcopy_count;

    block=1;
       blockcopy_count=1860;   
       SystemCLK();
#else
       SystemCLK(0); 
#endif
    Console(1);
    Isr_Init();
    NF8_Init();    

#ifdef        __NANDBL
    downPt=(unsigned char *)(DOWNLOAD_ADDRESS);        
    
    while(blockcopy_count<=OS_IMAGE_SIZE)        
    {
        block++;        
        Uart_putc('B');
        if(!NF8_IsBadBlock(block)) continue;    //  Skip bad block
        blockcopy_count++;

        for(i=0;i<32;i++)   // Read 32 page
        {
            if(!NF8_ReadPage(block, i, (unsigned char *)downPt))   //1
            {       
                while(1);
            }
            downPt += 512;        // Next page
        }        
        Uart_putc('A');
        if (blockcopy_count == OS_IMAGE_SIZE)
        {

        }
    }        
    run=(void (*)(void))(DOWNLOAD_ADDRESS);    
    run();
#else
    printf("Njs 2416 SD-UMON Compile at: %s--%s\n",__DATE__,__TIME__);
    UsbMon();
#endif

}

#ifndef        __NANDBL



void UsbMon(void)
{

    Usb_power_en();
    
    if (rRSTSTAT&0x8) rRSTCON|=(1<<16); //if reset by sleep wakeup, control the retention I/O cell

    //USB Port is Normal mode
    rMISCCR=rMISCCR&~(1<<12);  // USBD is 0 ,normal mode ,1 is suspend mode /
    rPWRCFG |= (0x1<<4); // phy power enable 

    pISR_USBD =(unsigned)Isr_Usb;    
    
    #ifndef S3C2450onSMDK2443
        pISR_EINT2 = (U32)Vbus_detect;
        Vbus_detect_init();
    #endif 
    
    Usb_Init();
    
    Delay(0);  //calibrate Delay()
//        Led_Display(0x6);
    rGPCUDP=0x00000400;    
    rGPCDAT=0;


//    rUSB_CLKCON = (0x1<<31)|(0x1<<2)|(0x0<<1)|(0x1<<0); // vbus detect enable...
    //D+ pull up , USB2.0 Function clock Enable, USB1.1 HOST disable,USB2.0 PHY test enable

    // CLKOUT0/1 select.
    printf("CLKOUT0:MPLL in, CLKOUT1:RTC clock.\n");
       printf("\n");
       printf("+-----------------------------------------------+\n");
       printf("| Huartian 2416 USB Downloader  %s----%s    +\n",__DATE__,__TIME__);
       printf("+-----------------------------------------------+\n");
       WhichMemory();
       printf("MPLL=%.2fMHz, ARMCLK=%.2fMHz (%d:%d:%d), HCLK=%.2fMHz, PCLK=%.2fMHz\n\n",
           (float)MPLL/1000000,(float)ARMCLK/1000000,ARMCLKdiv+1,(PREdiv+1)*(HCLKdiv+1),(PREdiv+1)*(HCLKdiv+1)*(PCLKdiv+1),(float)HCLK/1000000,(float)PCLK/1000000);
       printf("USB: IN_ENDPOINT:1 OUT_ENDPOINT:3\n"); 
       printf("FORMAT: <ADDR(DATA):4>+<SIZE(n+10):4>+<DATA:n>+<CS:2>\n");
       printf("NOTE: 1. Power off/on or press the reset button for 1 sec\n");
       printf("         in order to get a valid USB device address.\n");
       printf("      2. For additional menu, Press any key. \n");
       printf("\n");

////for 2443 switch to 2450 
#ifndef S3C2450onSMDK2443  
    USB_OnOff();
#endif     
    download_run=1; //The default menu is the Download & Run mode.
    
    Reset_Status_Check();
    AllocateUSBDEV();
    while(1)
    {
    
    #ifdef USBDMA
        eOpMode =USB_DMA; 
    #else
        eOpMode =USB_CPU; 
    #endif
        UsbdMain(); 
        if(menuUsed==1)Menu();
        WaitDownload();
    }
    FreeUSBDEV();
    

}

void UsbdMain(void)
{
    SetOpMode(eOpMode);
   // Init();
}
void MarkBadBlock()
{
    int blocknum=0;
    char key;
    printf("Pls input block num(dec or hex):");
    blocknum=GetIntNum();
    printf("\nDo you confirm mark block %d as bad block? y/n",blocknum);
    while(1)
    {
        key=getchar();
        if(key=='y' || key=='n') break;
    }
    if(key=='y') Adv_NF8_MarkBadBlock(blocknum);
}
void RemoveBadBlockMark()
{
    int blocknum=0;
    char key;
    printf("Pls input block num(dec or hex):");
    blocknum=GetIntNum();
    printf("\nDo you confirm remove bad mark of block %d and erase? y/n",blocknum);
    while(1)
    {
        key=getchar();
        if(key=='y' || key=='n') break;
    }
    if(key=='y') Adv_NF8_EraseBlock(blocknum);
}
int SpecialFunc()
{
    bool exitloop=false;
    char key;
    while(!exitloop)
    {
        printf("\n------Select Function------\n");
        printf("1. Check Bad Block\n");
        printf("2. Read Page \n");
        printf("3. Manul mark bad block \n");
        printf("4. Remove bad block mark \n");
        printf("5. Erase one block \n");
        printf("6. back to main menu \n");
        key=getchar();
        switch (key)
        {
            case '1':
                Adv_NF8_PrintBadBlockNum();
                exitloop=true;
                break;
            case '2':
                Test_Adv_NF8_Page_Read();
                exitloop=true;                
                break;
            case '3':
                MarkBadBlock();
                exitloop=true;                
                break;
            case '4':
                RemoveBadBlockMark();
                exitloop=true;                
                break;                
            case '5':
                Test_Adv_NF8_Block_Erase();
                exitloop=true;                
                break;
            case '6':
                exitloop=true;
                break;
            default:
                break;
        }
    }
#if 0    
    printf("Mark 2,3,4,5 as bad block!");
    NF8_Init();
    Adv_NF8_MarkBadBlock(2);
    Adv_NF8_MarkBadBlock(3);
    Adv_NF8_MarkBadBlock(4);
    Adv_NF8_MarkBadBlock(5);    
#endif    
    return TRUE;
}
int FormatNand()
{
    uint32 i;
    NF8_Init();
    for(i=0;i<BLOCKS_INNAND;i++)
    {
        if(Adv_NF8_IsBadBlock(i)!=FAIL)
            Adv_NF8_EraseBlock(i);
    }
    printf("Formate Over!\n");
    return TRUE;
}
void Menu(void)
{
    U8 key;
    menuUsed=1;
    while(1)
    {
        printf("\n###### Select Menu ######\n");
        printf(" [0] Download & Run\n");
        printf(" [1] Download Only\n");
        printf(" [2] Download & Program Nk\n");
        printf(" [3] Test SDRAM \n");
        printf(" [4] Clear SDRAM \n");
        printf(" [5] Special Func.\n");
         printf(" [6] Download with UART\n");
         printf(" [7] Download & Program Nk with UART\n");
        printf(" [8] Upload with USB 2.0 device \n");
        printf(" [9] Format Nand Flash \n");
        key=getchar();
        
        switch(key)
        {
        case '0':
            printf("\nDownload&Run is selected.\n\n");
            download_run=1;
            download_promgram=0;
            return;
        case '1':
            printf("\nDownload Only is selected.\n");
            printf("Enter a new temporary download address(0x3...):");
            tempDownloadAddress=GetIntNum();
            if((tempDownloadAddress<0x30000000) || (tempDownloadAddress>0x34000000))
                tempDownloadAddress=0x30000000;
            download_run=0;
            download_promgram=0;
            printf("The temporary download address is 0x%x.\n\n",tempDownloadAddress);
            return;
        case '2':
            printf("\nDownload  And Program Nk is selected.\n");
            printf("Enter a new temporary download address(0x3...):");            
            tempDownloadAddress=GetIntNum();
            if((tempDownloadAddress<0x30000000) || (tempDownloadAddress>0x34000000))
                tempDownloadAddress=0x30000000;            
            download_run=0;
            download_promgram=1;
            printf("\nThe temporary download address is 0x%x.\n\n",tempDownloadAddress);
            printf(" Enter Taget Block : ");
            g_TagetNandBlock=GetIntNum();
            printf(" \nThe taget nand block is :%d\n\n",g_TagetNandBlock);
            return;                
        case '3':
            printf("\nMemory Test is selected.\n");
            MemoryTest();
            Menu();
            return;
        case '4':
            printf("\nMemory Clear is selected.\n");
            ClearMemory();
            Menu();
            return;
        case '5':
            printf("This function has been removed! \n");
            SpecialFunc();
#if 0                
            printf("\nWhich UART channel do you want to use for the console?[0/1]\n");
            if(getchar()!='1')
            {
                *pMagicNum=0x0;
                printf("UART ch.0 will be used for console at next boot.\n");                    
            }
            else
            {
                *pMagicNum=0x12345678;
                 printf("UART ch.1 will be used for console at next boot.\n");        
                printf("UART ch.0 will be used after long power-off.\n");
            }
            printf("System is waiting for a reset. Please, Reboot!!!\n");
            while(1);
#endif                
            break;
        case '6':  // 
            printf("\nDownload  with UART\n");
            UartMON(0);
            return;
        case '7':  // 
            printf("\nDownload and program with UART\n");
            UartMON(1);
            return;                
        case '8':  //
            printf("\nUpload file !!\n");
            SetOpMode(eOpMode); 
            getchar();
            return;
        case '9':
            printf("\n Format Nand Disk !!\n");
            FormatNand();
            break;;
        default:
            break;
        }    
    }        

}

    //extern U32 checkTest;
int CheckNandFormat()
{
    uint8 *buff;
    uint32 i;
    buff=(uint8 *)malloc(BYTES_PERPAGE*2);
    if(buff==NULL)
    {
        printf("Can not malloc mem!Progarm Nk failed!\n");
        return FALSE;
    }
    Adv_NF8_ReadPage(0,0,buff);
    Adv_NF8_ReadPage(0,0,buff+BYTES_PERPAGE);            
    for(i=0;i<BYTES_PERPAGE*2;i++)
        if(*buff!=0xff)
        {
            printf("Nand have not format ! Abort!\n");
            free(buff);
            return FALSE;
        }
    return TRUE;
}
int MakeSysInfo()
{
    uint32 j,i;
    //检查坏块,形成Block Remap 信息
    j=0;    //逻辑,即数组下标
    for(i=0;i<BLOCKS_INNAND;i++)
    {
        if(Adv_NF8_IsBadBlock(i)==OK)
        {
            g_PhBlockNum[j++]=i;
        }
    }
    g_SysInfo.BlocksInNand=BLOCKS_INNAND;
    g_SysInfo.BytesPerPage=BYTES_PERPAGE;
    g_SysInfo.PagesPerBlock=PAGES_PERBLOCK;
    g_SysInfo.TotalBadBlocks=i-j;
    printf("Marked bad blocks total number: %d\n",g_SysInfo.TotalBadBlocks);
    return TRUE;
}
void ProgramNand()
{
    uint32 blocknum=g_TagetNandBlock;
    uint32 pagenum=0;
    uint32 DataSize=g_uDownloadFileSize;
    uint8 *p=(uint8 *)g_uDownloadAddress;
    Adv_NF8_EraseBlock(g_PhBlockNum[blocknum]);
    while(1)
    {
        if(DataSize>BYTES_PERPAGE)
        {
            if(!Adv_NF8_WritePage(g_PhBlockNum[blocknum],pagenum,p))
            {
                printf("Write page error @ Logic Block: %d Phsical Block:%d Page:%d\n",
                    g_PhBlockNum[blocknum],blocknum,pagenum);
                return;
            }
            p+=BYTES_PERPAGE;
            DataSize-=BYTES_PERPAGE;
            pagenum++;
            if(pagenum>=PAGES_PERBLOCK)
            {
                pagenum=0;
                blocknum++;
                Adv_NF8_EraseBlock(g_PhBlockNum[blocknum]);
            }                    
        }
        else
        {
            Adv_NF8_WritePage(g_PhBlockNum[blocknum],pagenum,p);
            break;
        }
    }
    if(g_TagetNandBlock==0)
    {
        Adv_NF8_WritePage(0,4,(uint8 *)g_PhBlockNum);
        Adv_NF8_WritePage(0,5,(uint8 *)g_PhBlockNum+BYTES_PERPAGE);
        Adv_NF8_WritePage(0,6,(uint8 *) (&g_SysInfo));
    }
    printf("\nWrite over! Start virify!\n");
     blocknum=g_TagetNandBlock;
     pagenum=0;
     DataSize=g_uDownloadFileSize;
     p=(uint8 *)g_uDownloadAddress;
    uint8 *buff=(uint8 *)malloc(BYTES_PERPAGE);
    if(p==NULL)
    {
        printf("malloc error! @%s exit \n",__LINE__);
    }
    while(1)
    {
        if(DataSize>BYTES_PERPAGE)
        {
            if(!Adv_NF8_ReadPage(g_PhBlockNum[blocknum],pagenum,buff))
            {
                printf("Read page error @ Logic Block: %d Phsical Block:%d Page:%d\n",
                    g_PhBlockNum[blocknum],blocknum,pagenum);
                free(p);
                return;
            }
            if(memcmp(p, buff,BYTES_PERPAGE))
            {
                printf("Verify failed @ Logic Block: %d Phsical Block:%d Page:%d\n",
                    g_PhBlockNum[blocknum],blocknum,pagenum);
                free(buff);
                return;
            }
            p+=BYTES_PERPAGE;
            DataSize-=BYTES_PERPAGE;                    
            pagenum++;
            if(pagenum>=PAGES_PERBLOCK)
            {
                pagenum=0;
                blocknum++;
            }                    
        }
        else
        {
            Adv_NF8_ReadPage(g_PhBlockNum[blocknum],pagenum,buff);
            if(memcmp(p, buff,DataSize))
            {
                printf("Verify failed @ Logic Block: %d Phsical Block:%d Page:%d\n",
                    g_PhBlockNum[blocknum],blocknum,pagenum);
            }
            break;
        }
    }        
    if(g_TagetNandBlock==0)
    {
        Adv_NF8_ReadPage(0,4,buff);
        if(memcmp((uint8 *)g_PhBlockNum, buff,BYTES_PERPAGE))
        {
            printf("Verify failed @ block 0, page4\n");
        }
        Adv_NF8_ReadPage(0,5,buff);
        if(memcmp((uint8 *)g_PhBlockNum+BYTES_PERPAGE, buff,BYTES_PERPAGE))
        {
            printf("Verify failed @ block 0, page5\n");
        }
        Adv_NF8_ReadPage(0,6,buff);
        if(memcmp((uint8 *)(&g_SysInfo), buff,sizeof(g_SysInfo)))
        {
            printf("Verify failed @ block 0, page6\n");
        }
    }
    
    free(buff);
    printf("Verify Pass!\n");        
}

void WaitDownload(void)
{
    U32 i;
    U32 j;
    U16 cs;
    U32 temp;
    U16 dnCS;
    int first=1;
    float time;
    U8 tempMem[16];
    U8 key;


    g_uDownloadAddress=(U32)tempMem; //_RAM_STARTADDRESS; 
    g_uDownloadFileSize=0;
    
    /*******************************/
    /*    Test program download    */
    /*******************************/
    j=0;

    if(IsEnumerationDone()==false)
    {
    printf("USB host is not connected yet.\n");
    }
    while(g_uDownloadFileSize==0)
    {
        if(first==1 && IsEnumerationDone()==true)
        {
            printf("USB host is connected. Waiting a download.\n");
            first=0;
        }
        if(j%0x50000==0)Led_Display(0x6);
        if(j%0x50000==0x28000)Led_Display(0x9);
        j++;
        key=Uart_GetKey();
        if(key!=0)
        {
            Menu();
            first=1; //To display the message,"USB host ...."
        }
    }
    
    StartStopwatch();  
    printf("\nNow, Downloading [ADDRESS:%xh,TOTAL:%d]\n",
            g_uDownloadAddress,g_uDownloadFileSize);
    printf("RECEIVED FILE SIZE:%8d",0);
    while(1)    //((U32)g_pDownPt-g_uDownloadAddress)<(g_uDownloadFileSize-8)
    {
        U32 tmpu32;
        tmpu32=(U32)g_pDownPt-g_uDownloadAddress;
        if (tmpu32>(g_uDownloadFileSize-8)) break;
//        if ((tmpu32 & (10*1024))==0)    //处理不过来.
//        {
//            printf("\b\b\b\b\b\b\b\b%8d",tmpu32);
//        }
        if(dma_done ==1)break;
    }
    dma_done=0;
    time=EndStopwatch();
    printf("\b\b\b\b\b\b\b\b%8d",g_uDownloadFileSize);    
    
    printf("\n(%5.1fKB/S,%3.1fS)\n",(float)(g_uDownloadFileSize/time*1000.),time/1000000);
    printf("RECEIVE FILE DONE !! \n");
    
    if(download_run==1)
    {
        rINTMSK=BIT_ALLMSK;
        run=(void (*)(void))g_uDownloadAddress;
        run();
    }
    if(download_promgram==1)
    {
        // njs add to program file to Nk.
        //g_TagetNandBlock
        //检查是否已格式化
        NF8_Init();
        //if(!CheckNandFormat())    return;
        MakeSysInfo();
        ProgramNand();
    }
}


static void __irq Isr_Usb(void)
{
    rINTMSK |=(BIT_USBD);
    
    HandleEvent();
    ClearPending(BIT_USBD);
    
    rINTMSK &= ~(BIT_USBD);
}

void Vbus_detect_init(void)
{
//for 2443 switch to 2450
#ifndef S3C2450onSMDK2443
    rGPFUDP = (rGPFCON & ~(0x3<<4));        
#endif
    rGPFCON = (rGPFCON & ~(0x3<<4))|(2<<4);            //GPF2 = EINT2
    rEXTINT0 = (rEXTINT0 & ~(0xf<<8))  | (0x7<<8) ; //EINT2=pull down disable,high level triggered
    
    rEINTPEND = 0xffffff;

    rSRCPND = BIT_EINT2; //to clear the previous pending states
    rINTPND = BIT_EINT2;

    rEINTMASK &= ~((1<<2));
    rINTMSK &= ~(BIT_EINT2);
}

void Usb_power_en(void)
{
    // In SOM2416, this pin is open
#if 0        
    rGPHUDP|=(0x1<<28); // for usb power enable....
    rGPHCON|=(0x1<<28); // for usb power enable....
    rGPHDAT|=(0x1<<14); // for usb power enable....
#endif        
}

void Usb_power_dis(void)
{
    rGPHUDP|=(0x3<<28); // for usb power disable....
    rGPHCON|=(0x1<<28); // for usb power disable....
    rGPHDAT&=~(0x1<<14); // for usb power disable....
}

void Usb_Reset(void)
{
    rUSB_RSTCON = (0x0<<2)|(0x0<<1)|(0x1<<0);//Function 2.0 S/W reset, Host 1.1 S/W reset,PHY 2.0 S/W reset
    Delay(2); // phy reset must be asserted for at 10us 
    rUSB_RSTCON = (0x1<<2)|(0x1<<1)|(0x0<<0);//Function 2.0 S/W reset, Host 1.1 S/W reset,PHY 2.0 S/W reset
    rUSB_RSTCON = (0x0<<2)|(0x0<<1)|(0x0<<0);//Function 2.0 S/W reset, Host 1.1 S/W reset,PHY 2.0 S/W reset
    Delay(20); 
}

void Usb_Init(void)
{
    //for 2443 switch to 2450
    #ifdef S3C2450onSMDK2443
        rUSB_PHYCTRL =(0x0<<3)|(0x0<<2)|(0x1<<1)|(0x0<<0);  //48Mhz,x-tal,External X-tal,device
    #else
//            rUSB_PHYCTRL =(0x0<<3)|(0x1<<2)|(0x1<<1)|(0x0<<0);  //48Mhz,OSC,External X-tal,device
        rUSB_PHYCTRL =(0x0<<3)|(0x0<<2)|(0x1<<1)|(0x0<<0);  //KIT2416 48Mhz,x-tal,External X-tal,device
    #endif
    
    rUSB_PHYPWR = (0x0<<31)|(0x3<<4)|(0x0<<3)|(0x0<<2)|(0x0<<1)|(0x0<<0); 
    //48Mhz clock on ,PHY2.0 analog block power on,XO block power on,XO block power in suspend mode,PHY 2.0 Pll power on ,suspend signal for save mode disable 
     
    rUSB_CLKCON = (0x0<<31)|(0x1<<2)|(0x0<<1)|(0x0<<0); // vbus detect enable...
    //D+ pull up , USB2.0 Function clock Enable, USB1.1 HOST disable,USB2.0 PHY test enable
    
    //for 2443 switch to 2450
    #ifdef S3C2450onSMDK2443
        rUSB_CLKCON = (0x1<<31)|(0x1<<2)|(0x0<<1)|(0x1<<0); // vbus detect enable...
    #endif
     
    Init();
    MMU_EnableICache();  
    
//    rTR |=0x2<<6; 
    
    ClearPending(BIT_USBD);
    rINTMSK&=~(BIT_USBD);   // usb interrupt enable 

}


void USB_OnOff(void)
{
    if((rGPFDAT&(0x1<<2))==0)
    {
       
         printf("disconnected\n");
         Usb_power_dis();
         rUSB_CLKCON = (0x0<<31)|(0x1<<2)|(0x0<<1)|(0x1<<0); // vbus detect enable...
         rMISCCR=rMISCCR|(1<<12);  // USBD is 0 ,normal mode ,1 is suspend mode /
        rPWRCFG &= ~(0x1<<4); // phy power enable 
    }
     else   
     {    
         printf("connected\n");
         Usb_power_en();
         
         Delay(10);
                //USB Port is Normal mode
        rMISCCR=rMISCCR&~(1<<12);  // USBD is 0 ,normal mode ,1 is suspend mode /
        rPWRCFG |= (0x1<<4); // phy power enable 

        Usb_Reset(); // 
        Usb_Init();
        rUSB_CLKCON = (0x1<<31)|(0x1<<2)|(0x0<<1)|(0x0<<0); // vbus detect enable...
        //D+ pull up , USB2.0 Function clock Enable, USB1.1 HOST disable,USB2.0 PHY test enable
        
     }
}


static void __irq Vbus_detect(void)
{
    
    rEINTMASK |= ((1<<2));
    
//    printf("rGPFDAT =%x \n",rGPFDAT&(0x1<<2));
    
    USB_OnOff();
    
    ClearPending(BIT_EINT2);
    rEINTPEND=(1<<2);
    rEINTMASK &= ~((1<<2));
}


void WhichMemory(void)
{
    
    if(rBANKCFG & (0x1<<3))
    {
        printf("mDDR\n");    
    }else{
        printf("mSDR\n");    
    }
}

#endif


void Reset_Status_Check(void)
{
    printf("reset status register = %08x\n", rRSTSTAT);
    

    
    if( rRSTSTAT & (1<<0) )
    {
        printf("Power-on Reset\n");
    }

    else if( rRSTSTAT & (1<<2) )
    {
        printf("\nWatch-dog Reset\n\n");
        run=(void (*)(void))0x30000000;
        run();
    }
    else if( rRSTSTAT & (1<<3) )//Sleep mode wake-up
    {
        printf("\nSLEEP mode Wake-up\n\n");
        run=(void (*)(void))0x30000000;
        run();
    }
    else if( rRSTSTAT & (1<<4) )
    {
        printf("\nDeep STOP mode Wake-up\n\n");
        run=(void (*)(void))0x30000000;
        run();
    }
    else if( rRSTSTAT & (1<<5) )
    {
        printf("\nSoft Reset\n\n");
        run=(void (*)(void))0x30000000;
        run();
    }
}

五. sd-irom制作
  sd-boot注意连接时的地址,编绎完的代码不能超过8K。然后用工具把文件扩充到8K,然后把sd-boot和umon的bin文件合并到一起,命令:
  批处理命令:
copy /y ..\SD-BOOT\SDLoader.nb0 .
copy /b/y SD-Umon.bin+SDLoader.nb0 SD-IROM.nb0
pause

  另附本人做的小工具下载地址:
http://ishare.iask.sina.com.cn/f/13568428.html

六. nand启动制作
  用sd 启动后,把nand-boot和umon烧进去就ok了。
0 0