s3c2440_Nand Flash Controller

来源:互联网 发布:html调用js函数 编辑:程序博客网 时间:2024/06/04 18:25

Nand Flash简介:Nand Flash是由日本的东芝公司(Toshiba)于1989年发明。它具有掉电后仍能保存数据的特点,类似于PC上的硬盘,可以用来存放操作系统、应用程序、各个进程产生的各类数据。【Nor Flash是在1988年时由美国的Intel公司发明,比较贵,写入速度较慢,寿命较短,不易发生位反转等特点】

Nand Flash的接口是I/O接口,不能随机访问任意地址上的数据,只能顺序访问并且是串行访问,因此代码不能直接在上面执行。而Nor的是和RAM的接口相同的,支持XIP(eXecute In Place立地执行),不需要将其中的代码复制到内存中执行。


tq2440开发板上面用到的nand是K9F208U0A,原理图如上。

引脚功能:

8个I/O口:写操作时,用来输入命令,行列地址和数据;读操作时,只输出数据;不使用芯片时I/O处于高阻态。

CLE:命令锁存使能端为高电平“1”同时CE和WE为“0”时I/O上的命令送入命令寄存器中,并且在WE的上升沿到来时锁定写入。ALE是地址锁存使能端,使用和CLE一样。当CLE和ALE都无效时数据有效。从下面的表中可以知道写入命令、地址和数据都是在WE上升沿到来时锁定的。RE:读使能端,要读数据时“0”有效。这些引脚的高低电平的设置只需要配置2440的相关寄存器就可以自动完成。


物理结构:容量为256MByte,内部需要28(2^28bit=256MB)条地址线(包括了:行地址和列地址),我们可能会疑惑连接nand的总线宽度只有8位(8个I/O),实际要用到的地址宽度远比这个大。如此的结构是为了减小芯片的体积和提高可扩展性。

K9F208U0A以页(Page)为单位进行读写,以块(Block)为单位进行擦除。

1Block=64 Pages(总共2048 Blocks)

1Page=2112Bytes(Main Area:2KBytes + Space Area:64Bytes)这个64 Bytes的空闲区的主要作用是补偿Nand Flash上产生的坏块,这样有坏块产生时系统通过算法管理将数据转移到空闲区。

2K Bytes:



地址周期长度为:5



命令集合:


前面讲了一大段Nand Flash存储器,对它进行读写大量的数据时不是简单的CPU对Nand发地址,存取数据,它需要一个东东来管理它,这东东就是今天的主角:Nand Flash Controller。s3c2440里面集成了NandFlash控制器。控制器提供了几个寄存器来简化对Nand的操作。前面也有提过,比如想要发出写命令时,只需要往NFCMMD寄存器里面写入0x80即可,Nand Flash控制器会自动发出各种控制信号。

2440的nand控制器的寄存器功能:

NFCONF:nand配置寄存器。设置时序宽度TACLS[13:12]bit(命令和地址使能信号的建立时间)、nWE和nRE引脚使能信号有效时长TWPRH0[10:8]bit、写入数据起作用的时间长TWRPH1[6:4]bit ; 只读位[3:1]用来读取支持页的类型和多少个地址周期 ; bit 1设置数据宽度。结合下面的时序图理解,持续时间计算还要结合nand的芯片手册。


NFCONT:nand控制寄存器。使能/禁止nand控制器和nFCE信号、初始化ECC(用于校验)、锁定nand(只读,不可写和擦除,很少会用到)

NFCMMD:nand命令寄存器。只需要往这个寄存器写入命令即可,cpu不用管nand有没有收到,这样就可以加快处理速度。

NFADDR:地址寄存器。

NFDATA:数据寄存器。用来读写数据。有32位长,只用到8位。

NFSTAT:nand状态寄存器。只用到了bit0,0:busy,1:ready


由于下面是关于读nand操作的代码,nand控制器的相关寄存器就只说上面6个,如果要进行写和擦除操作看看2440的datasheet找到相关的寄存器来配置就可以了。

startup.S文件:实现将Nand Flash上存放的第二段代码(4k以后的)复制到SDRAM上执行。

.text.global _start_start:            ldr     sp, =4096            bl      disable_watch_dog            bl      memsetup            bl      nand_init                        @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中            ldr     r0,     =0x30000000                 mov     r1,     #4096                     mov     r2,     #2048                       bl      read_nand               @调用C函数nand_read            ldr     sp, =0x34000000         @设置栈            ldr     lr, =halt_loop          @设置返回地址            ldr     pc, =mainhalt_loop:            b       halt_loop
后面调用main函数不能使用bl指令来跳转,因为在整个代码中使用.lds连接脚本将目标文件分开连接,只能使用ldr指令跳转。【地址无关:运行地址与编译地址无关。地址相关:编译地址等于运行地址】

nand.lds文件:将目标文件分开排列

SECTIONS {   firtst  0x00000000 : { startup.o init.o nand.o}  second 0x30000000 : AT(4096) { main.o }} 
第2行:startup.o init.o nand.o这3个目标文件连接在一起的运行地址为0,且生成的映像文件的偏移地址为0,即从0开始存放。

