mini2440中nand falsh的使用

Nand flash复用数据总线和地址总线,并由相应的控制信号区分。以页为单位读取,块为单位擦除。由于没有完整的数据总线和地址总线,并且不能以字节为单位擦除,所以存储在Nand flash的程序要加载到ARM中执行。

mini2440 Nand flash连接:

http://blog.csdn.net/c1194758555 

nFCE:使能信号。

CLE:控制信号。

ALE:地址控制信号。

nFWE:写使能信号。

nFRE:读使能信号。

LDATA0 - LDATA7:数据传输。

mini2440中256M的NAND FLASH 存储单元结构组织结构图:


NAND FLASH每页有2KB+64B的ECC校验。每块有64页。有8个IO进行数据传输,由相应的控制信号来区分传输的为命令,地址,数据。


地址序列表

Nand Flash的使用:

Makefile文件:

objs := start.o init.o nand.o led.o

nand.bin : $(objs)
	arm-linux-ld -Tnand.lds	-o nand_elf $^
	arm-linux-objcopy -O binary -S nand_elf $@
	arm-linux-objdump -D -m arm  nand_elf > nand.dis

%.o:%.c
	arm-linux-gcc -Wall -c -O2 -o $@ $<

%.o:%.S
	arm-linux-gcc -Wall -c -O2 -o $@ $<

clean:
	rm -f  nand.dis nand.bin nand_elf *.o

链接脚本:

SECTIONS
{
   . = 0x0;
   .one  : { start.o init.o nand.o }
   . = 0x30000000;
   .two  : AT(4096) { led.o }
}

把初始化操作放到前4KB,点亮LED的放到4KB后面,可以验证是否从Nand Flash读取成功。前4K中在CPU内部ARM执行的指令的跳转是与位置无关,而ldr pc,=main是与位置有关的指令,所以程序将调到SDARM中执行。由于没有开MMU,所以CPU发出的地址就是实际的物理地址。

初始化CPU:

#define mem_addr 0x48000000
#define WTDOG (*(volatile unsigned long *)0x53000000)
void close_wtdog()
{
   WTDOG = 0x00;
}

void mem_init()
{
   unsigned int i;
   const unsigned long table[]={ 0x22011110,     //BWSCON
                                 0x00000700,     //BANKCON0
                                 0x00000700,     //BANKCON1
                                 0x00000700,     //BANKCON2
                                 0x00000700,     //BANKCON3  
                                 0x00000700,     //BANKCON4
                                 0x00000700,     //BANKCON5
                                 0x00018005,     //BANKCON6
                                 0x00018005,     //BANKCON7
                                 0x008C07A3,     //REFRESH
                                 0x000000B1,     //BANKSIZE
                                 0x00000030,     //MRSRB6
                                 0x00000030,     //MRSRB7
                                    };

   unsigned long* temp = (unsigned long*)mem_addr;
   
   for(i = 0; i < 13; i++)
       temp[i] = table[i];
}

Nand flash的操作:

#define NFCNF   (*(volatile unsigned char*)0x4E000000)
#define NFCONT  (*(volatile unsigned char*)0x4E000004)
#define NFCMMD  (*(volatile unsigned char*)0x4E000008)
#define NFADDR  (*(volatile unsigned char*)0x4E00000C)
#define NFDATA  (*(volatile unsigned char*)0x4E000010)
#define NFSTAT  (*(volatile unsigned char*)0x4E000020)

#define pag_size 2048
void write_cmd(unsigned int cmd)
{
   NFCMMD = cmd;
}

void write_addr(unsigned int adds)
{
  unsigned int col = adds & (pag_size - 1);
  unsigned int pag = adds / pag_size;
  
  NFADDR = col & 0xff;
  unsigned char i;
  for(i = 0; i < 10; i++);
  NFADDR = (col >> 8) & 0xf;
  for(i = 0; i < 10; i++);

  NFADDR = pag & 0xff;
  for(i = 0; i < 10; i++)
  NFADDR = (pag >> 8) & 0xff;
  for(i = 0; i < 10; i++);
  NFADDR = (pag >> 16) & 0x3;
  for(i = 0; i < 10; i++); 
}

unsigned char read_data()
{
  return NFDATA;
}

void busy()
{
   int i;
   while(!(NFSTAT & (0x1 << 0)))
   for(i = 0; i < 10; i++);
}

void set_disce()
{
  NFCONT |= (0x1 << 1);
}

void set_edce()
{
  unsigned char i;
  NFCONT &= (~(0x1 << 1));
  for(i = 0; i < 10; i ++);
}

void rest_nand()
{
   set_edce();
   write_cmd(0xff);
   busy();
   set_disce();
}

void init_nand()
{
   NFCNF = (0x0 << 12 | 0x3 << 8 | 0x0 << 4);
   NFCONT = (0x1  << 4 | 0x1 << 1 | 0x1 << 0);
   rest_nand();
}

void Read(unsigned char* buf,unsigned long addr,unsigned long size)
{
 if((addr & (pag_size -1)) || (size & (pag_size - 1))) return;

  set_edce();
  unsigned int i,j;

  for(i = addr; i < (addr + size); )
  {
    write_cmd(0x0);
    write_addr(i);
    write_cmd(0x30);
    busy();

    for(j = 0; j < pag_size; j++,i++)
    {
      *buf = read_data();
      buf++;
    }
  }
  set_disce();
  return;
}

由于Nand flash的数据是通过8个IO传输的,所以要用char类型,否则不能达到预期的效果。

LED闪烁:

#define GPIO  0x56000000 /*GPIO的基地址*/
#define GPBCON (*(volatile unsigned long *)(GPIO + 0x10)) 
#define GPBDAT (*(volatile unsigned long *)(GPIO + 0x14))
void time(volatile unsigned long t)
{
   while(t--);
}

int main()
{  
   GPBCON &=  (~(0x3 << 12 | 0x3 << 14 | 0x3 << 16 | 0x3 << 10));
   GPBCON |=    (0x1 << 12 | 0x1 << 14 | 0x1 << 16 | 0x1 << 10);

   while(1)
   {
      GPBDAT &=  (~(0x1 << 5  | 0x1 << 6  | 0x1 << 7  | 0x1 << 8));
      time(50000);
      GPBDAT |=   (0x1 << 5  | 0x1 << 6  | 0x1 << 7  | 0x1 << 8);
      time(50000);
   }
   return 0;
}

 



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值