代码正确性验证:
验证代码的正确性可以使用先写入特定字符,然后在读出来的方法验证。
实验板:MINI2440 256M
首先下载一个可用的u-boot到NorFlash中,用于查看NandFlash中的数据。
然后以NorFlash启动进入u-boot,使用tftp工具或者其他工具把测试程序下载到NandFlash的0地址。以NandFlash启动查看测试结果。
测试文件main.c:
int xboot_main()
{
int num = 0;
int a = 1;
int b = 2;
char buf[2048] = {"hello NandFlash"};
char buf2[2048] = {};
uart_init();
printf("start nandflash read/write\n\r");
NF_Erase(0x32345);
NF_WritePage(0x32345,buf);
NF_PageRead(0x32345,buf2);
printf("\n\n%s\n\r",buf2);
while(1)
{
printf("\n***************************************\n\r");
printf("\n****************XBOOT*****************\n\r");
printf("1:Download Linux Kernel from TFTP Server!\n\r");
printf("2:Boot Linux from RAM!\n\r");
printf("3:Boot Linux from Nand Flash!\n\r");
printf("\n Plese Select:");
scanf("%d",&num);
switch (num)
{
case 1:
//tftp_load();
break;
case 2:
//boot_linux_ram();
break;
case 3:
//boot_linux_nand();
break;
default:
printf("Error: wrong selection!\n\r");
break;
}
}
return 0;
}
|
完整的nand.c文件:
#define NFCONF (*(volatile unsigned long*)0x4E000000)
#define NFCONT (*(volatile unsigned long*)0x4E000004)
#define NFCMD (*(volatile unsigned char*)0x4E000008)
#define NFADDR (*(volatile unsigned char*)0x4E00000C)
#define NFDATA (*(volatile unsigned char*)0x4E000010)
#define NFSTAT (*(volatile unsigned char*)0x4E000020)
#define TACLS 1
#define TWRPH0 2
#define TWRPH1 1
void select_chip()
{
NFCONT &= ~(1<<1);
}
void deselect_chip()
{
NFCONT |= (1<<1);
}
void clear_RnB()
{
NFSTAT |= (1<<2);
}
void send_cmd(unsigned cmd)
{
NFCMD = cmd;
}
void send_addr(unsigned addr)
{
NFADDR = addr;
}
void wait_RnB()
{
while (!(NFSTAT&(1<<2)))
{
;
}
}
void nand_reset()
{
//选中flash
select_chip();
//清除RnB
clear_RnB();
//发送0xff命令
send_cmd(0xff);
//等待RnB
wait_RnB();
//取消选中flash
deselect_chip();
}
void nand_init()
{
//初始化NFCONF
NFCONF = (TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);
//初始化NFCONT
NFCONT = (1<<0) | (1<<1);
//复位
nand_reset();
}
void NF_PageRead(unsigned long addr,unsigned char* buff)
{
int i;
//int col = addr % 2048;
//int page = addr / 2048;
int col = 0x0;
int page = addr;
//选中nandflash芯片
select_chip();
//清除RnB
clear_RnB();
//发送命令0x00
send_cmd(0x00);
send_addr(col & 0xff);
send_addr((col >> 8) & 0xff);
send_addr(page & 0xff);
send_addr((page >> 8) & 0xff);
send_addr((page >> 16) & 0xff);
//发送命令0x30
send_cmd(0x30);
//等待RnB
wait_RnB();
//读取数据
for(i=0;i<2048;i++)
{
buff[i] = NFDATA;
}
//取消选中nandflash芯片
deselect_chip();
}
void nand_to_ram(unsigned long start_addr, unsigned char* sdram_addr, int size)
{
int page = start_addr / 2048;
for(;size>0;)
{
NF_PageRead(page,sdram_addr);
size -= 2048;
sdram_addr += 2048;
page++;
}
}
int NF_Erase(unsigned long addr)
{
int ret;
unsigned int page = addr/2048;
//选中flash芯片
select_chip();
//清除RnB
clear_RnB();
//发送命令0x60
send_cmd(0x60);
//发送行地址
send_addr(page&0xff);
send_addr((page>>8)&0xff);
send_addr((page>>16)&0xff);
//发送命令D0
send_cmd(0xD0);
//等待RnB
wait_RnB();
//发送命令0x70
send_cmd(0x70);
//读取擦除结果
ret = NFDATA;
//取消选中flash芯片
deselect_chip();
return ret;
}
int NF_WritePage(unsigned long addr,unsigned char *buff)
{
unsigned int i,ret = 0,page,col;
col = addr % 2048;
page = addr /2048;
//选中nandflash
select_chip();
//清除RnB
clear_RnB();
//发送0x80命令
send_cmd(0x80);
//发送2个列地址
/* 这种写法ok
send_addr(col & 0xff);
send_addr((col >> 8) & 0xff);
send_addr(page & 0xff);
send_addr((page >> 8) & 0xff);
send_addr((page >> 16) & 0xff);
*/
send_addr(addr & 0xff); // a0~a7
send_addr((addr >> 8) & 0x7); // 以程序角度看 a8~a10
send_addr((addr >> 11) & 0xff); // 以程序角度看 a12~a19
send_addr((addr >> 19) & 0xff); // 以程序角度看 a20~a27
send_addr((addr >> 27) & 0xff); // 以程序角度看 a28
/* wrong 移位错误
send_addr(addr & 0xff); // a0~a7
send_addr((addr >> 8) & 0x7); // 以程序角度看 a8~a10
send_addr((addr >> 12) & 0xff); // 以程序角度看 a12~a19
send_addr((addr >> 20) & 0xff); // 以程序角度看 a20~a27
send_addr((addr >> 28) & 0xff); // 以程序角度看 a28
*/
//发送数据
for(i=0;i<2048;i++)
{
NFDATA = buff[i];
}
//发送0x10命令
send_cmd(0x10);
//等待RnB
wait_RnB();
//发送0x70命令
send_cmd(0x70);
//读取写入结果
ret = NFDATA;
//关闭nandflash
deselect_chip();
return ret;
}
|
使用到的命令:
tftp 30000000 xboot.bin; nand erase 0 10000; nand write 30000000 0 10000
下载成功后把把拨码开关拨到Nand启动,使用命令:
reset
|
执行完reset后看到:
可以看到NandFlash已经能正常写入并读取了,安全起见,再来使用u-boot查看一下NandFlash中的情况:
以Nor启动进入u-boot:
nand read 33000000 0x32000 10000; md.b 33000000 100
回车
回车
回车
回车,可以看到:
|
这就完全可以清晰的看到NandFlash中的值了。
移植u-boot的过程中,为了实现NandFlash启动会使用一段实现u-boot.bin从NandFlash拷贝到SDRAM的代码,学习完上述NandFlash的操作再去看那段代码就没有任何难度了。
完整工程下载地址:http://download.csdn.net/detail/doccode/8914847
使用到的u-boot.bin下载地址:http://download.csdn.net/detail/doccode/8914859