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)。
- s3c2440_Nand Flash Controller
- [Flash Component] Movie Controller
- s3c2440 nand flash controller
- NAND flash controller -samsung s3c2410 as example
- 关于FL2440的NAND FLASH CONTROLLER
- s3c6410硬件NAND FLASH CONTROLLER(NAND FLASH 控制器)
- IFC --- An introduction to Freescale Integrated Flash Controller
- Tiny6410学习笔记3——Nand Flash Controller
- controller
- Controller
- controller
- @controller
- Controller
- controller
- controller
- @Controller
- controller
- Controller
- c++构造函数再调用构造函数
- CSS雪碧:要还是不要?
- 工程文件存储策略,实现前后兼容打开。
- Word2vec在事件挖掘中的调研
- 设计模式C++实现(4)——单例模式
- s3c2440_Nand Flash Controller
- 二级指针详解
- htmlparser
- WhatsApp的190亿估值高不高?
- 学习Python的总结
- Ubuntu 12.04 LTS 中文输入法的安装
- 男人不坏, 女人不爱.
- void及void指针介绍
- 设计模式C++实现(5)——原型模式、模板方法模式