第3行:main.o的运行地址为0x30000000(在SDRAM上,)映像文件的偏移地址为4096,即存放在nand上地址为4096处。

init.c文件:完成基本初始化。这个文件就不解释了,估计大家都懂的。

#define WTCON(*(volatile unsigned long *)0x53000000)#define MEM_CTL_BASE0x48000000  //start address of memory controler register void disable_watch_dog();void memsetup();void disable_watch_dog(){WTCON= 0;}void memsetup(){int i = 0;unsigned long *p = (unsigned long *)MEM_CTL_BASE;unsigned long  const    mem_cfg_val[]={ 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                                              };for(; i < 13; i++)p[i] = mem_cfg_val[i];}
关键的是下面这个文件。
nand.c文件:初始化nand flash,nand的读操作

#define rNFCONF         (*(volatile unsigned int *)0x4e000000)     #define rNFCONT         (*(volatile unsigned int *)0x4e000004)   #define rNFCMMD         (*(volatile unsigned char *)0x4e000008)  #define rNFADDR         (*(volatile unsigned char *)0x4e00000C)  #define rNFDATA         (*(volatile unsigned char *)0x4e000010) #define rNFSTAT         (*(volatile unsigned char *)0x4e000020)#define Busy 1void nand_init(void);void read_nand(unsigned char *buf,unsigned long start_addr,int size);/*Operating funtion*/static void nand_chip_select(void){int i;rNFCONT &= ~(1<<1);for(i=0;i<10;i++);}static void nand_chip_deselect(void){rNFCONT |= (1<<1);}static void write_commond(int cmd){rNFCMMD = cmd;}static void write_addr(unsigned int addr)  //Five cycles{int i;rNFADDR = (addr & 0xff);for(i=0;i<10;i++);rNFADDR = (addr>>8)&(0x0f);for(i=0; i<10; i++);rNFADDR = (addr>>11)&(0xff);for(i=0;i<10;i++);rNFADDR = (addr>>19)&(0xff);for(i=0;i<10;i++);rNFADDR = (addr>>27)&(0x02);for(i=0;i<10;i++);}static void wait_operate(void)  //Read the status register{int i;while(!(rNFSTAT & Busy))for(i=0;i<10;i++);}static unsigned char read_data(void){return rNFDATA;}static void nand_reset(void){nand_chip_select();write_commond(0xff);wait_operate();nand_chip_deselect();}void nand_init(void) {#define TACLS 0#define TWRPH0 3  //为了满足TACLS+TWRPH0+TWRPH1>46ns.这里是设置50ns#define TWRPH1 0/*set time series*/        rNFCONF = ((TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4));/* enable Nand controler initialize ECC,nand chip deselect*/rNFCONT = (1<<4)|(1<<1)|(1<<0);nand_reset();}void read_nand(unsigned char *buf,unsigned long start_addr,int size)//argument_1:destination address   2:nand read start_address  3:length of data{int i,j;if ((start_addr & (2048-1)) || (size & (2048-1))){        return ;    /*The length of address is not aligned*/}nand_chip_select();for(i=start_addr;i<(start_addr+size);){write_commond(0);write_addr(i);write_commond(0x30);wait_operate();for(j=0;j<2048;j++,i++){*buf = read_data();buf++;}}nand_chip_deselect();return ;}
定义写地址操作函数write_addr()函数时首先要先明确上电复位时nand的Page size大小。我用的天嵌板2440的nand flash是256MB的K9F2G08U0A,支持8bit、2KBytes(+64Bytes)的Pages、5个写地址周期(由原理图可知NCON0=1,GPG13=1,GPG14=1,GPG15=0)。




0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 运管罚款没钱交怎么办 郑州地铁票没买怎么办 遇到吸毒者拦路威胁要钱怎么办 开车遇见拦路要钱的怎么办 高速上有人拦车怎么办 马路上有人拦车怎么办 苹果手机下截软件要钱怎么办 孩子在学校问同学要钱怎么办 在学校被同学要钱怎么办 把人家店砸了要怎么办 外汇出金不到账怎么办 把罚款单弄丢了怎么办 在12306买不到下铺怎么办有 地铁票买反了怎么办 香港买错特惠票怎么办 到达迪拜t3 后怎么办 海藻面膜调多了怎么办 被鸡爪子抓伤了怎么办 被鸡抓伤肿了怎么办 护士电子化没有激活码怎么办 窗帘盒螺丝掉了怎么办 窗帘的环扣掉了怎么办 门式起重吊装行车脱轨怎么办 在日本丢了东西怎么办 在日本钱包丢了怎么办 被起诉后没钱还怎么办 分期付款卖车打不起车款怎么办 地铁票买多了怎么办 工伤陪护费没有发票怎么办 工伤医疗费报销单位不盖章怎么办 家里的led灯坏了怎么办 吊顶led灯坏了怎么办 客厅空了一面墙怎么办 轨道灯的轨道不够长怎么办 奔驰大灯不亮了怎么办 led顶灯不亮了怎么办 吸顶灯led灯坏了怎么办 车底盘塑料被刮怎么办 汽车门电机坏了怎么办 宁波北仑普高差三分该怎么办 上班的地方甲醛味很重怎么办