📄 nand.c
字号:
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();
//printf("goto_start...\n");
goto_start = (void (*)(U32, U32))a2;
(*goto_start)(a0, a1);
}
static int nand_boot;
static int have_nandflash;
int nand_config()
{
int ret;
U16 id;
nandif_t ni;
NF_Init();
id = NF_CheckId();
//printf("chip ID = %x\n",id);
if(id == K9F1208_ID)
{
//printf("k9f1208\n");
ni.cpage_size = 512;
ni.cpages_in_block = 32;
ni.cpage2Kis = 0;
ni.page_offset = 9;
ni.block_offset = 14;
have_nandflash =1;
NAND_PART = K9f1208_Part;
}
else if(id == K9F1G08_ID)
{
ni.cpage_size = 2048;
ni.cpages_in_block = 64;
ni.cpage2Kis = 1;
ni.page_offset = 11;
ni.block_offset = 17;
have_nandflash =1;
NAND_PART = K9f1g08_Part;
}
else
{
have_nandflash =0;
}
cpage2Kis = ni.cpage2Kis;
cpage_size = ni.cpage_size; /* Current Page Size */
cpages_in_block = ni.cpages_in_block;
coob_size = (ni.cpage_size/512)*16;
cblock_size = ni.cpage_size * ni.cpages_in_block;
page_offset = ni.page_offset;
block_offset =ni.block_offset;
#if 0
printf("cpage2Kis=%d\n",cpage2Kis);
printf("cpage_size=%d\n",cpage_size);
printf("cpages_in_block=%d\n",cpages_in_block);
printf("coob_size=%d\n",coob_size);
printf("cblock_size=%d\n",cblock_size);
printf("coob_size=%d\n",coob_size);
printf("page_offset=%d\n",page_offset);
printf("block_offset=%d\n",block_offset);
#endif
/*
GSTATUS4 = ((ni.cpage_size <<16) & 0xffff0000 ) |
((ni.cpages_in_block <<8)& 0xff00) |
((ni.cpage2Kis )& 0xff );
*/
}
void get_nandinfo(void)
{
//nandif_t ni;
//ni.cpage_size = (GSTATUS4>>16) & 0xffff;
//ni.cpage2Kis = (GSTATUS4) & 0xff;
//ni.cpages_in_block = (GSTATUS4>>8) & 0xff;
}
void check_nandflash(void)
{
}
void Nand_Detect()
{
int boot_mode;
boot_mode =rBWSCON;
if(!(boot_mode &0x6))
nand_boot =1; //boot_mode:nand flash
else
nand_boot =0;//boot from nor flash
nand_config();
get_nandinfo();
//Test_Write();
}
extern int sprintf(char * /*s*/, const char * /*format*/, ...);
static void LoadRun(void)
{
U32 i, block,ram_addr, buf = boot_params.run_addr.val;
struct param_struct *params = (struct param_struct *)0x30000100;
int size;
// int page;
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="ttyS0";
break;
case 1:
tty_sel="ttyS1";
break;
case 2:
tty_sel="tty1";
break;
case 3:
tty_sel="ttySAC0";
break;
case 4:
tty_sel="ttySAC1";
break;
default:
tty_sel=""; //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 {
block = NAND_PART[1].offset>>block_offset;
size = NAND_PART[1].size;
ram_addr = buf;
//page = NAND_PART[1].offset>>page_offset
//printf("block =%x,size =%x,ram_addr=%x\n",block,size,ram_addr);
s3c244x_nand_read(block,size,ram_addr);
}
#if 0
if(!boot_params.root_sel.val) {
int ramdisk_sz;
printf("Load Ramdisk...\n");
block = NAND_PART[2].offset>>block_offset;
size = NAND_PART[1].size;
ram_addr = boot_params.initrd_addr.val;
ramdisk_sz = boot_params.initrd_len.val;
printf("block =%x,size =%x,ram_addr=%x\n",block,size,ram_addr);
if(ramdisk_sz>0)
s3c244x_nand_read(block,size,ram_addr);
}
#endif
//NF_DIS();
//ChangeClockDivider(13,12);
//ChangeMPllValue(67,1,1); //300MHz,2440A!
//rCLKCON = 0x7fff0;
//printf("call_linux...\n");
call_linux(0, boot_params.machine.val, buf);
}
void NandErase(void)
{
int i, err = 0;
Nand_Detect();
//Test_Write();
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", StartBlock, BlockCnt);
while(1) {
char c;
c = getch();
if((c=='y')||(c=='Y'))
break;
if((c=='n')||(c=='N'))
return;
}
for(i=0; i<BlockCnt; i++) {
if(!NF_EraseBlock(StartBlock+i)) {
err ++;
puts("Press any key to continue...\n");
getch();
}
}
//NF_DIS(); //disable nand flash interface
puts("Erase Nand partition completed ");
if(err)
printf("with %d bad block(s)\n", err);
else
puts("success\n");
}
void NandWrite(void)
{
Nand_Detect();
if(!have_nandflash)
return;
WrFileToNF();
NF_DIS(); //disable nand flash interface
}
int RelocateNKBIN(U32 img_src, U32 *pStart, U32 *pLength, U32 *pLaunch);
static void LoadRunWince(void)
{
U32 ram_addr, buf = boot_params.initrd_addr.val;
int size;
printf("Load Kernel...\n");
if(boot_params.osstor.val) //load program from NOR or NAND FLASH
memcpy((void *)buf, (void *)(0x04000000+0x00020000), 0x00fe0000);
else {
StartBlock= NAND_PART[boot_params.start.val].offset>>block_offset; //part 2,3...
//size = boot_params.initrd_len.val;//NandPart[boot_params.root_sel.val].size;
size = NAND_PART[3].size;
//ram_addr = buf;
ram_addr = 0x30200000;
printf("start_block=%x,size=%x,ram_addr=%x\n",StartBlock,size,ram_addr);
s3c244x_nand_read(StartBlock,size,ram_addr);
}
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)
{
Nand_Detect();
//if(!nand_boot)
// return;
if(boot_params.start.val<2) //linux
LoadRun();
MemoryTest();
LoadRunWince();
}
#include "norflash.h"
#define NOR_PARAMS_OFFSET 0x1c000
int search_params(void)
{
U32 block;
U32 page, page_cnt;
U8 dat[0x20000];
BootParams *pBP = (BootParams *)dat;
int ret=-1;
Nand_Detect(); //don't show info in Nand_Detect!
if(nand_boot) {
block = (NAND_PART[1].offset>>block_offset)-1;
//page_cnt = NAND_PART[0].size>>page_offset;
//printf("block = %x\n",block);
//search from the last page
s3c244x_nand_read(block,cblock_size, (U32)dat);
if(!strncmp(boot_params.start.flags, pBP->start.flags, 10)) {
ret = 0;
}
} 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;
}
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 block;
U8 dat[0x20000];
int ret = 0;
Nand_Detect();
if(nand_boot) {
memset(dat, 0, sizeof(boot_params));
memcpy(dat, &boot_params, sizeof(boot_params));
block = (NAND_PART[1].offset>>block_offset)-1;
//printf("block = %x\n",block );
s3c244x_nand_write(block,cblock_size,(U32)dat);
printf("Save boot params success.\n");
} else {
//memcpy(dat, (void *)0x04000000, NOR_PARAMS_OFFSET);
memcpy(dat, &boot_params, sizeof(boot_params));
//ProgNorFlash(0, (U32)dat, sizeof(dat)); //28F128
SectorProg((NOR_PARAMS_OFFSET),(U16 *)dat,0x1000);
}
return ret;
}
int set_params(void)
{
int i, key, chg=0;
ParamItem *pPID;
int lcd_type;
char *string;
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!
printf("\n");
printf("1: display 240x320\n");
printf("2: display 320x240\n");
printf("3: display 480x272\n");
printf("4: display 640x480\n");
lcd_type = Uart_GetIntNum();
switch(lcd_type)
{
case 1:
string = "display=shp240";
strncpy(boot_params.string, string,strlen(string)+1);
strncpy(boot_params.string, string,strlen(string)+1);
break;
case 2:
string = "display=shp320";
strncpy(boot_params.string, string,strlen(string)+1);
boot_params.user_params.val = strlen(string);
break;
case 3:
string = "display=shp480";
strncpy(boot_params.string, string,strlen(string)+1);
boot_params.user_params.val = strlen(string);
break;
case 4:
string = "display=shp640";
strncpy(boot_params.string, string,strlen(string)+1);
boot_params.user_params.val = strlen(string);
break;
default:
break;
}
//strncpy(boot_params.string, cmd, strlen(cmd)+1);
//boot_params.user_params.val = strlen(string);
} 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 + -