NAND Flash

来源:互联网 发布:手机应用数据备份 编辑:程序博客网 时间:2024/04/30 19:23

NAND Flash

参考链接:http://blog.csdn.net/angusing/article/details/8047155
SDRAM.C代码:
#include <common.h>
#define MEMCCMD 0x7e001004
#define P1REFRESH 0x7e001010
#define P1CASLAT 0x7e001014
#define MEM_SYS_CFG 0x7e00f120
#define P1MEMCFG 0x7e00100c
#define P1T_DQSS 0x7e001018
#define P1T_MRD 0x7e00101c
#define P1T_RAS 0x7e001020
#define P1T_RC 0x7e001024
#define P1T_RCD 0x7e001028
#define P1T_RFC 0x7e00102c
#define P1T_RP 0x7e001030
#define P1T_RRD 0x7e001034
#define P1T_WR 0x7e001038
#define P1T_WTR 0x7e00103c
#define P1T_XP 0x7e001040
#define P1T_XSR 0x7e001044
#define P1T_ESR 0x7e001048
#define P1MEMCFG2 0X7e00104c
#define P1_chip_0_cfg 0x7e001200
#define P1MEMSTAT 0x7e001000
#define P1MEMCCMD 0x7e001004
#define P1DIRECTCMD 0x7e001008
#define HCLK 133000000
#define nstoclk(ns) (ns/( 1000000000/HCLK)+1)
int ddr_init( void )
{
// tell dramc to configure
set_val( MEMCCMD, 0x4 );
// set refresh period
set_val( P1REFRESH, nstoclk(7800) );
// set timing para
set_val( P1CASLAT, ( 3 << 1 ) );  
set_val( P1T_DQSS, 0x1 );// 0.75 - 1.25
set_val( P1T_MRD, 0x2 );
set_val( P1T_RAS, nstoclk(45) );
set_val( P1T_RC, nstoclk(68) );
u32 trcd = nstoclk( 23 );
set_val( P1T_RCD, trcd | (( trcd - 3 ) << 3 ) );
u32 trfc = nstoclk( 80 );
set_val( P1T_RFC, trfc | ( ( trfc-3 ) << 5 ) );   
u32 trp = nstoclk( 23 );
set_val( P1T_RP, trp | ( ( trp - 3 ) << 3 ) ); 
set_val( P1T_RRD, nstoclk(15) );
set_val( P1T_WR, nstoclk(15) );
set_val( P1T_WTR, 0x7 );
set_val( P1T_XP, 0x2 );
set_val( P1T_XSR, nstoclk(120) );
set_val( P1T_ESR, nstoclk(120) );

// set mem cfg 
set_nbit( P1MEMCFG, 0, 3, 0x2 );  /* 10 column address */
/* set_nbit: 把从第bit位开始的一共len位消零,然后把这几位设为val */
set_nbit( P1MEMCFG, 3, 3, 0x2 );  /* 13 row address */
set_zero( P1MEMCFG, 6 ); /* A10/AP */
set_nbit( P1MEMCFG, 15, 3, 0x2 ); /* Burst 4 */
set_nbit( P1MEMCFG2, 0, 4, 0x5 );
set_2bit( P1MEMCFG2, 6, 0x1 );/* 32 bit */
set_nbit( P1MEMCFG2, 8, 3, 0x3 );/* Mobile DDR SDRAM */
set_2bit( P1MEMCFG2, 11, 0x1 );
set_one( P1_chip_0_cfg, 16 );/* Bank-Row-Column organization */
// memory init
set_val( P1DIRECTCMD, 0xc0000 ); // NOP
set_val( P1DIRECTCMD, 0x000 );// precharge
set_val( P1DIRECTCMD, 0x40000 );// auto refresh
set_val( P1DIRECTCMD, 0x40000 );// auto refresh
set_val( P1DIRECTCMD, 0xa0000 ); // EMRS
set_val( P1DIRECTCMD, 0x80032 ); // MRS
set_val( MEM_SYS_CFG, 0x0 );
// set dramc to "go" status
set_val( P1MEMCCMD, 0x000 );
// wait ready
while( !(( read_val( P1MEMSTAT ) & 0x3 ) == 0x1));
}

NAND.C代码:
#define MEM_SYS_CFG     (*((volatile unsigned long *)0x7E00F120))
#define NFCONF          (*((volatile unsigned long *)0x70200000))
#define NFCONT          (*((volatile unsigned long *)0x70200004))
#define NFCMMD          (*((volatile unsigned long *)0x70200008))
#define NFADDR          (*((volatile unsigned long *)0x7020000C))
#define NFDATA          (*((volatile unsigned char *)0x70200010))
#define NFSTAT          (*((volatile unsigned long *)0x70200028))
void nand_select(void)
{
NFCONT &= ~(1<<1);
}
void nand_deselect(void)
{
NFCONT |= (1<<1);
}
void nand_cmd(unsigned char cmd)
{
NFCMMD = cmd;
}
void nand_addr(unsigned char addr)
{
NFADDR = addr;
}
unsigned char nand_get_data(void)
{
return NFDATA;
}
void wait_ready(void)
{
while ((NFSTAT & 0x1) == 0);
}
void nand_reset(void)
{
/* 选中 */
nand_select();
/* 发出0xff命令 */
nand_cmd(0xff);
/* 等待就绪 */
wait_ready();
/* 取消选中 */
nand_deselect();
}
void nand_init(void)
{
/* 让xm0csn2用作nand flash cs0 片选引脚 */
MEM_SYS_CFG &= ~(1<<1);
/* 设置时间参数 */
#define TACLS     0
#define TWRPH0    1
#define TWRPH1    0
NFCONF &= ~((1<<30) | (7<<12) | (7<<8) | (7<<4));
NFCONF |= ((TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4));
/* 使能nand flash controller */
NFCONT |= 1;
nand_reset();
}
void nand_send_addr(unsigned int addr)
{
#if 0
unsigned int page = addr / 2048;
/* 这两个地址表示从页内哪里开始 */
nand_addr(addr & 0xff);
nand_addr((addr >> 8) & 0xff);
/* 下面三个地址表示哪一页 */
nand_addr(page & 0xff);
nand_addr((page >> 8) & 0xff);
nand_addr((page >> 16) & 0xff);
#else
nand_addr(addr & 0xff);         /* a0~a7 */
nand_addr((addr >> 8) & 0x7);   /* 程序的角度: a8~a10 */
nand_addr((addr >> 11) & 0xff); /* 程序的角度: a11~a18 */
nand_addr((addr >> 19) & 0xff); /* 程序的角度: a19~a26 */
nand_addr((addr >> 27) & 0xff); /* 程序的角度: a27~    */

#endif
}
int nand_read(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
unsigned int addr = nand_start;
int i, count = 0;
unsigned char *dest = (unsigned char *)ddr_start;
/* 选中芯片 */
nand_select();
while (count < len)
{
/* 发出命令0x00 */
nand_cmd(0x00);
/* 发出地址 */
nand_send_addr(addr);
/* 发出命令0x30 */
nand_cmd(0x30);
/* 等待就绪 */
wait_ready();
/* 读数据 */
for (i = 0; i < 2048 && count < len; i++)
{
dest[count++] = nand_get_data();
}
addr += 2048;
}
/* 取消片选 */
nand_deselect();
return 0;
}
int copy2ddr(unsigned int nand_start, unsigned int ddr_start, unsigned int len)
{
int ret;

/* 初始化nand flash controller */
nand_init();

/* 读nand flash */
ret = nand_read(nand_start, ddr_start, len);

return ret;
}