NFSTAT寄存器 

当RnB信号由低电平跳变成高电平时,该bit位会被自动置1(硬件完成),表示Flash可以读,读NFDATA寄存器; 
但是,此信号何时变为低电平?手动操作该bit位,使其清0。 
有点特殊的是,如果将该bit清0,要向该bit写1. 
此方法与以往有区别: 
写 0 ,清0 
写 1,置1 
而该bit位: 
写1,清0 
自动,置1

案例:读Nand flash的第0页的主数据 
2048+64 bytes 
u-boot.bin 
nand_page.h

#define __NAND_H__
#define __NAND_H__//定义寄存器
#define NFCONF (*((volatile unsigned int*)0xBOE00000));
#define NFCONT (*((volatile unsigned int*)0xBOE00004));
#define NFCMMD (*((volatile unsigned int*)0xBOE00008));
#define NFADDR (*((volatile unsigned int*)0xBOE0000C));
#define NFDATA (*((volatile unsigned int*)0xBOE00010));
#define NFSTAT (*((volatile unsigned int*)0xBOE00028));//声明函数原型
extern void nand_init(void);
extern void nand_read_id(void);
//buf:保存读取页数据的首地址
//page:表示要读的页号
extern void nand_page_read(unsigned int *buf,unsigned int page);#endif
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

nand_page.c

#include "nand.h"
#include "uart.h"
#include "itoa.h"void nand_init(void)
{//nand flash 控制器使用的管脚配置,//因为我们使用的nand flash启动方式,所以关于GPIO管脚功能配置可以不做//如果使用的不是nand flash启动,将需要配置NFCONF = (0xF<<12) | (0xF<<8) |(0xF<<4) | (1<<1); NFCONT = (3<<12) | (3<<8) | 7;
}void nand_read_id(void)
{//1,nand falsh片选信号拉低,使能nand falsh芯片//操作 NFCONT bit[1] = 0;NFCONT &= ~(1<<1);//  1<<1 ==> 10//2,向NFCMMD寄存器写入0x90NFCMMD = 0x90;//3,向NFADDR寄存器写入0x0NFADDR = 0x0;//4,延时int i;for(i = 0;i < 256; i++){;}//5,读NFDATA 寄存器(字)ID//读5个字节的ID号unsigned int id1;unsigned int id2;id1 = NFDATA;id2 = (NFDATA & 0xFF);//只要低八位//6,Nand flash片选信号拉高//操作 NFCONT bit[1] = 1;NFCONT |= (1<<1) ;//7,显示读出来的nand flash的ID号char buf[16];uart0_puts("\n ID1 = ");itoa(buf,id1);//转换(整型无法直接打印,打印前转换成字符串)uart0_puts(buf);//输出uart0_puts("\n ID2 = ");itoa(buf2,id2);//转换uart0_puts(buf2);//输出
}void nand_page_read(unsigned int *buf,unsigned int page)
{//1.Nand Flash 片选信号拉低NFCON &= ~(1<<1);//2。发送第一次读命令 0x0NFCMD = 0x0;//3,发送页内地址,分两个周期//由于读一页,给该页第0个//字节的页内地址,即0NFADDR = 0x0;NFADDR = 0x0;//4,发送页号,分三个周期NFADDR = (page & 0xFF);//低8bit//bit[15:8]NFADDR = ((page >> 8) & 0xFF);//中间的8 bit//bit[18:16]NFADDR = ((page >> 16) & 0xFF);//5,发送第二次读命令 0x30NFCMMD = 0x30//6,清除标志NFSTAT 写1清bit[4]NFSTAT |= (1<<4);//7,等待NFSTAT bit[4]自动置 1 while(!(NFSTAT & (1<<4))){;}//8,读取数据(2048)NFDATA//以字读NFDATAint i;for(i=0;i<512;i++)//512*4 = 2048{buf[i] = NFDATA;}//9, nand flash片选信号拉高NFCONT |= (1<<1) ;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85

cmd.c

#include "cmd.h"
#include "led.h"
#include "nand.h"
#include "nand_page.h"void cmd_ledon(void)
{//调用开灯函数led_on();
}void cmd_nid(void)
{//调用读nand flash Id函数nand_read_id();
}void cmd_ledoff(void)
{//调用关灯函数led_off();
}static unsinged int test_buf[512];
void cmd_read(void)
{char itoa_buf[16];uart0_puts("\n nand read...");nand_page_read(test_buf,0);
}void cmd_boot_linux(void)
{//后面实现
}const cmd_t cmd_tb1[] =
{{"ledon",cmd_ledon},{"ledoff",cmd_ledoff},{"nid",cmd_nid},{"nread",cmd_read},{"bootlinux",cmd_boot_linux},//启动内核的命令,后面会用到
};int cmd_tab1_num = sizeof(cmd_tb1)/sizeof(cmd_tb1[0]);cmd_t *find_cmd(const char *name)
{for(int i=0;i<cmd_tab1_num;i++){if(name == cmd_tb1[i].name){return cmd_tb1[i];}  }return NULL;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58

案例:如何把linux内核读到内存中? 
启动TAPD ,烧写Image 
tarena# tftp 0x20008000 Image 
tarena#nand erase 0x600000 0xC00000 #从6MB的位置开始,擦除12MB 
tarena#nand write 0x20008000 0x600000 0xC00000 

cmd.c中的cmd_boot_linux函数实现如下:


typedef void (*func_t)(int r0,int r1,int r2);//函数指针,无返回值,三个整型参数void cmd_boot_linux(void)
{//1,从nand falsh的0x600000读取内核Image到内存的//0x20008000,大小0xC00000uart0_puts("\n Loading kerenl");unsigned int *ptr = (unsigned int *)0x200080000//求起始页 6MB(0x600000)//每一页2048字节大小unsigned int page = 0x600000/2048;int i;for(i=0;i<0xC00000/2048;i++){uart0_putc('.');nand_page_read(ptr,page);page++;//读下页ptr += 2048/4;//读过来的起始地址}uart0_puts("\n Run linux...");//2,调用内存0x20008000处的Image(内核)func_t = kernel_start;kernel_start = (func_t)0x20008000;//把这个地址强制转换为一个函数的地址,为了后面执行这个函数kernel_start(0,2456,0);//这里与移植有关,先忽略
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

链接脚本 shell.lds

//1,告诉链接器如何组织可执行文件
//2,描述了程序在内存中执行时的大致内存布局,注意各个段的顺序
SECTIONS
{.= 0x23000000;.text:{main.o(.text);*.o(.text);}.rodata:{*.o(.rodata);}. = ALIGN(4);//4字节对齐.data://数据段{*.o(.data);}.=ALIGN(4);__bss__start = .;.bss :{.o(.bss);}__end =.;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29

将makefile文件中的”-Ttext 0x20008000” 修改为”-T shell.lds”即可,链接过程就会按照链接脚本的方式往下执行。

坏块处理 
坏块判断原则:

Nand falsh 8192块 
1块=64页

main区: 
spare区:

0块 
0页 


… 
63 
读第0页,第2048个字节(spare区第一个字节), 
如果不是0xFF,那就是一个坏块, 
如果是0xFF,读第一页,第2048个宽限(spare区第一个字节) 
如果是0xFF,好块 
如果不是0xFF,坏块

好块: 
第0页,2048,0xFF 
第1页,2048,0xFF

坏块: 
1)第0页,2048,不是0xFF 
2)第0页,2048,0xFF 
第1页,2048,不是0xFF

1块 
第64页(绝对页号) 
第65页(绝对页号)

2块 
第128页 
第129页

3块 
192页 
193页

在nandread.h中增加

//读page的len个字节到buf
extern void nand_page_oob(char *buf,int len,unsigned int page);//判断是否坏块
extern int nand_blk_check(unsigned int page_no);
  • 1
  • 2
  • 3
  • 4
  • 5

在对应的.c文件中

//读page的len个字节到buf
extern void nand_page_oob(char *buf,int len,unsigned int page)
{//1,Nand flash 的片选信号拉低NFCONT &= ~(1<<1);//2,发送读命令 1: 0x0NFCMMD = 0x0;//3,发送页内地址,2次,2048NFADDR = 0x0;NFADDR = 0x8;//4,发送页号地址,3次NFADDR = (page & 0xFF);NFADDR = (page >>8) & 0xFF);NFADDR = (page >>16) & 0xFF);//5,发送读命令 2:0x30NFADDR = 0x30;//6,清等待标志,清NFSTAT bit[4],写1清0//7,等待NFSTAT bit[4]跳变成1//8,读取一个字节的坏块标志//由于是读一个字节,int i;for(i=0;i<len;i++){// buf[] = ;}//9,nand flash片选信号拉高NFCONT |=(1<<1);
}//判断是否坏块
extern int nand_blk_check(unsigned int page_no)
{unsigned char flag;nand_page_read_oob(&flag,1,page_no);if(flag != 0xFF){return 1;//坏块}nand_page_read_oob(&flag,1,page_no++);if(flag != 0xFF){return 1;//坏块}return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44

cmd.c增加命令nbad

void cmd_nandbad(void)
{int i;char ibuf[16];for(i=0;i<;i++)//循环一次判断一块{if(nand_blk_check(i)) //页号是每块的起始页号{uart0_puts("\n Bad B lock:");itoa(ibuf,i);//将i转成字符uart0_puts(ibuf);}}
}

NFSTAT寄存器 的RnB的bit4相关推荐

  1. 嵌入式裸机NandFlash和 SD/iNand学习笔记

    一. Nandflash 1.1 定义 Nand-flash存储器是flash存储器的一种,其内部采用非线性宏单元模式,为固态大容量内存的实现提供了廉价有效的解决方案.Nand-flash存储器具有容 ...

  2. Nandflash 驱动移植

    前段时间,研究了一下4G的Nandflash驱动.手头上只有飞凌6410BSP自带的Nandflash驱动,该驱动不支持K9GAG08U0D(2G)和K9LBG08U0D(4G)的Nandflash. ...

  3. S5PV210体系结构与接口11:NandFlash SD卡编程

    目录 1. Flash ROM简介 1.1 概述 1.2 Nor & Nand Flash比较 1.2.1 接口对比 1.2.2 容量和成本对比 1.2.3 可靠性对比 1.2.4 使用寿命对 ...

  4. 嵌入式Linux驱动学习【8】—— Nand Flash

    1 Nand Flash   原理图.   引脚: 引脚 功能 IO0~IO7 数据输入输出 CLE 命令锁存 ALE 地址锁存 nCE 芯片使能 nRE 读使能 nWE 写使能 R/nB 就绪/忙 ...

  5. 7.NAND芯片的读写及ECC检验软硬件实现_上

    最近在study ARM,在网上看到一些先行者们总结出来的一些东西,觉得很有参考意义,特收藏起来便于日后查找学习(在此向原帖作者致敬). 第一节概论 nandflash在对大容量的数据存储中发挥着重要 ...

  6. u-boot 启动代码start.S详解(for mini2440)

    u-boot存储器映射图: start.S 代码分析 #include <common.h> #include <config.h>/*#include <config. ...

  7. fl2440u-boot移植

    在移植u-boot之前,可以参考我之前的博客移植操作一遍,理解一下ARM-LINUX的启动流程:bootloader->linux内核->文件系统->应用程序.最重要的一点,移植u- ...

  8. LED音乐频谱之输出数据处理

    转载请注明出处:http://blog.csdn.net/ruoyunliufeng/article/details/38023539 一.PWM调节 1.初始化 void DACInit() {CC ...

  9. Nandflash 驱动深度分析(基于S3C2410)

    NAND Flash在嵌入式系统中的地位与PC机上的硬盘类似,用于保存系统运行所必需的操作系统.应用程序.用户数据.运行过程中产生的各类数据.与内存掉电后数据丢失不同,NAND Flash中的数据在掉 ...

最新文章

  1. iOS 单例模式全面解析
  2. 怎样将项目上传到github上
  3. S3C2410时钟部分总结
  4. POJ 3461 kmp 应用
  5. 收集常用的CSS基础面试题
  6. unity自动生成敌人_Unity 3D做2D坦克大战--敌人自动攻击AI编写
  7. 大数据分布式工作流任务调度系统DolphinScheduler v1.3.4
  8. 【3D游戏建模】3D建模师的发展前景
  9. 第三章:react 应用( 基于 react )
  10. 双绞线传输距离_一看就懂的网络传输介质介绍
  11. 计算机是如何启动的?(转载)
  12. SQL 经典练习题 + 答案
  13. Mapgis67软件实用操作
  14. Django技术文档
  15. html 横屏滚动字幕,手机知识:手机横屏滚动字幕
  16. 显卡参数详解[原创]
  17. 计算机进入启动死循环,教你win10重启死循环怎么解决
  18. autocad2014 菜单栏 闪退_AutoCAD2014闪退解决办法
  19. MyBatis 大于小于符号表示
  20. Android Camera使用OpenGL ES 2.0和GLSurfaceView对预览进行实时二次处理(黑白滤镜)

热门文章

  1. 剑指offer 专项突破版 78、合并排序链表
  2. B站 MySQL学习随手记 全是满满的干货!
  3. 液晶显示屏划痕修复方法
  4. 2017年全球FinTech变革全景揭秘及前景展望
  5. 景区WiFi覆盖方案
  6. 技术架构之高并发系统设计方法论
  7. Oracle数据库学习第一天
  8. 使用U盘系统盘安装操作系统步骤
  9. 【Jenkins】插件安装报错“另一个程序正在使用此文件,进程无法访问”完美解决
  10. H.324M 3G-324M