JZ2440的NandFlash控制器

2024-02-29 21:40
文章标签 控制器 nandflash jz2440

本文主要是介绍JZ2440的NandFlash控制器,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

【点此回顾上课学习内容]

芯片的型号:K9F2G08U0C

摘要: 本文以S3C2440为例来讲解NAND FLASH控制器的使用方法. 例程中故意将一部分代码放置到 nand 的4k 字节之后, 因无法自动拷贝到steppingstone, 所以需要读取nand中的内容到sdram, 本例程重点关注nand的初始化和读取.

1. 硬件部分:


1.1 简介

  • 芯片大小:256M Byte
  • 记忆单元阵列:(256M + 8,192K)bit x 8bit
  • 擦写次数比较少:10 万次 
  • 数据保留时间:10 年
  • 8个IO 口进行数据和地址的复用,因此,读写的时候要用到多个周期
 引脚定义及接法



1.2 内部存储单元的组织结构:



K9F2G08U0C共有2048个Block(块), 每个Block含有64 Page(页), 每个Page含有2k byte的正常存储空间以及64 byte的校验空间 .

总空间 = 2048 * 64 * (2 * 1024 + 64)  byte = 264MB

实际存储空间 = 2048 * 64 * 2 * 1024 byte = 256MB

对 nandflash 的结构的几点说明:

  1.  一页中 1k 表示的是main 区(用于存储用户数据)容量,32 表示的是 spare 区(用于在读写操作的时候存放校验码)容量
  2. 块的大小一般是 128kb、256kb、512kb,貌似这里更小,是64kb
  3. 每个块里边包含很多页,老的 nandflash ,页大小是 256 Bytes、512Bytes,这类被称作 small block,地址周期只有 4 个。常见的nandflash,页大小多数是 2k Bytes,被称作 big block,地址周期 5 个,更新的 nandflash 页大小是 4k Bytes,这里的这个芯片,页大小是 2k Bytes,属于 big block。
  4. 这个芯片的写操作是以页为单位的擦除是以块为单位的
  5. 在一个块中,对每一页的编程必须是顺序的,比如,一个块中有128个页,那么你只能先对 Page0 编程,再对 Page1 编程 ...
  6. 为了能让 nandflash 作为启动介质,s3c2440 内部集成了4k 的 sram ,当从 nand 启动的时候,nandflash 代码的前 4k 空间会被赋值到 s3c2440 内部,然后从内部的 sram 开始启动。
  7. s3c2440 硬件产生 ECC 校验码。

1.3寻址方式

   NAND的读写的最小单位为Page:
小页:


大页:(K9F2G08U0C共有2048个Block(块), 每个Block含有 64 Page(页),所以我们这款芯片为大页读写)



列地址: 进行 Block 和 Page 寻址

行地址: 进行 Page 内寻址

如何区分Nandflash读写是大页还是小页点我!


2. 软件部分:


由于 s3c2440 内部有nand 的控制器,去查看2440的数据手册,自己编写时序操作程序不是明智的选择,正确的方式是一步一步配置好 s3c2440 的 nandflash 控制器,然后对应查看K9F2G08U0C的芯片手册看是否符合要求!
在此以读Nandflash为例子来配置寄存器。

2.1 初始化部分:

设置好时序中的几个间隔时间:
从 s3c2440 芯片手册上可以知道:
    图1


对于 CLE/ALE 上的时序,我们需要设置 TACLS,TWRPH0,TWRPH1,这几个都在 NFCONF 寄存器里。

寄存器

地址

R/W

描述

复位值

NFCONF

0x4E000000

R/W

Nandflash 的配置寄存器

0x0000100X

 

NFCONF

Bit

描述

初始值

Reserved

[15:14]

保留

-

TACLS

[13:12]

CLE & ALE duration setting value (0~3)

Duration =  HCLK x TACLS

01

...

...

...

...

TWRPH0

[10:8]

TWRPH0 duration setting value (0~7)

Duration =  HCLK x ( TWRPH0 + 1 )

000

...

...

...

...

TWRPH1

[6:4]

TWRPH1 duration setting value (0~7)

Duration =  HCLK x ( TWRPH1 + 1 )

000

从这里之后的几个都是由硬件决定(就是上下拉)的不需要软件来管。


 原理图中的这个地方设置的是上表中 TWRPH1 之后的位:


CCON = 1; // 支持 1k 字节或 2k 字字节每页的NAND flash存储器
GPG13 = 1; // 每页 2k 字节
GPG14 = 1; // 5个地址周期
GPG15 = 0; // 8位总线

要 求上边的 TACLS、TWRPH0、TWRPH1 的值:
  1. 我们假设 HCLK 为 最大值 136MHz ,稍作分析可得,我们实际的HCLK肯定要小很多,但是如果最大值满足那么小一点的HCLK肯定满足条件!则 HCLK 的周期是 1/136MHz = 7.4ns<flash时钟来自于HCLK后面讲时钟会提到>
  2. 查看 nandflash 的数据手册,找到跟时间相关的时序图和时间:
        时间表

        时序:
找一个跟上边红色数字 图1 中都有的一张时序图:

我们把图一也拿过来
    图1

则 
TACLS 时间是 tCLS -tWP,查 时间表 得到 12ns -12ns = 0ns
    根据寄存器中描述的计算公式:Duration =  HCLK x TACLS =>  0ns = 7.4ns x TACLS  => TACLS = 0

TWRPH0 的时间是 tWP ,查 时间表 得到 12ns 
    根据寄存器中描述的计算公式:Duration =  HCLK x ( TWRPH0 + 1 )  =>  12ns = 7.4ns x (TWRPH0 + 1)  => TWRPH0 = 1.6 ,由于他的取值范围是 (0~7) ,并且,时间表中的时间是最小能识别的时间,那我们取TWRPH0 =3

TWRPH1 的时间是 tclh = 5ns
    根据寄存器中描述的计算公式:Duration =  HCLK x ( TWRPH1 + 1 ) => 5ns = 7.4ns x (TWRPH1 + 1) => TWRPH1 = 0 即定能满足
[cpp] view plain copy
 print?
  1. #define NFCONF  (*((volatile unsigned long *)0x4E000000))  
  2.   
  3. void nand_init(void )  
  4. {  
  5.     #define TACLS   0  
  6.     #define TWRPH0  3  
  7.     #define TWRPH1  0  
  8.   
  9.     /* 设置时序 */  
  10.     NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);  
  11.     /* 使能 nandflash 控制器,初始化ECC,关片选 */  
  12.     NFCONT = (1<<4)|(1<<1)|(1<<0);  
  13. }  

2.2 芯片的选择和禁止(让芯片操作 CE 引脚):

[cpp] view plain copy
 print?
  1. #define NFCONT  (*((volatile unsigned long *)0x4E000004))  
  2.   
  3. void nand_select(void )  
  4. {  
  5.     NFCONT &= ~(1<<1);  
  6. }  
  7.   
  8. void nand_deselect(void )  
  9. {  
  10.     NFCONT |= (1<<1);  
  11. }  

2.3 写命令和写地址

[cpp] view plain copy
 print?
  1. // 写命令 注意是八位的命令  
  2. #define NFCMMD (*((volatile unsigned char *)0x4E000008))  
  3.   
  4. void nand_cmd(unsigned char cmd)  
  5. {  
  6.  volatile int i;  
  7.  NFCMMD = cmd;  
  8.  for (i = 0; i<10; i++); // 延时一段时间  
  9. }  

  1. // 写地址   (大页)
  2. #define NFADDR (*((volatile unsigned char *)0x4E00000C))  
  3. #define NAND_SECTOR_SIZE    2048  
  4. #define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE_LP - 1)  
  5.   
  6. void nand_addr(unsigned int addr)  
  7. {  
  8. // unsigned int col = addr % 2048;  
  9. // unsigned int page = addr / 2048;  
  10.  col = addr & NAND_BLOCK_MASK;  
  11.  page = addr / NAND_SECTOR_SIZE;  
  12.  volatile int i;  
  13.  NFADDR = col & 0xff;                /* Column Address A0~A7 */  
  14.  for (i = 0; i<10; i++);  
  15.  NFADDR = (col>>8) & 0x0f;       /* Column Address A8~A11 */  
  16.  for (i = 0; i<10; i++);  
  17.  NFADDR = page & 0xff;            /* Row Address A12~A19 */  
  18.  for (i = 0; i<10; i++);  
  19.  NFADDR = (page>>8) & 0xff;   /* Row Address A20~A27 */  
  20.  for (i = 0; i<10; i++);  
  21.  NFADDR = (page>>16) & 0x03;  /* Row Address A28~A29 */  
  22.  for (i = 0; i<10; i++);  
  23. }  



对程序的解释:
 flash芯片的手册上有对于大页 flash 的访问 各个周期传递的位:

因此上边的命令 NFADDR = ... 就不难理解了。
至于,各个周期间的延时:
从flash芯片的数据手册上知道:

对于 I/O 引脚上的数据进行采集是在 WE 的上升沿进行的,因此, 每两个周期的间隔至少应该大于一个 tDS = 12ns,而对 flash 他的时钟来自 HCLK =136MHz,即使是单周期指令,也要 1/136MHz=7.4ns,因此,要延时一段时间。

2.4 读数据:

flash 芯片上:

flash 芯片上:



[cpp] view plain copy
 print?
  1. #define NFSTAT (*((volatile unsigned char *)0x4E000020))  
  2. #define NFDATA (*((volatile unsigned char *)0x4E000010))  
  3. void nand_wait_teady(void)  
  4. {  
  5.     while(!(NFSTAT & 1))  
  6.          for(i = 0; i < 10; i++);  
  7. }  
  8.   
  9. unsigned char nand_data(void)  
  10. {  
  11.     return NFDATA;  
  12. }  
  13. /* 
  14. * 参数的含义: 从NAND Flash位置start_addr开始,将数据复制到SDRAM地址buf处,共复制size字节
  15. */  
  16. void nand_read(unsignedchar* buf, unsignedlong start_addr, int size)
  17. {  
  18.     int i,j;  
  19.   if((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)){
  20. return;
  21.    }
  22.     
  23.    nand_select_chip(); //选中芯片  
  24.    
  25.    for(i=start_addr; i < (start_addr + size);) 
  26.     {  
  27.         write_cmd(0x00); // 发出读命令 00h  
  28.         write_addr(i); // 发送读的地址  
  29.         write_cmd(0x30); // 发出读命令 30h  
  30.         nand_wait_ready(); // 等待不忙  
  31.   
  32.         for(j=0; j < NAND_SECTOR_SIZE; j++,i++)  
  33.         {  
  34.             *buf = read_data(); // 读数据    
  35.             buf++;  
  36.         }    
  37.     }  
  38.     nand_deselect_ship(); // 取消片选
  39.     return ;  
  40. }  

总结一下:

(1)选中芯片

(2)发送00h

(3)发出地址

(4)发30h

(5)等待就绪

(6)读一页数据

2.5 复位 flash 芯片:

知道了上边的命令的表格,那 复位的实现也就简单了:
[cpp] view plain copy
 print?
  1. void nand_reset(void)  
  2. {  
  3.     nand_select_chip(); // 选中芯片  
  4.     write_cmd(0xff);  
  5.     nand_wait_ready();  
  6.     nand_deselect_chip();  
  7. }  

3.NandFlash操作实例

 

篇幅有限,点击跳转NandFlash 控制器操作实例:读Flash



这篇关于JZ2440的NandFlash控制器的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/760185

相关文章

jmeter之仅一次控制器

仅一次控制器作用: 不管线程组设置多少次循环,它下面的组件都只会执行一次 Tips:很多情况下需要登录才能访问其他接口,比如:商品列表、添加商品到购物车、购物车列表等,在多场景下,登录只需要1次,我们期望的是重复执行登陆后面的接口来做压测,这就和事务相关,例如 事务1: 登录—>添加购物车 事务2: 登录—>购物车列表 事务3: 登录—>商品列表—>添加购物车 … 一、仅一次控制器案例 在

为控制器的方法添加必要参数

前言:做这个系统时,要求每次调用接口时要传操作人、操作人电脑ip、菜单id,然后计入log。本来前端读取到然后加入请求头,后端写入log即可。但是老大要求后端也要把控必传参数,避免前端忘记。所以就写了这个。IOperationFilter 这个是百度知道的。主要用于在Swagger生成的API文档中动态地添加或修改操作(即API接口)的元数据。 用处:可以自动地为 Swagger/OpenAPI

IBM Storwize V7000存储控制器故障节点报错574

背景:由于客户机房搬迁,需要下电迁移设备。该存储自2016年投入生产使用后,从未关过机,已正常运行七八年时间,期间只更换过硬盘,无其他硬件故障。 在GUI界面点击关闭系统后,大概等了40分钟,存储仍未关机,所有硬盘状态灯绿色常亮,面板无报错。到设备后面看控制器的状态,发现node2已经正常关机了,node1仍然在运行,又等了大概20分钟还没有关机,直接将电源线给拔掉了。 再次上电以后,发现

s3c2440---中断控制器

一、概述 S3C2440A 中的中断控制器接受来自 60 个中断源的请求。提供这些中断源的是内部外设,如 DMA 控制器、 UART、IIC 等等。 在这些中断源中,UARTn、AC97 和 EINTn 中断对于中断控制器而言是“或”关系。 当从内部外设和外部中断请求引脚收到多个中断请求时,中断控制器在仲裁步骤后请求 ARM920T 内核的 FIQ 或 IRQ。 仲裁步骤由硬件优先级逻辑决定

【风力发电】基于智能控制器的光伏/风电混合发电系统

摘要 光伏和风力发电因其可再生性和环保性在全球范围内得到了广泛应用。本文提出了一种基于智能控制器的光伏/风电混合发电系统,通过智能控制器对系统的功率输出进行优化管理。实验结果表明,该系统能够在不同的环境条件下高效运行,显著提高了能源利用率和系统稳定性。 理论 光伏/风电混合发电系统结合了太阳能和风能的优势,能够更好地适应不同的气候条件。然而,由于太阳辐射和风速的变化性,这种系统的功率输出

kubernetes里面那些事————控制器

资源-控制器 一,控制器作用二,控制器类型2.1,Deployment:无状态应用部署2.2,DaemonSet:确保所有Node运行同一个pod2.3,StatefulSet:有状态应用部署2.4,Job:一次性任务2.5,CronJob:定时任务2.6,pod2.7,service2.8,replicaset2.9,endpoints 三,控制器yaml应用3.1,Deployment3

C1-2 ABB二次SDK开发——手把手教登录对应的机器人控制器(图片引导操作)登录机器人控制器和刷新机器人列表

1.完成配置后我们开始进行操作 C1-1 ABB二次SDK开发——C#Window窗体-环境配置(带ABB二次开发SDK资源包)-CSDN博客文章浏览阅读95次。3.记住路径,右键C#引用,然后导入ABB.Robotics.Controllers.PC.dll。2.安装资源文件PCABB二次开发的SDK,并打开安装路径。1.新建VSC#的windowfrom项目。4.在框架代码主界面代码中添加。

【unity实战】利用Root Motion+Blend Tree+Input System+Cinemachine制作一个简单的角色控制器

文章目录 前言动画设置Blend Tree配置角色添加刚体和碰撞体代码控制人物移动那么我们接下来调整一下相机的视角效果参考完结 前言 Input System知识参考: 【推荐100个unity插件之18】Unity 新版输入系统Input System的使用,看这篇就够了 Cinemachine虚拟相机知识参考: 【推荐100个unity插件之10】Unity最全的最详细的C

【kubernetes】控制器Statefulset入门及应用

一,概念 为了管理有状态服务(如数据库mysql等)的问题,采用Statefulset来管理 【有状态服务】 StatefulSet是有状态的集合,管理有状态的服务,它所管理的Pod的名称不能随意变化。数据持久化的目录也是不一样,每一个Pod都有自己独有的数据持久化存储目录。比如MySQL主从、Redis集群等。 【无状态服务】 RC、Deployment、DaemonSet都是管理无状

DM8168 ccs5.4 烧写u-boot到nandflash

烧写用到的工具是  nand-flash-writer.out 它的源码路径在 ${EZSDK}/board-support/host-tools/src/nandflash-<version>.tar.gz 解压后导入到ccs进行编译后得到 nand-flash-writer.out。   接着: ①导入8168.gel文件 ②将u-boot.noxip.bin 先存放在电脑中 ③