字号:大 中 小
有网友来信要介绍一下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了。