You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

740 lines
21 KiB

#include<pmon.h>
#include<asm.h>
#include<machine/types.h>
#include<linux/mtd/mtd.h>
#include<linux/mtd/nand.h>
#include<linux/mtd/partitions.h>
#include<sys/malloc.h>
#define MYDBG
//printf("%s:%x\n",__func__,__LINE__);
#define _WL(x,y) (*((volatile unsigned int*)(x)) = (y))
#define _RL(x,y) ((y) = *((volatile unsigned int*)(x)))
#define NAND_WL(x,y) _WL((x) + NAND_BASE,(y))
#define NAND_RL(x,y) _RL((x) + NAND_BASE,(y))
#define DMA_WL(x,y) _WL((x) + DMA_DESP,(y))
#define DMA_RL(x,y) _RL((x) + DMA_DESP,(y))
#define RAM_ADDR 0x84100000
#define DMA_DESP 0x84001000
#define NAND_TMP 0x84800000
#define BLOCK_TO_PAGE(x) ((x)<<6)
#define PAGE_TO_BLOCK(x) ((x)>>6)
#define PAGE_TO_FLASH(x) ((x)<<11)
#define PAGE_TO_FLASH_H(x) ((x)>>21)
#define PAGE_TO_FLASH_S(x) ((x)<<12)
#define PAGE_TO_FLASH_H_S(x) ((x)>>20)
#define FLASH_TO_PAGE(x) ((x)>>11)
#ifdef SOC
#define VT_TO_PHY(x) ((x) & 0x0fffffff)
#else
#define VT_TO_PHY(x) ((x) & 0x0fffffff | 0x80000000)
#endif
#define PAGES_A_BLOCK 0x40
#define NAND_BASE 0xbbee0000
#define NAND_DMA 0x1bee0040
#define CMD 0x0
#define ADDRL 0x4
#define ADDRH 0x8
#define TIMING 0xc
#define IDL 0x10
#define IDH 0x14
#define PARAM 0x18
#define OPNUM 0x1c
#define CS_RDY_MAP 0x20
#define DMA_ACCESS_ADDR 0x40
#define DMA_ORDER 0x0
#define DMA_SADDR 0x4
#define DMA_DEV 0x8
#define DMA_LEN 0xc
#define DMA_SET_LEN 0x10
#define DMA_TIMES 0x14
#define DMA_CMD 0x18
#define ORDER_REG 0xbbd00100
#define STOP_DMA (_WL(0xbbd00100,0x10))
#define START_DMA(x) do{ _WL(0xbbd00100,(VT_TO_PHY(x)|0x8));}while(0)
#define ASK_DMA(x) (_WL(0xbbd00100,(VT_TO_PHY(x)|0x4)))
#define en_count(tmp) do{asm volatile("mfc0 %0,$23;li $2,0x2000000;or $2,%0;mtc0 $2,$23;":"=r"(tmp)::"$2"); }while(0)
#define dis_count(tmp) do{asm volatile("mtc0 %0,$23;"::"r"(tmp)); }while(0)
//#define SET_GPIO0_OUT(x) do{x=(x==0?0:1);x=(*((volatile unsigned int*)0xbfd010f0) & ~0x1)|x; _WL(0xbfd010f0,(x));}while(0)
//#define SET_GPIO1_IN(x) ((*((volatile unsigned int*)0xbfd010e0) & 0x2)>>1)
#if 0
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
#endif
int is_bad_block(u32 block);
int erase_block(u32 block);
int read_pages(u32 ram,u32 page,u32 pages,u8 flag);//flag:0==main 1==spare 2==main+spare
int write_pages(u32 ram,u32 page,u32 pages,u8 flag);//flag:0==main 1==spare 2==main+spare
int read_nand(u32 ram,u32 flash, u32 len,u8 flag);
int write_nand(u32 ram,u32 flash,u32 len,u8 flag);
int erase_nand(u32 start,u32 blocks);
int chipsize = 0x08000000;
void nand_udelay(unsigned int us)
{
int tmp=0;
// en_count(tmp);
udelay(us);
// dis_count(tmp);
}
static void nand_send_cmd(u32 cmd, u32 page)//Send addr and cmd
{
//#define CMD 0x0
NAND_WL(CMD, 0);
NAND_WL(CMD, 0x40); // reset nand
//操作发生在NAND的SPARE区
if(cmd & (0x1<<9)){
//操作发生在NAND的MAIN区
if(cmd &(0x1<<8)){
//#define PAGE_TO_FLASH_S(x) ((x)<<12)
//NAND_WL(ADDRL, PAGE_TO_FLASH_S(page));
//NAND_WL(ADDRL, 0x800); //起始地址在2K处 备用区
NAND_WL(ADDRL, 0x000); //起始地址在2K处 备用区
}else{
//NAND_WL(ADDRL, PAGE_TO_FLASH_S(page)+0x800); //起始地址在2K处 备用区
NAND_WL(ADDRL, 0x800); //起始地址在2K处 备用区
}
// NAND_WL(ADDRH,PAGE_TO_FLASH_H_S(page));
}else{
//#define PAGE_TO_FLASH(x) ((x)<<11) 2K
//NAND_WL(ADDRL, PAGE_TO_FLASH(page));
NAND_WL(ADDRL, 0);
// NAND_WL(ADDRH, PAGE_TO_FLASH_H_S(page));
}
NAND_WL(ADDRH, page);
{
int val=0;
// printf("flashaddr==0x%08x,cmd==%d\n",NAND_RL(ADDRL,val),cmd);
}
//printf("flashaddr page = %08x, cmd==%04x\n",page, cmd);
NAND_WL(CMD, cmd & (~0xff));
NAND_WL(CMD, cmd);
}
#if 0
void gpio_init(void)
{
_WL(0xbfd010c0,0x3);//enable gpio0 and gpio1
_WL(0xbfd010d0,0x2);//gpio0 output,gpio1 intput
}
#endif
static u8 rdy_status(void)
{
//外部NAND芯片RDY情况
//return ((*((u32*) (NAND_BASE+CMD)) & (0x1<<16)) == 0 ? 0:1);
return ((*((u32*) (NAND_BASE+CMD)) & (0x1<<10)) == 0 ? 0:1);
}
static u8 nand_op_ok(u32 len, u32 ram)
{
u32 ask=0, dmalen=0, dmastatus=0;
while(!rdy_status())
nand_udelay(20);
return 0;
while(1){
ASK_DMA(DMA_DESP); //用户请求将当前DMA操作的相关信息写回到指定的内存地址
_RL(DMA_DESP+0x4, ask); //DMA操作的内存地址
_RL(DMA_DESP+0xc, dmalen);
_RL(DMA_DESP+0x18, dmastatus);
// printf("ask ==0x%08x,damlen==0x%08x,dmastatus==0x%08x\n",ask,dmalen,dmastatus);
// printf("ask should==0x%08x,len==0x%08x\n", (VT_TO_PHY(ram)+((len+3)/4)*4),len);
//判断读取的值是否是写入的值
if(ask == (VT_TO_PHY(ram)+((len+3)/4)*4)){break;}else{return 0;} //THF
nand_udelay(60);
}
while(!rdy_status())
nand_udelay(20);
return 0;
}
static void dma_config(u32 len,u32 ddr,u32 cmd)
{
MYDBG
DMA_WL(DMA_ORDER, 0); //下一个描述符地址寄存器 这里设置为无效
MYDBG
DMA_WL(DMA_SADDR, VT_TO_PHY(ddr)); //内存地址寄存器
MYDBG
DMA_WL(DMA_DEV, NAND_DMA); //设备地址寄存器 Loongson 1B的NAND Flash DMA存取地址
MYDBG
DMA_WL(DMA_LEN, (len+3)/4); //长度寄存器 代表一块被搬运内容的长度,单位是字 由于从NAND Flash读取回的数据以字节为单位 所以除以4 加3是?
MYDBG
DMA_WL(DMA_SET_LEN, 0); //间隔长度寄存器 间隔长度说明两块被搬运内存数据块之间的长度,前一个step的结束地址与后一个step的开始地址之间的间隔
MYDBG
DMA_WL(DMA_TIMES, 1); //循环次数寄存器 循环次数说明在一次DMA操作中需要搬运的块的数目
MYDBG
DMA_WL(DMA_CMD, cmd); //控制寄存器
MYDBG
}
int is_bad_block(u32 block)
{
u32 page=0;
//#define BLOCK_TO_PAGE(x) ((x)<<6)
page = BLOCK_TO_PAGE(block); //Bloac 对应的页起始地址? 以64页为1个Block
read_pages(RAM_ADDR, page, 1, 1); //最后的1代表读取64B备用区
if(*((u8*) RAM_ADDR) != 0xff){
printf(" *((u8*) RAM_ADDR) = %08x\n", *((u8*) RAM_ADDR));
return 1;
} //判断是否为坏块 参考nand flash数据手册
//if(*((u8*) RAM_ADDR) != 0xff){return 0;} //判断是否为坏块 参考nand flash数据手册
return 0;
}
int erase_block(u32 block)
{
u32 flash_l=0,flash_h=0;
//NAND_WL(TIMING, 0x206); //NAND命令有效需等待的周期数 NAND一次读写所需总时钟周期数
NAND_WL(OPNUM, 0x1); //NAND读写操作Byte数;擦除为块数
// printf("block==0x%08x\n",block);
nand_send_cmd(0x9, BLOCK_TO_PAGE(block));
MYDBG
nand_udelay(50);
MYDBG
while(!rdy_status())
nand_udelay(30);
return 0;
}
//flag:0==main 1==spare 2==main+spare
int read_pages(u32 ram, u32 page, u32 pages, u8 flag)
{
u32 len=0,dma_cmd=0,nand_cmd=0;
u32 ret = 0,tmp;
switch(flag){
case 0:
len = pages * 0x800; //2K(K9F1G08U0C)
nand_cmd = 0x103; //操作发生在NAND的MAIN区+读操作+命令有效
break;
case 1:
len = pages * 0x40; //64B
nand_cmd = 0x203; //操作发生在NAND的SPARE区+读操作+命令有效
break;
case 2:
len = pages * 0x840; //2K + 64B
nand_cmd = 0x303; //操作发生在NAND的SPARE区+操作发生在NAND的MAIN区+读操作+命令有效
break;
default:
len = 0;
nand_cmd = 0;
break;
}
MYDBG
dma_config(len, ram, dma_cmd); //配置DMA
MYDBG
//#define STOP_DMA (_WL(0xbbd00100,0x10))
STOP_DMA; //用户请求停止DMA操作
MYDBG
nand_udelay(5);
MYDBG
//#define START_DMA(x) do{ _WL(0xbbd00100,(VT_TO_PHY(x)|0x8));}while(0)
START_DMA(DMA_DESP);
// printf("0xbfd001160===0x%08x\n",*(volatile unsigned int *)(0xbbd00100));
NAND_WL(TIMING, 0x40c); //NAND命令有效需等待的周期数 NAND一次读写所需总时钟周期数
NAND_WL(OPNUM, len); //NAND读写操作Byte数;擦除为块数
nand_send_cmd(nand_cmd, page);
nand_udelay(20000);
MYDBG
ret = nand_op_ok(len, ram);
// nand_udelay(100);
MYDBG
if(ret){
printf("nandread 0x%08x page 0x%08x pages have some error\n",page,pages);
}
return ret;
}
#if 0
int write_pages(u32 ram,u32 page,u32 pages,u8 flag)
{
u32 len=0,dma_cmd=0x1000,nand_cmd=0;
u32 ret=0;
switch(flag){
case 0:
len = pages * 0x800;
nand_cmd = 0x105;
break;
case 1:
len = pages * 0x40;
nand_cmd = 0x205;
break;
case 2:
len = pages * 0x840;
nand_cmd = 0x305;
break;
default:
len = 0;
nand_cmd = 0;
break;
}
printf("len==0x%08x,pages==0x%08x\n",len,pages);
dma_config(len,ram,dma_cmd);
STOP_DMA;
nand_udelay(10);
START_DMA(DMA_DESP);
NAND_WL(TIMING,0x412);
NAND_WL(OPNUM,len);
nand_send_cmd(nand_cmd,page);
nand_udelay(1000);
MYDBG;
ret = nand_op_ok(len,ram);
MYDBG;
if(ret){
printf("nandwrite 0x%08x page 0x%08x pages have some error\n",page,pages);
}
return ret;
}
#endif
int write_pages(u32 ram,u32 page,u32 pages,u8 flag)
{
u32 len=0,dma_cmd=0x1000,nand_cmd=0;
u32 ret=0,step=1;
int val=pages;
#if 1
switch(flag){
case 0: /* main */
len = step*0x800;
nand_cmd = 0x105;
break;
case 1: /* spare */
len = step*0x40;
nand_cmd = 0x205;
break;
case 2: /* main + spare */
len = step*0x840;
nand_cmd = 0x305;
break;
default:
len = 0;
nand_cmd = 0;
break;
}
#endif
for(; val>0; val-=step){
// printf("len==0x%08x,pages==0x%08x\n",len,val);
dma_config(len,ram,dma_cmd);
STOP_DMA;
nand_udelay(10);
START_DMA(DMA_DESP);
// NAND_WL(TIMING,0x40c);
NAND_WL(OPNUM,len);
nand_send_cmd(nand_cmd,page);
nand_udelay(300);
ret = nand_op_ok(len,ram);
ram += len;
page += step;
MYDBG;
if(ret){
printf("nandwrite 0x%08x page 0x%08x pages have some error\n",page,pages);
}
}
return ret;
}
//检查输入的参数是否在可处理的范围内
int error_check(u32 ram, u32 flash, u32 len)
{
if(FLASH_TO_PAGE(flash) >= 0xffffffff){
printf("the FLASH addr is big,this program don't work on this FLASH addr...\n");
return -1;
}
if(flash & 0x7ff){
printf("the FLASH addr don't align/* Need 0x800B alignment*/\n"); //以2K(K9F1G08U0C)为1页
return -1;
}
if(ram & 0x1f){
printf("the RAM addr 0x%08x don't align/* Need 32B alignment*/\n",ram);
return -1;
}
if(len < 0 || len > chipsize){
printf("the LEN 0x%08x(%d) is a unvalid number\n",len,len);
return -1;
}
return 0;
}
int read_nand(u32 ram,u32 flash,u32 len,u8 flag)
{
u32 page = 0;
u32 ret = 0;
u32 b_pages = 0,a_pages = 0;
u32 pages = 0, block = 0, chunkblock = 0, chunkpage = 0;
int badblock_count=0; //lxy
ret = error_check(ram, flash, len); //检查输入的参数是否在可处理的范围内
if(ret)
return ret;
//#define FLASH_TO_PAGE(x) ((x)>>11)
//把输入的flash地址转换为页地址 这里页大小为2K 如果换用不同的Flash会如何?
page = FLASH_TO_PAGE(flash);//start page
// printf("%x:page==0x%08x\n",__LINE__,page);
while(is_bad_block(PAGE_TO_BLOCK(page))){
// printf("%x:page==0x%08x\n",__LINE__,page);
// printf("%x:block==0x%08x\n",__LINE__,PAGE_TO_BLOCK(page));
// printf("block==%x,page==%x\n",PAGE_TO_BLOCK(page),page);
// MYDBG;
//#define PAGES_A_BLOCK 0x40
page += PAGES_A_BLOCK; //页大小(2K)+ 64B (K9F1G08U0C)
badblock_count++;
//#define BLOCK_TO_PAGE(x) ((x)<<6)
//#define PAGE_TO_BLOCK(x) ((x)>>6)
page = (BLOCK_TO_PAGE(PAGE_TO_BLOCK(page))); //64页 组成1个Block 擦除以Block为单位
// printf("%x:page==0x%08x\n",__LINE__,page);
printf("the FLASH addr 0x%08x is a bad block,auto change FLASH addr 0x%08x\n", flash, PAGE_TO_FLASH(page));
}
switch(flag){
case 0:
chunkblock = 0x20000; //128K
chunkpage = 0x800;
break;
case 1:
chunkblock = 0x1000; //4K
chunkpage = 0x40;
break;
case 2:
chunkblock = 0x21000; //128K+4K
chunkpage = 0x840;
break;
default:
chunkblock = 0;
chunkpage = 0;
break;
}
// printf("reading ");
pages = (len + chunkpage - 1)/chunkpage;
// printf("%x:pages==0x%08x\n",__LINE__,pages);
b_pages = page % PAGES_A_BLOCK; //每Block的Page数 余数为0
b_pages = (PAGES_A_BLOCK - b_pages);
// printf("%x:pages==0x%08x b_pages=%x\n", __LINE__, pages, b_pages);
if(pages > b_pages && b_pages > 0){
ret = read_pages(ram, page, b_pages, flag);
pages -= b_pages;
page += b_pages;
ram += (chunkpage * b_pages);
}else if(pages <= b_pages && b_pages > 0){
ret = read_pages(ram, page, pages, flag);
pages = 0;
}
if(ret){return ret;}
if(pages){
block = pages / PAGES_A_BLOCK;
a_pages = pages % PAGES_A_BLOCK;
}
for(;block > 0;block--){
while(is_bad_block(PAGE_TO_BLOCK(page))){
printf("the FLASH addr 0x%08x is bad block,try next block...\n",PAGE_TO_FLASH(page));
page += PAGES_A_BLOCK;
}
ret = read_pages(ram, page, PAGES_A_BLOCK, flag);
// printf(". ");
if(ret) {return ret;}
pages -= PAGES_A_BLOCK;
page += PAGES_A_BLOCK ;
ram += chunkblock;
}
if(a_pages){
while(is_bad_block(PAGE_TO_BLOCK(page))){
printf("the FLASH addr 0x%08x is bad block,try next block...\n",PAGE_TO_FLASH(page));
page += PAGES_A_BLOCK;
}
ret = read_pages(ram,page,a_pages,flag);
if(ret){return ret;}
}
// printf("... done\n");
/*
{
int i;
unsigned char *temp = (unsigned char *)ram;
for (i=0; i<256; i++)
{
if((i%16) == 0)
printf("\n");
// printf("%x ", *(unsigned int *)(ram+(i*4)));
printf("%02x ", *(temp+i));
}
printf("\n");
}
*/
// return ret;
return badblock_count;
}
int write_nand(u32 ram, u32 flash, u32 len, u8 flag)
{
u32 page=0,start_page=0;
u32 ret = 0;
u32 b_pages = 0,a_pages=0;
u32 pages = 0,block=0,chunkblock=0,chunkpage=0;
int badblock_count=0; //lxy
ret = error_check(ram,flash,len); //检查输入的参数是否在可处理的范围内
if(ret)
return ret;
//#define FLASH_TO_PAGE(x) ((x)>>11)
//把输入的flash地址转换为页地址 这里页大小为2K 如果换用不同的Flash会如何?
page = FLASH_TO_PAGE(flash);//start page
//检查该页是否为坏块
while(is_bad_block(PAGE_TO_BLOCK(page))){
page += PAGES_A_BLOCK;
badblock_count++;
page = (BLOCK_TO_PAGE(PAGE_TO_BLOCK(page)));
printf("the FLASH addr 0x%08x is a bad block,auto change FLASH addr 0x%08x\n", flash, PAGE_TO_FLASH(page));
}
switch(flag){
case 0:
chunkblock = 0x20000;
chunkpage = 0x800;
break;
case 1:
chunkblock = 0x1000;
chunkpage = 0x40;
break;
case 2:
chunkblock = 0x21000;
chunkpage = 0x840;
break;
default:
chunkblock = 0;
chunkpage = 0;
break;
}
// printf("writing. ");
pages = (len + chunkpage - 1)/chunkpage; // pages total
// printf("%x:pages==0x%08x\n",__LINE__,pages);
start_page = page % PAGES_A_BLOCK; //页在块中的相对起始地址
if(start_page){ // page index in a block
b_pages = (PAGES_A_BLOCK - start_page);
}
if(b_pages > 0){
//读取需要写入的页在对应块中的该块的数据,暂存
ret = read_pages(NAND_TMP, page - start_page, start_page, 2); //page - start_page = 以块为单位块中的第一个页地址
if(ret){return ret;}
erase_block(PAGE_TO_BLOCK(page));//擦除该块
ret = write_pages(NAND_TMP, page - start_page, start_page, 2);
// printf(". ");
if(ret){return ret;}
}
if(pages > b_pages && b_pages > 0){
ret = write_pages(ram, page, b_pages, flag);
pages -= b_pages;
page += b_pages;
ram += (chunkpage * b_pages);
}else if(pages <= b_pages && b_pages > 0){
ret = write_pages(ram,page,pages,flag);
pages = 0;
}
if(ret){return ret;}
if(pages){
block = pages / PAGES_A_BLOCK;
a_pages = pages % PAGES_A_BLOCK;
}
// printf("block==0x%08x,a_pages==0x%08x\n",block,a_pages);
for(;block > 0;block--){
MYDBG
erase_block(PAGE_TO_BLOCK(page));
while(is_bad_block(PAGE_TO_BLOCK(page))){
printf("the FLASH addr 0x%08x is bad block,try next block...\n",PAGE_TO_FLASH(page));
page += PAGES_A_BLOCK;
erase_block(PAGE_TO_BLOCK(page));
}
MYDBG
ret = write_pages(ram,page,PAGES_A_BLOCK,flag);
MYDBG
// printf(". ");
if(ret) {return ret;}
pages -= PAGES_A_BLOCK;
page += PAGES_A_BLOCK;
ram += chunkblock;
}
MYDBG
if(a_pages){
erase_block(page);
while(is_bad_block(PAGE_TO_BLOCK(page))){
printf("the FLASH addr 0x%08x is bad block,try next block...\n",PAGE_TO_FLASH(page));
page += PAGES_A_BLOCK;
erase_block(PAGE_TO_BLOCK(page));
}
ret = write_pages(ram,page,a_pages,flag);
if(ret){return ret;}
}
// printf("... done\n");
// return ret;
return badblock_count;
}
int erase_nand(u32 start,u32 blocks)
{
int i = 0;
// printf("erasing ");
for(; i<blocks; i++){
erase_block(i+start);
// printf(". ");
}
// printf(" done\n");
MYDBG
return 0;
}
#if 1
//int mymain_nand(u8 ops,u32 ram,u32 flash,u32 len,u8 flag)
int mymain_nand(int argc,char **argv)
{
u8 ops = 0, flag = 0;
u32 ram = 0, flash = 0;
u32 len = 0;
printf("\n\t\t*****Nand Flash OPS*****\n\n");
{
printf("Uargs:callbin ./bin/nand_ops.bin OPS startblock blocks\n");
printf("Uargs:callbin ./bin/nand_ops.bin OPS ram flashaddr len flag\n");
printf("Uargs:flag: 0=main; 1=spare; 2=spare+main\n\n");
printf("Uargs:OPS: 0=write nand; 1=read nand; 2=erase nand\n\n");
}
// printf("\nbuf==0x%08x,ram==0x%08x,flash==0x%08x,len==0x%08x,flag==0x%08x\n",buf,ram,flash,len,flag);
ops=strtoul(argv[1],0,0);
ram=strtoul(argv[2],0,0);
flash=strtoul(argv[3],0,0);
len=strtoul(argv[4],0,0);
flag=strtoul(argv[5],0,0);
#if 1
switch(ops){
case 2:
erase_nand(ram,flash);
printf("erase nand ops OK...\n");
break;
case 1:
read_nand(ram,flash,len,flag);
printf("read nand ops OK...\n");
break;
case 0:
write_nand(ram,flash,len,flag);
printf("write nand ops OK...\n");
break;
default:
printf("\ninput invalid OPS(0 erase_nand; 1 read_nand; 2 write_nand)...\n\n");
break;
}
#endif
return 0;
}
#endif
int mynand_erase(int argc,char **argv)
{
u32 start=0,blocks=0;
if(argc!=3){
printf("args error...\n");
printf("uargs:erase_nand <startblock> <blocks>\n");
printf("example:erase_nand 1 0x10\n");
return -1;
}
start = strtoul(argv[1],0,0); //擦除块起始地址 128K为1块 0为第0块 1为第1块.....等等
blocks = strtoul(argv[2],0,0); //擦除的块数 0为不擦除
// printf("start==0x%08x,blocks==0x%08x\n",start,blocks);
erase_nand(start, blocks);
// printf("erase nand ops OK...\n");
return 0;
}
int mynand_read(int argc,char **argv)
{
u32 ram=0,flash=0,len=0;
u8 flag=0;
char *dst=NULL;
if(argc!=5){
printf("args error...\n");
printf("uargs:read_nand <ramaddr> <flashaddr> <len> <flag>\n");
printf("uargs:flag = (m/M(main),s/S(spare),a/A(main+spare))\n");
printf("example:read_nand 0xa1000000 0x0 0x20000 m\n");
return -1;
}
if(!strncmp(argv[4],"m",1) || !strncmp(argv[4],"M",1)){flag=0;} //main区
else if(!strncmp(argv[4],"s",1) || !strncmp(argv[4],"S",1)){flag=1;} //备用区
else if(!strncmp(argv[4],"a",1) || !strncmp(argv[4],"A",1)){flag=2;} //main+备用区
else{flag=0;}
ram = strtoul(argv[1],0,0); //读取的NAND Flash数据保存到的内存地址?
flash = strtoul(argv[2],0,0); //读取的NAND Flash起始地址?
len = strtoul(argv[3],0,0); //读取长度
// printf("ram==0x%08x,flash==0x%08x\n",ram,flash,len,flag);
read_nand(ram, flash, len, flag);
// printf("read nand ops OK...\n");
return 0;
}
int mynand_write(int argc,char **argv)
{
u32 ram=0,flash=0,len=0;
u8 flag=0;
char *dst=NULL;
if(argc!=5){
printf("args error...\n");
printf("uargs:write_nand <ramaddr> <flashaddr> <len> <flag>\n");
printf("uargs:flag = (m/M(main),s/S(spare),a/A(main+spare))\n");
printf("example:write_nand 0xa1000000 0x0 0x20000 m\n");
return -1;
}
if(!strncmp(argv[4],"m",1) || !strncmp(argv[4],"M",1)){flag=0;} //main区
else if(!strncmp(argv[4],"s",1) || !strncmp(argv[4],"S",1)){flag=1;} //备用区
else if(!strncmp(argv[4],"a",1) || !strncmp(argv[4],"A",1)){flag=2;} //main+备用区
else{flag=0;}
ram = strtoul(argv[1],0,0); //将要写到NAND Flash中的,暂存在内存中的数据首地址?
flash = strtoul(argv[2],0,0); //写入的NAND Flash起始地址?
len = strtoul(argv[3],0,0); //写入长度
printf("ram=0x%08x,flash=0x%08x, len = 0x%08x, flag = 0x%08x\n",ram,flash,len,flag);
write_nand(ram, flash, len, flag);
// printf("write nand ops OK...\n");
return 0;
}
static const Cmd Cmds[] =
{
{"MyCmds"},
{"erase_nand","val",0,"NANDFlash OPS:erase_nand <startblock> <blocks>",mynand_erase,0,99,CMD_REPEAT},
{"read_nand","val",0,"NANDFlash OPS:read_nand <ramaddr> <flashaddr> <len> <flag(a/A/m/M/s/S)>",mynand_read,0,99,CMD_REPEAT},
{"write_nand","val",0,"NANDFlash OPS:write_nand <ramaddr> <flashaddr> <len> <flag(a/A/m/M/s/S)>",mynand_write,0,99,CMD_REPEAT},
//{"mtd_erase","val",0,"NANDFlash OPS:mtd_erase /dev/mtdx",my_flash_erase,0,99,CMD_REPEAT},
{0, 0}
};
static void init_cmd __P((void)) __attribute__ ((constructor));
static void init_cmd()
{
cmdlist_expand(Cmds, 1);
}