📄 nand.c
字号:
// SEccUnlock();
/*
printf("ecc2:");
for(i=0;i<8;i++)
printf("0x%x ",tmp[i]);
printf("\n");
*/
for(i=0;i<8;i++)
WrNFDat(tmp[i]);
// SEccLock();
}
WrNFCmd(PROGCMD1);
stat = WaitNFBusy();
NFChipDs();
#ifdef WR_BAD_BLK_TEST
if((addr&0xff)==0x17) stat = 1; //just for test bad block
#endif
if(stat)
printf("Write nand flash 0x%x fail\n", addr);
else {
U8 RdDat[512];
ReadPage(addr, RdDat);
for(i=0; i<512; i++)
if(RdDat[i]!=buf[i]) {
printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
stat = 1;
break;
}
}
return stat;
}
static void MarkBadBlk(U32 addr)
{
addr &= ~0x1f;
NFChipEn();
WrNFCmd(READCMD2); //point to area c
WrNFCmd(PROGCMD0);
WrNFAddr(4); //mark offset 4,5,6,7
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
WrNFDat(0); //mark with 0
WrNFDat(0);
WrNFDat(0); //mark with 0
WrNFDat(0);
WrNFCmd(PROGCMD1);
WaitNFBusy(); //needn't check return status
WrNFCmd(READCMD0); //point to area a
NFChipDs();
}
static int CheckBadBlk(U32 addr)
{
U8 dat;
addr &= ~0x1f;
NFChipEn();
WrNFCmd(READCMD2); //point to area c
WrNFAddr(5); //mark offset 4,5,6,7
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
WaitNFBusy();
dat = RdNFDat();
WrNFCmd(READCMD0); //point to area a
NFChipDs();
return (dat!=0xff);
}
/************************************************************/
// Nand Flash 的分区
struct Partition{
U32 offset;
U32 size;
char *name;
};
// Nand Flash 的分区设置
static struct Partition NandPart[] = {
{0, 0x00040000, "ATBOOT"}, // 256 K
{0x00040000, 0x02300000, "WINCE "}, // 35 M
{0x02340000, 0x01cc0000, "USER"}, // 28.75 M
{0, 0 , 0}
};
static U32 StartPage, BlockCnt;
extern U32 downloadAddress;
extern U32 downloadFileSize;
extern int sel_part;
extern int auto_nk;
static int NandSelPart(char *info)
{
U16 i, max_sel;
struct Partition *ptr = NandPart;
printf("Please select which region to %s : Esc to abort\n", info);
for(i=0; ptr->size!=0; i++, ptr++)
printf("%d : offset 0x%-8x, size 0x%-8x [%s]\n", i, ptr->offset, ptr->size, ptr->name);
max_sel = i;
while(1) {
i = getch();
if(i==0x1b)
return -1;
if((i>='0')&&(i<(max_sel+'0'))) {
i -= '0';
StartPage = NandPart[i].offset>>9;
BlockCnt = NandPart[i].size>>14;
return i;
}
}
}
static void WrFileToNF(void)
{
S32 nf_part, i ,size, skip_blks;
U32 ram_addr;
if(auto_nk==1)
nf_part = sel_part;
else
nf_part = NandSelPart("write");
if(nf_part<0)
return;
if(downloadFileSize>NandPart[nf_part].size) {
puts("Download file size is more large than selected partition size!!!\n");
return;
}
printf("Now write nand flash page 0x%x from ram address 0x%x, filesize = %d\n", StartPage, downloadAddress, downloadFileSize);
skip_blks = 0;
ram_addr = downloadAddress;
size = downloadFileSize;
for(i=0; size>0; ) {
if(!(i&0x1f)) {
if(EraseBlock(i+StartPage)) {
NandPart[nf_part].size -= 32<<9; //partition available size - 1 block size
if(downloadFileSize>NandPart[nf_part].size) {
puts("Program nand flash fail\n");
return;
}
MarkBadBlk(i+StartPage);
skip_blks++;
i += 32;
continue;
}
}
if(WritePage(i+StartPage, (U8 *)ram_addr)) {
ram_addr -= (i&0x1f)<<9;
size += (i&0x1f)<<9;
i &= ~0x1f;
NandPart[nf_part].size -= 32<<9; //partition available size - 1 block size
if(downloadFileSize>NandPart[nf_part].size) {
puts("Program nand flash fail\n");
return;
}
MarkBadBlk(i+StartPage);
skip_blks++;
i += 32;
continue;
}
ram_addr += 512;
size -= 512;
i++;
}
puts("Program nand flash partition success\n");
if(skip_blks)
printf("Skiped %d bad block(s)\n", skip_blks);
}
#define LINUX_PAGE_SHIFT 12
#define LINUX_PAGE_SIZE (1<<LINUX_PAGE_SHIFT)
#define COMMAND_LINE_SIZE 1024
struct param_struct {
union {
struct {
unsigned long page_size; /* 0 */
unsigned long nr_pages; /* 4 */
unsigned long ramdisk_size; /* 8 */
unsigned long flags; /* 12 */
#define FLAG_READONLY 1
#define FLAG_RDLOAD 4
#define FLAG_RDPROMPT 8
unsigned long rootdev; /* 16 */
unsigned long video_num_cols; /* 20 */
unsigned long video_num_rows; /* 24 */
unsigned long video_x; /* 28 */
unsigned long video_y; /* 32 */
unsigned long memc_control_reg; /* 36 */
unsigned char sounddefault; /* 40 */
unsigned char adfsdrives; /* 41 */
unsigned char bytes_per_char_h; /* 42 */
unsigned char bytes_per_char_v; /* 43 */
unsigned long pages_in_bank[4]; /* 44 */
unsigned long pages_in_vram; /* 60 */
unsigned long initrd_start; /* 64 */
unsigned long initrd_size; /* 68 */
unsigned long rd_start; /* 72 */
unsigned long system_rev; /* 76 */
unsigned long system_serial_low; /* 80 */
unsigned long system_serial_high; /* 84 */
unsigned long mem_fclk_21285; /* 88 */
} s;
char unused[256];
} u1;
union {
char paths[8][128];
struct {
unsigned long magic;
char n[1024 - sizeof(unsigned long)];
} s;
} u2;
char commandline[COMMAND_LINE_SIZE];
};
extern void call_os(U32 a0, U32 a1, U32 a2);
/*************************************************************/
static __inline void cpu_arm920_cache_clean_invalidate_all(void)
{
__asm{
mov r1, #0
mov r1, #7 << 5 /* 8 segments */
cache_clean_loop1:
orr r3, r1, #63UL << 26 /* 64 entries */
cache_clean_loop2:
mcr p15, 0, r3, c7, c14, 2 /* clean & invalidate D index */
subs r3, r3, #1 << 26
bcs cache_clean_loop2 /* entries 64 to 0 */
subs r1, r1, #1 << 5
bcs cache_clean_loop1 /* segments 7 to 0 */
mcr p15, 0, r1, c7, c5, 0 /* invalidate I cache */
mcr p15, 0, r1, c7, c10, 4 /* drain WB */
}
}
void cache_clean_invalidate(void)
{
cpu_arm920_cache_clean_invalidate_all();
}
static __inline void cpu_arm920_tlb_invalidate_all(void)
{
__asm{
mov r0, #0
mcr p15, 0, r0, c7, c10, 4 /* drain WB */
mcr p15, 0, r0, c8, c7, 0 /* invalidate I & D TLBs */
}
}
void tlb_invalidate(void)
{
cpu_arm920_tlb_invalidate_all();
}
// 启动应用程序
// 包括linux 和 WinCE
//
void call_os(U32 a0, U32 a1, U32 a2)
{
void (*goto_start)(U32, U32);
rINTMSK=BIT_ALLMSK;
cache_clean_invalidate();
tlb_invalidate();
__asm{
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 */
}
goto_start = (void (*)(U32, U32))a2;
(*goto_start)(a0, a1);
}
extern int sprintf(char * /*s*/, const char * /*format*/, ...);
#define ATAG_NONE 0x00000000
#define ATAG_CORE 0x54410001
#define ATAG_RAMDISK 0x54410004
#define ATAG_CMDLINE 0x54410009
struct tag_core {
U32 flags; /* bit 0 = read-only */
U32 pagesize;
U32 rootdev;
};
struct tag_header {
U32 size;
U32 tag;
};
struct tag_mem32 {
U32 size;
U32 start; /* physical start address */
};
struct tag_videotext {
U8 x;
U8 y;
U16 video_page;
U8 video_mode;
U8 video_cols;
U16 video_ega_bx;
U8 video_lines;
U8 video_isvga;
U16 video_points;
};
struct tag_ramdisk {
U32 flags; /* bit 0 = load, bit 1 = prompt */
U32 size; /* decompressed ramdisk size in _kilo_ bytes */
U32 start; /* starting block of floppy-based RAM disk image */
};
struct tag_initrd {
U32 start; /* physical start address */
U32 size; /* size of compressed ramdisk image in bytes */
};
struct tag_serialnr {
U32 low;
U32 high;
};
struct tag_revision {
U32 rev;
};
struct tag_videolfb {
U16 lfb_width;
U16 lfb_height;
U16 lfb_depth;
U16 lfb_linelength;
U32 lfb_base;
U32 lfb_size;
U8 red_size;
U8 red_pos;
U8 green_size;
U8 green_pos;
U8 blue_size;
U8 blue_pos;
U8 rsvd_size;
U8 rsvd_pos;
};
struct tag_cmdline {
char cmdline[1]; /* this is the minimum size */
};
struct tag_acorn {
U32 memc_control_reg;
U32 vram_pages;
U8 sounddefault;
U8 adfsdrives;
};
struct tag_memclk {
U32 fmemclk;
};
struct tag {
struct tag_header hdr;
union {
struct tag_core core;
struct tag_mem32 mem;
struct tag_videotext videotext;
struct tag_ramdisk ramdisk;
struct tag_initrd initrd;
struct tag_serialnr serialnr;
struct tag_revision revision;
struct tag_videolfb videolfb;
struct tag_cmdline cmdline;
/*
* Acorn specific
*/
struct tag_acorn acorn;
/*
* DC21285 specific
*/
struct tag_memclk memclk;
} u;
};
#define tag_next(t) ((struct tag *)((U32 *)(t) + (t)->hdr.size))
#define tag_size(type) ((sizeof(struct tag_header) + sizeof(struct type)) >> 2)
static void SetTAG(void){
struct tag *params = (struct tag *)0x30000100;
char *linux_cmd;
char *p;
memset(params, 0, sizeof(struct tag));
/* step1: setup start tag */
params->hdr.tag = ATAG_CORE;
params->hdr.size = tag_size(tag_core);
params->u.core.flags = 0;
params->u.core.pagesize = LINUX_PAGE_SIZE;
params->u.core.rootdev = 0;
params = tag_next(params);
/* step2: setup commandline tag */
// linux_cmd = get_linux_cmd_line();
linux_cmd = "root=/dev/mtdblock1 rw rootfstype=jffs2 noinitrd init=/linuxrc console=ttySAC1,115200 mem=64M\0";
if (linux_cmd == NULL) {
printf("Wrong magic; could not find linux command line\n");
} else {
/* eat leading white space */
for (p=linux_cmd; *p==' '; p++) {
;
}
/* setup cmdline tag magic number */
params->hdr.tag = ATAG_CMDLINE;
/* please notice that size counts by word. */
params->hdr.size = (sizeof(struct tag_header) + strlen(linux_cmd) + 1 + 4) >> 2;
memcpy(params->u.cmdline.cmdline, linux_cmd, strlen(linux_cmd)+1);
params = tag_next(params);
printf("linux command line is: \"%s\"\n", linux_cmd);
}
/* step3: setup end tag */
params->hdr.tag = ATAG_NONE;
params->hdr.size = 0;
/* help info that tagged list setups up completely */
printf("Tagged list setups up successfully\n");
}
static void LoadRun(void)
{
U32 i, ram_addr, buf = boot_params.run_addr.val;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -