📄 nand.c
字号:
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;
char *display_sel;
switch (boot_params.root_sel.val) {
case 0:
rootfs = "/dev/ram";
break;
case 1:
rootfs = "nfs";
break;
case 2:
rootfs = "/dev/mtdblock2"; // by pht.
break;
case 3:
rootfs = "/dev/mtdblock3";
break;
case 4:
rootfs = "/dev/mtdblock4";
break;
default:
rootfs=""; //user define
break;
}
switch (boot_params.display_sel.val) {
case 0:
display_sel = "display=sam320";
break;
case 1:
display_sel = "display=vga640";
break;
case 2:
display_sel = "display=tv640";
break;
default:
display_sel = "display=vga640";
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="ttyS0";
break;
case 3:
tty_sel="ttyS1";
break;
default:
tty_sel="ttySAC0"; //user define
break;
}
devfs_sel = "devfs=mount";
memset(parameters, 0, sizeof(parameters));
sprintf(parameters,
"root=%s init=/linuxrc %s console=%s,%d mem=%dK %s %s %s",
rootfs,
initrd,
tty_sel,
boot_params.serial_baud.val,
boot_params.mem_cfg.val>>10,
devfs_sel,
display_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[2].offset>>9;
size = NandPart[2].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[3].offset>>9;
size = NandPart[3].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 ++;
add_bpage(i+StartPage);
puts("Press any key to continue...\n");
getch();
}
}
DsNandFlash(); //disable nand flash interface
puts("Erase Nand partition completed ");
if(err)
{
save_params();
cpy_bpage();
printf("with %d bad block(s)\n", err);
}
else
puts("success\n");
}
void NandWrite(void)
{
InitNandFlash(1);
if(!have_nandflash)
return;
WrFileToNF();
DsNandFlash(); //disable nand flash interface
}
extern MemoryTest(void);
int RelocateNKBIN(U32 img_src, U32 *pStart, U32 *pLength, U32 *pLaunch);
static void LoadRunApp()
{
U32 i, ram_addr, buf = boot_params.initrd_addr.val;
int size;
MemoryTest();
printf("Load Application...\n");
StartPage = NandPart[1].offset>>9; //part 2,3...
size = NandPart[1].size;//NandPart[boot_params.root_sel.val].size;
ram_addr = boot_params.AppRun_addr.val;
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;
}
printf("run 0x%08x...\n",boot_params.AppRun_addr.val);
//RelocateNKBIN(buf, &buf, &i, &boot_params.run_addr.val);
call_linux(0, 0, boot_params.AppRun_addr.val);
}
static void LoadRunWince(void)
{
U32 i, ram_addr, buf = boot_params.initrd_addr.val;
int size;
MemoryTest();
printf("Load Kernel...\n");
StartPage = NandPart[5].offset>>9; //part 2,3...
size = boot_params.initrd_len.val;//NandPart[boot_params.root_sel.val].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;
}
printf("run 0x%08x...\n", boot_params.run_addr.val);
//RelocateNKBIN(buf, &buf, &i, &boot_params.run_addr.val);
call_linux(0, 0, boot_params.run_addr.val);
}
void NandLoadRun(void)
{
InitNandFlash(1);
LoadRun();
}
void NandLoadRun_wince(void)
{
InitNandFlash(1);
LoadRunWince();
}
void NandLoadRun_App()
{
InitNandFlash(1);
LoadRunApp();
}
void AutoNandLoadRun()
{
InitNandFlash(1);
switch(boot_params.start.val){
case 1:
LoadRunApp();
break;
case 2:
LoadRun();
break;
case 3:
LoadRunWince();
break;
default:
break;
}
}
#include "norflash.h"
#define NOR_PARAMS_OFFSET 0x1c000
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 {
memcpy(dat, (void *)(NOR_PARAMS_OFFSET), 512); //now mmu is not set, so use original address
if(!strncmp(boot_params.start.flags, pBP->start.flags, 10))
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;
}
memcpy(boot_params.bpage, (unsigned int*)pPIS->flags+32, 4);
if(boot_params.bpage[0]>20)//第一次烧写时可能不对,所以判断一下
{
boot_params.bpage[0]=0;
}
memcpy(boot_params.bpage, (unsigned int*)pPIS->flags+32, boot_params.bpage[0]*4+4);
} else {
//printf("Fail to find boot params! Use Default parameters.\n");
//don't printf anything before serial initialized!
}
cpy_bpage();
return ret;
}
void cpy_bpage()
{
if(boot_params.bpage[0]>20)
{
boot_params.bpage[0]=0;
}
memcpy((char *)BPAGE_MAGIC_ADD,bpage_magic,8);
memcpy((unsigned int *)BPAGE_ADD,boot_params.bpage,boot_params.bpage[0]*4+4);
}
//添加坏块信息
void add_bpage(unsigned int seq)
{
int i, j;
//printf("----------bpage %x-----\n",seq);
i = 1;
/*
//boot_params.bpage[1]=seq;
boot_params.bpage[1]=0x11111;
printf("----------bpage %x-----!!!\n",boot_params.bpage[1]);
*/
while (i < boot_params.bpage[0] && boot_params.bpage[i] < seq)
i++;
if (boot_params.bpage[i] == seq)
return;
else if (i == boot_params.bpage[0])
boot_params.bpage[i+1] = seq;
else
{
j = boot_params.bpage[0];
while (j >= i)
{
boot_params.bpage[j + 1] = boot_params.bpage[j];
j--;
}
boot_params.bpage[i] = seq;
}
boot_params.bpage[0]++;
}
//保存在最后两个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 {
memcpy(dat, (void *)0x04000000, NOR_PARAMS_OFFSET);
memcpy(dat+NOR_PARAMS_OFFSET, &boot_params, sizeof(boot_params));
ProgNorFlash(0, (U32)dat, sizeof(dat)); //28F128
}
DsNandFlash();
return ret;
}
int set_params(void)
{
int i, key, chg=0;
ParamItem *pPID;
printf(" +------------------------------------------------------------+\n");
printf(" | Config parameters |\n");
printf(" +------------------------------------------------------------+\n");
//printf("\n#####Config parameters#####\n");
do {
pPID = &boot_params.start;
for(i=0; pPID<=&boot_params.user_params; pPID++, i++)
printf(" [%2d] %-10s : 0x%08x (%d)\n",
i, pPID->flags, pPID->val, pPID->val);
printf(" [%2d] : 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;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -