[国嵌攻略][052][NandFlash驱动设计_读]

NandFlash读数据方式

1.页读,读出页中主数据区的所有数据,提供页地址(行地址)

2.随机读,读出页中指定的存储单元的数据,提供页地址(行地址)和页内偏移(行地址)

 

代码编写

1.根据NandFlash中的读时序图写出工作流程,可以通过在芯片手册中搜索operation找到相关描述

2.主要关心的是IO脚上时序的变化

3.初始化闪存分为初始化闪存控制器和闪存芯片

4.对位操作

4.1.清零

x &= ~(y<<z)   对x的z位开始的y清零

4.2.置1

x |= y<<z   对x的z位开始的y置1

4.3.取数

x & y<<z   取出x的第z位开始的y

4.4.置数

x = y

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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
/********************************************************************
*名称:flash
*作者:D
*时间:2015.11.08
*功能:闪存驱动
********************************************************************/
 
/********************************************************************
*                            宏定义
********************************************************************/
#define NFCONF ( *((volatile unsigned long *)0x4E000000) )   //闪存配置寄存器
#define NFCONT ( *((volatile unsigned long *)0x4E000004) )   //闪存控制寄存器
#define NFCMMD ( *((volatile unsigned long *)0x4E000008) )   //闪存命令寄存器
#define NFADDR ( *((volatile unsigned long *)0x4E00000C) )   //闪存地址寄存器
#define NFDATA ( *((volatile unsigned char *)0x4E000010) )   //闪存数据寄存器
#define NFSTAT ( *((volatile unsigned long *)0x4E000020) )   //闪存状态寄存器
 
#define PAGE_SIZE 2048   //页大小
 
/********************************************************************
*                         函数原型声明
********************************************************************/
void init_flash();
void init_flash_controller();
void reset_flash_chip();
 
void read_flash(unsigned long src, unsigned long dst, int len);
void read_page_flash(unsigned long page, unsigned char *buf);
 
/********************************************************************
*名称:init_flash
*功能:初始化闪存
*********************************************************************/
void init_flash(){
    //初始化闪存控制器
    init_flash_controller();
     
    //重置闪存芯片
    reset_flash_chip();
}
 
/********************************************************************
*名称:init_flash_controller
*功能:初始化闪存控制器
*********************************************************************/
void init_flash_controller(){
    //初始化闪存配置寄存器
    NFCONF = (1<<12)|(1<<8)|(1<<4);   //设置TACLS:1 TWRPH0:1 TWRPH1:1
     
    //初始化闪存控制寄存器
    NFCONT = (1<<1)|(1<<0);   //设置Reg_nCE:1 MODE:1
}
 
/********************************************************************
*名称:reset_flash_chip
*功能:重置闪存芯片
*********************************************************************/
void reset_flash_chip(){
    //选中闪存芯片
    NFCONT &= ~(1<<1);   //设置Reg_nCE:0
     
    //清除忙信号
    NFSTAT |= (1<<2);    //设置RnB_TransDetect:0
 
    //发送重启命令
    NFCMMD = 0xFF;
     
    //等待忙信号
    while( !(NFSTAT&(1<<2)) );   //当RnB_TransDetect等于1时,结束循环
     
    //释放闪存芯片
    NFCONT |= 1<<1;   //设置Reg_nCE:1
}
 
/********************************************************************
*名称:read_flash
*参数:
*   src   源地址
*   dst   目的地址
*   len   读取长度
*返回:
*   null
*功能:读闪存
*********************************************************************/
void read_flash(unsigned long src, unsigned long dst, int len){
    unsigned long page;   //页号
    unsigned char *buf;   //页缓存
     
    while(len > 0){
        page = src>>11;               //设置页号
        buf = (unsigned char *)dst;   //设置页缓存
        read_page_flash(page, buf);
         
        src +=PAGE_SIZE;
        dst +=PAGE_SIZE;
        len -=PAGE_SIZE;
    }
}
 
/********************************************************************
*名称:read_page_flash
*参数:
*   page   页号
*   buf    页缓存,2048字节
*返回:
*   none
*功能:页读闪存
*********************************************************************/
void read_page_flash(unsigned long page, unsigned char *buf){
    int i;   //循环计数器
 
    //选中闪存芯片
    NFCONT &= ~(1<<1);   //设置Reg_nCE:0
     
    //清除忙信号
    NFSTAT |= (1<<2);    //设置RnB_TransDetect:0
 
    //发送读命令(0x00)
    NFCMMD = 0x00;
     
    //发送列地址
    NFADDR = 0x00;   //Col.Add1
    NFADDR = 0x00;   //Col.Add2
     
    //发送行地址
    NFADDR = (page>>0)&0xFF;    //Row.Add1
    NFADDR = (page>>8)&0xFF;    //Row.Add2
    NFADDR = (page>>16)&0xFF;   //Row.Add3
     
    //发送读命令(0x30)
    NFCMMD = 0x30;
     
    //等待忙信号
    while( !(NFSTAT&(1<<2)) );   //当RnB_TransDetect等于1时,结束循环
     
    //读取数据
    for(i = 0; i < PAGE_SIZE; i++){
        buf[i] = NFDATA;   //注意,NFDATA寄存器数据类型要和buf匹配,一个读周期读出一个字节
    }
     
    //释放闪存芯片
    NFCONT |= 1<<1;   //设置Reg_nCE:1
}

 

posted @   盛夏夜  阅读(316)  评论(0编辑  收藏  举报
编辑推荐:
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
阅读排行:
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
点击右上角即可分享
微信分享提示