📄 nand.c
字号:
void disable_irq(void);
void call_linux(U32 a0, U32 a1, U32 a2)
{
void (*goto_start)(U32, U32);
rINTMSK=BIT_ALLMSK;
cache_clean_invalidate();
tlb_invalidate();
__asm{
// mov r0, a0//%0
// mov r1, a1//%1
// mov r2, a2//%2
mov ip, #0
mcr p15, 0, ip, c13, c0, 0 /* zero PID */
mcr p15, 0, ip, c7, c7, 0 /* invalidate I,D caches */
mcr p15, 0, ip, c7, c10, 4 /* drain write buffer */
mcr p15, 0, ip, c8, c7, 0 /* invalidate I,D TLBs */
mrc p15, 0, ip, c1, c0, 0 /* get control register */
bic ip, ip, #0x0001 /* disable MMU */
mcr p15, 0, ip, c1, c0, 0 /* write control register */
//mov pc, r2
//nop
//nop
/* no outpus */
//: "r" (a0), "r" (a1), "r" (a2)
}
// SetClockDivider(1, 1);
// SetSysFclk(FCLK_200M); //start kernel, use 200M
//SET_IF();
goto_start = (void (*)(U32, U32))a2;
(*goto_start)(a0, a1);
}
extern int sprintf(char * /*s*/, const char * /*format*/, ...);
static void LoadRun(void)
{
U32 i, ram_addr, buf = boot_params.run_addr.val;
struct param_struct *params = (struct param_struct *)0x30000100;
int size;
memset(params, 0, sizeof(struct param_struct));
/*{
U32 *pD = (U32 *)0x30000100;
for(i=0; i<0x1000; i++)
pD[i] = 0;
}*/
if(boot_params.start.val) {
char parameters[512];
char *rootfs;
char initrd[32];
char *tty_sel;
char *devfs_sel;
switch (boot_params.root_sel.val) {
case 0:
rootfs = "/dev/ram";
break;
case 1:
rootfs = "nfs";
break;
case 2:
rootfs = "/dev/mtdblock2";
break;
case 3:
rootfs = "/dev/mtdblock3";
break;
case 4:
rootfs = "/dev/hda1";
default:
rootfs=""; //user define
break;
}
if(boot_params.root_sel.val)
sprintf(initrd, "load_ramdisk=0");
else
sprintf(initrd, "initrd=0x%08x,0x%08x",
boot_params.initrd_addr.val,
boot_params.initrd_len.val);
switch (boot_params.tty_sel.val) {
case 0:
tty_sel="ttySAC0";
break;
case 1:
tty_sel="ttySAC1";
break;
case 2:
tty_sel="ttsA/0";
break;
default:
tty_sel="ttySAC1"; //user define
break;
}
if(boot_params.devfs_sel.val)
devfs_sel = "devfs=mount";
else
devfs_sel = "";
memset(parameters, 0, sizeof(parameters));
sprintf(parameters,
"root=%s init=/linuxrc %s console=%s,%d mem=%dK %s %s",
rootfs,
initrd,
tty_sel,
boot_params.serial_baud.val,
boot_params.mem_cfg.val>>10,
devfs_sel,
boot_params.string);
params->u1.s.page_size = LINUX_PAGE_SIZE;
params->u1.s.nr_pages = (boot_params.mem_cfg.val >> LINUX_PAGE_SHIFT);
memcpy(params->commandline, parameters, strlen(parameters));
printf("Set boot params = %s\n", params->commandline);
}
printf("Load Kernel...\n");
if(boot_params.osstor.val) //load program from NOR or NAND FLASH
memcpy((void *)buf, (void *)(0x04000000+0x00020000), 0x001e0000);
else {
StartPage = NandPart[1].offset>>9;
size = NandPart[1].size;
ram_addr = buf;
for(i=0; size>0; ) {
if(!(i&0x1f)) {
if(CheckBadBlk(i+StartPage)) {
printf("Skipped bad block at 0x%x\n", i+StartPage);
i += 32;
size -= 32<<9;
continue;
}
}
ReadPage((i+StartPage), (U8 *)ram_addr);
i++;
size -= 512;
ram_addr += 512;
}
}
if(!boot_params.root_sel.val) {
int ramdisk_sz;
printf("Load Ramdisk...\n");
StartPage = NandPart[2].offset>>9;
size = NandPart[1].size;
ram_addr = boot_params.initrd_addr.val;
ramdisk_sz = boot_params.initrd_len.val;
for(i=0; size>0&&ramdisk_sz>0; ) {
if(!(i&0x1f)) {
if(CheckBadBlk(i+StartPage)) {
printf("Skipped bad block at 0x%x\n", i+StartPage);
i += 32;
size -= 32<<9;
continue;
}
}
ReadPage((i+StartPage), (U8 *)ram_addr);
i++;
size -= 512;
ram_addr += 512;
ramdisk_sz -= 512;
}
}
DsNandFlash();
//ChangeClockDivider(13,12);
//ChangeMPllValue(67,1,1); //300MHz,2440A!
//rCLKCON = 0x7fff0;
call_linux(0, boot_params.machine.val, buf);
}
/************************************************************/
static int have_nandflash;
static void InitNandFlash(int info)
{
U32 i;
InitNandCfg();
i = ReadChipId();
if(info)
printf("Read chip id = %x\n", i);
if((i==0x9873)||(i==0xec75))
NandAddr = 0;
else if(i==0xec76)
NandAddr = 1;
else {
if(info)
puts("Chip id error!!!\n");
have_nandflash = 0;
return;
}
have_nandflash = 1;
if(info)
printf("Nand flash status = %x\n", ReadStatus());
}
void NandErase(void)
{
int i, err = 0;
InitNandFlash(1);
if(!have_nandflash)
return;
i = NandSelPart("erase");
if(i<0)
return;
printf("Are you sure to erase nand flash from page 0x%x, block count 0x%x ? [y/n]\n", StartPage, BlockCnt);
while(1) {
char c;
c = getch();
if((c=='y')||(c=='Y'))
break;
if((c=='n')||(c=='N'))
return;
}
for(i=0; BlockCnt; BlockCnt--, i+=32) {
if(EraseBlock(i+StartPage)) {
err ++;
puts("Press any key to continue...\n");
getch();
}
}
DsNandFlash(); //disable nand flash interface
puts("Erase Nand partition completed ");
if(err)
printf("with %d bad block(s)\n", err);
else
puts("success\n");
}
int NandWrite(void)
{
int Ret;
InitNandFlash(1);
if(!have_nandflash)
return -1;
Ret = WrFileToNF();
DsNandFlash(); //disable nand flash interface
return Ret;
}
extern MemoryTest(void);
int RelocateNKBIN(U32 img_src, U32 *pStart, U32 *pLength, U32 *pLaunch);
static void LoadRunWince(void)
{
const U32 NK_SIZE = (32 * 1024 * 1024); //NK大小
U32 i, ram_addr, buf = boot_params.initrd_addr.val;//_RAM_STARTADDRESS+0x00200000;//
long size;
MemoryTest();
printf("Load Kernel...\n");
printf("run flash address 0x%08x...\n", buf);
if(boot_params.osstor.val) //load program from NOR or NAND FLASH
{
memcpy((void *)buf, (void *)(0x04000000+0x00020000), 0x00fe0000);
}
else {
StartPage = NandPart[boot_params.start.val].offset>>9; //part 2,3...
size = NandPart[boot_params.start.val].size;
ram_addr = buf;
printf("size%d\n", size);
printf("StartPage%d\n", StartPage);
for(i=0; size>0; ) {
if(!(i&0x1f)) {
if(CheckBadBlk(i+StartPage)) {
printf("Skipped bad block at 0x%x\n", i+StartPage);
i += 32;
//size -= 32<<9;
continue;
}
}
ReadPage((i+StartPage), (U8 *)ram_addr);
i++;
size -= 512;
ram_addr += 512;
}
}
//RelocateNKBIN(buf, &buf, &i, &boot_params.run_addr.val);
printf("run 0x%08x...\n", buf);
call_linux(0, 0, buf);
}
void NandLoadRun(void)
{
InitNandFlash(1);
//if(!have_nandflash)
// return;
if(boot_params.start.val<2) //linux
LoadRun();
LoadRunWince();
}
/*
void TestNandFlash(void)
{
InitNandFlash();
while(1)
{
U8 key = '2';
puts("\nNand flash operations, press ESC to exit\n");
puts("1.Write nand flash with download file\n");
puts("2.Load progam from nand flash and run\n");
puts("3.Erase nand flash partition\n");
puts("4.Test nand flash erase, write, read\n");
key = getch();
if(key==0x1b)
goto TestNandExit;
else if(key=='1')
WrFileToNF();
else if(key=='2')
LoadRun();
else if(key=='3')
NandErase();
else if(key=='4')
TestFunc();
}
TestNandExit:
DsNandFlash(); //disable nand flash interface
}*/
int search_params(void)
{
U32 page, page_cnt;
U8 dat[528];
BootParams *pBP = (BootParams *)dat;
int ret=-1;
InitNandFlash(0); //don't show info in InitNandFlash!
if(have_nandflash) {
page = NandPart[0].offset>>9;
page_cnt = NandPart[0].size>>9;
//search from the last page
while(page_cnt--) {
ReadPage(page+page_cnt, dat);
if(!strncmp(boot_params.start.flags, pBP->start.flags, 10)) {
ret = 0;
break;
}
}
} else {
ret = 0;
}
DsNandFlash();
if(!ret) {
ParamItem *pPIS = &pBP->start, *pPID = &boot_params.start;
for(; pPID<=&boot_params.user_params; pPIS++, pPID++)
if(!strncmp(pPID->flags, pPIS->flags, sizeof(pPID->flags)))
pPID->val = pPIS->val;
strncpy(boot_params.string, pPIS->flags, boot_params.user_params.val+1);
if(boot_params.user_params.val!=strlen(pPID->flags)) {
memset(boot_params.string, 0, sizeof(boot_params.string));
boot_params.user_params.val = 0;
}
} else {
//printf("Fail to find boot params! Use Default parameters.\n");
//don't printf anything before serial initialized!
}
return ret;
}
//保存在最后两个block,应确保程序(包括出现坏块时)不会覆盖到最后两块
int save_params(void)
{
U32 page, page_cnt;
U8 dat[0x20000];
int ret = 0;
InitNandFlash(1);
have_nandflash=1;
if(have_nandflash) {
memset(dat, 0, sizeof(boot_params));
memcpy(dat, &boot_params, sizeof(boot_params));
page = (NandPart[1].offset>>9)-64;
for(page_cnt=0; page_cnt<64; page_cnt++) {
if(!(page_cnt%32))
EraseBlock(page);
if(!WritePage(page+page_cnt, dat))
break;
}
if(page_cnt>=64)
ret = -1;
printf("Save boot params %s.\n", ret?"fail":"success");
} else {
}
DsNandFlash();
return ret;
}
int set_params(void)
{
int i, key, chg=0;
ParamItem *pPID;
printf("\nConfig parameters\n");
do {
pPID = &boot_params.start;
for(i=0; pPID<=&boot_params.user_params; pPID++, i++)
printf("[%d] : %s%-8s is 0x%08x (%d)\n",
i, (i>9)?"":" ", pPID->flags, pPID->val, pPID->val);
printf("[%d] : Exit\n", i);
if(boot_params.user_params.val)
printf("User parameters is : \"%s\"\n", boot_params.string);
printf("\nplease select item:");
key = Uart_GetIntNum();
if(key>=0&&key<i) {
chg = 1;
printf("please enter value:");
i = key;
if((&boot_params.start + i)==&boot_params.user_params) {
//确保输入的字节数不超过127!
char cmd[128];
memset(cmd, 0, sizeof(cmd));
Uart_GetString(cmd);
strncpy(boot_params.string, cmd, strlen(cmd)+1);
boot_params.user_params.val = strlen(cmd);
} else {
key = Uart_GetIntNum();
(&boot_params.start + i)->val = key;
}
} else
break;
} while(1);
if(chg) {
printf("Do you want to save parameters? press y or Y for save.\n");
key = getch();
if(key=='y'||key=='Y')
save_params();
}
return 0;
}
void LoadRunEboot(void)
{
const U32 EBOOT_NAND_ADDRESS = 0x30000; //Eboot在NAND Flash中的首地址
const U32 EBOOT_SDRAM_ADDRESS = 0x30038000; //Eboot拷贝到SDram中的地址
const U32 EBOOT_SIZE = (100 * 1024); //Eboot大小
U32 i, ram_addr, buf = EBOOT_SDRAM_ADDRESS;
int size;
if(rNFCONF & 0x00000008)
{
StartPage = EBOOT_NAND_ADDRESS >>12;
}
else
{
StartPage = EBOOT_NAND_ADDRESS >>9;
}
size = EBOOT_SIZE;
ram_addr = buf;
MemoryTest();
printf("Load Eboot...");
InitNandFlash(1);
for(i=0; size>0; ) {
if(!(i&0x1f)) {
if(CheckBadBlk(i+StartPage)) {
printf("Skipped bad block at 0x%x\n", i+StartPage);
i += 32;
//size -= 32<<9;
continue;
}
}
ReadPage((i+StartPage), (U8 *)ram_addr);
i++;
size -= 512;
ram_addr += 512;
}
DsNandFlash();
//跳转到eboot中去跑
printf("run at 0x%x",buf);
call_linux(0, 0, buf);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -