当前位置:首页 > 单片机 > 单片机
[导读]实验目的:突破4KB的Steppingstone存储空间限制,读取NandFlash中4KB后的代码实现“点灯大法”,借此掌握NandFlash的操作。实验环境及说明:恒颐S3C2410开发板H2410。H2410核心板的NandFlash选用的是三星片上(SOP)K9

实验目的:突破4KB的Steppingstone存储空间限制,读取NandFlash中4KB后的代码实现“点灯大法”,借此掌握NandFlash的操作。

实验环境及说明:恒颐S3C2410开发板H2410。H2410核心板的NandFlash选用的是三星片上(SOP)K9F1208U0M,该NandFlash容量为64MB。

实验思路:开发板上电启动后,自动将NandFlash开始的4K数据复制到SRAM中,然后跳转到0地址开始执行。然后初始化存储控制器SDRAM,调用NandFlash读函数操作把4KB后的点灯代码复制到SDRAM中,跳到点灯代码的入口点实现点灯操作。

知识掌握:NandFlash内部结构、命令字及存储控制器
一、NandFlash内部结构
不同开发板使用的NandFlash的型号可能不一样,本文只是以K9F1208U0M为例做个简单介绍。引脚描述如下所示:

'700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/73_67_af4843899d603e0.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_af4843899d603e0.jpg');" border="0">
NandFlash存储单元结构图如下所示:

'700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/73_67_b53cf1b5e09813b.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_b53cf1b5e09813b.jpg');" border="0" width="700">
Device、 Block和Page之间的关系---1 Device = 4,096 Blocks = 4096*32 Pages = 128K Pages;1 Block = 32 Page;1 Page = 528 Byte = 512 Byte + 16 Byte。其中1 Page中包含有数据寄存器512 Byte和16 Byte的备用位用于ECC校验存储。所以有528 columns * 128K rows(Pages)。1 Page中的512 Byte的数据寄存器又分为两个部分1st 256 Bytes和 2nd 256 Bytes。用于数据存储的单元有 512 Bytes * 32 Pages * 4096 Blocks = 64 MB,用于ECC校验单元有16 Bytes * 32 Pages * 4096 Blocks = 2MB 。
二、NandFlash命令字
操作NandFlash时,先传输命令,然后传输地址,最后进行数据的读/写。K9F1208U0M的命令字如下所示:

'700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://img.21ic.com/21ic_pic/danpianji/73_67_9f90461920e6b01.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_9f90461920e6b01.jpg');" border="0" width="700">
由于寻址需要26bit的地址,该26bit地址通过四个周期发送到NandFlash,如下图所示:

'700')this.width='700';if(this.offsetHeight>'700')this.height='700';" src="http://www.arm79.com/attachment/Mon_1005/73_67_e8c052eed36f8b9.jpg" onclick="if(this.width>=700) window.open('http://www.arm79.com/attachment/Mon_1005/73_67_e8c052eed36f8b9.jpg');" border="0">
Read 1操作:该操作是对512 Bytes * 32 Pages * 4096 Blocks = 64 M的数据寄存器进行寻址。第一个周期发送A7~A0的8bit Column地址,8bit的寻址范围是0~255,只能对1st 256 Bytes部分进行寻址。00h命令是1st 256 Bytes部分寻址。当发送01h命令时,A8将会被置1,此时寻址范围变成了256~511了,所以01h命令是对2nd 256 Bytes部分进行寻址。(*注意:A8在发送00h命令后被清0,在发送01h命令后被置1,并且在发送01h对2nd寻址完毕后,A8会自动清0,指 针会自动地指向1st);第二个周期的A9~A13的5bit是对Page进行寻址(因为1 Block = 32 Pages,5bit的寻址范围是0~31,可以对1 Block里面的所有Page进行寻址)。A14~A25的12bit则是对Block进行寻址,12bit的寻址范围是0~4095,对整个 Device的4096个Blocks进行寻址。Read 2操作:该操作是对16 Bytes * 32 Pages * 4096 Blocks =2MB的备用位(ECC)进行寻址。50h命令为Read2操作,对1 Page里面的后16 Byte寻址。这样,通过四个周期的发送即可对整个Device的所有存储单元进行寻址。
三、NandFlash存储控制器
S3C2410 为简化对NandFlash的操作,提供了一组NandFlash控制器来实现对K9F1208U0M命令字的操作,主要有配置寄存器NFCONF、控制 寄存器NFCONT、命令寄存器NFCMD、地址寄存器NFADDR、数据寄存器NFDATA和状态寄存器NFSTAT。
★NFCONF被用来使 能/禁止NandFlash控制器、使能/禁止控制引脚信号nFCE、初始化ECC、设置NandFlash的时序参数。TACLS、TWRPH0、 TWRPH1---这三个参数控制着NandFlash信号线CLE/ALE与写控制信号new的时序关系。根据NandFlash的Datasheet 中对其最小读/写/控制时间的要求,联系HCLK实际取值一般为100MHz,可以设这三个参数分别为1:3:1个HCLK即可(貌似ViVi中是 1:3:1),这样可以满足其时序要求。
★NandFlash状态寄存器NFSTAT。只用到最低位[0],0:busy;1:ready。
NandFlash 存储控制器根据OM[1:0]位的取值可以工作在①自动启动模式---OM[1:0]=00时,复位之后,NandFlash的最先4KB的代码被复制到 Steppingstone中即内部4KB的SRAM。Steppingstone被映射为Bank0(nGS0),且CPU在此4KB内部SRAM中开 始执行启动代码;②NandFlash模式。

示例代码解析:
★head.S头文件来设置SDRAM,设置SDRAM,将第二部分代码复制到SDRAM,然后跳到SDRAM继续执行。
.equMEM_CTL_BASE, 0x48000000

.text
.global _start
_start:
bldisable_watch_dog @关门喂狗
blmem_control_setup @设置存储控制器
ldr sp, =4096 @设置栈指针,以下C函数调用前需要设好栈
blnand_init@初始化NandFlash
@将NandFlash中地址4096开始的1024字节代码(led.c编译得到)复制到SDRAM中
ldrr0, =0x30000000@目标地址=0x30000000,SDRAM起始地址
movr1, #4096@源地址=4096,连接的时候led代码在4096开始处
movr2, #1024@复制长度=1024,对于本实验的led足够
blnand_read@调用C函数nand_read
ldrlr, =halt_loop @设置返回地址
ldrsp, =0x34000000 @重新设置栈
ldrpc, =main @使用向pc赋值的方法进行跳转到点灯代码
halt_loop:
bhalt_loop
★nand.c文件实现NandFlash的初始化和数据读取
#define BUSY1

typedef unsigned long S3C2410_REG32;//貌似此处定义为unsigned int反汇编结果一样的,也没问题。猜可能是ARM指令直接按32位存储了吧,知道的可以和我说一下!

/* NandFlash结构体 */
typedef struct {
S3C2410_REG32 NFCONF;
......
S3C2410_REG32 NFECC;
}S3C2410_NAND;

static S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;

/* 供外部调用的函数声明 */
void nand_init(void);
void nand_read(unsigned char *buf, unsigned long start_addr, int size);

/* S3C2410的NandFlash处理函数声明 */
static void s3c2410_nand_reset(void);
......
static unsigned char s3c2410_read_data();

/* S3C2410的NandFlash操作函数实现 */

/* 复位 */
static void s3c2410_nand_reset(void)
{
s3c2410_nand_select_chip();
s3c2410_write_cmd(0xff);//发命令字0xFF实现复位操作复位
s3c2410_wait_idle();
s3c2410_nand_deselect_chip();
}

/* 等待NandFlash就绪 */
static void s3c2410_wait_idle(void)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT;
while(!(*p & BUSY))
for(i=0; i<10; i++);
}

/* 发出片选信号 */
static void s3c2410_nand_select_chip(void)
{
int i;
s3c2410nand->NFCONF &= ~(1<<11);//对NFCONF的11位写0,激活NandFlash
for(i=0; i<10; i++);
}

/* 取消片选信号 */
static void s3c2410_nand_deselect_chip(void)
{
s3c2410nand->NFCONF |= (1<<11);//对NFCONF的11位写1,使NandFlash不活动
}

/* 发出命令 */
static void s3c2410_write_cmd(int cmd)
{
volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD;
*p = cmd;
}

/* 发出地址 */
static void s3c2410_write_addr(unsigned int addr)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFADDR;

*p = addr & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 9) & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 17) & 0xff;
for(i=0; i<10; i++);
*p = (addr >> 25) & 0xff;
for(i=0; i<10; i++);
}

/* 读取数据 */
static unsigned char s3c2410_read_data(void)
{
volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA;
return *p;
}

//设置TACLS、TWRPH0、TWRPH1三者的值,貌似ViVi等代码中TWRPH0设为3,不知这样的好处,知道的可以告诉我!
#define TACLS 0
#define TWRPH02
#define TWRPH10
/* 初始化NandFlash */
void nand_init(void)
{
/* 使能NandFlash控制器, 初始化ECC, 禁止片选, 设置时序 */
s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
/* 复位s3c2410 NandFlash */
s3c2410_nand_reset();
}

#define NAND_SECTOR_SIZE512
#define NAND_BLOCK_MASK (NAND_SECTOR_SIZE - 1)
/* 读函数 */
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
int i, j;

if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
return ;/* 地址或长度不对齐 */
}
/* 选中芯片 */
s3c2410_nand_select_chip();
for(i=start_addr; i < (start_addr + size);) {
/* 发出READ0命令 */
s3c2410_write_cmd(0);
/* 写地址*/
s3c2410_write_addr(i);
/*等待*/
s3c2410_wait_idle();
for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
*buf = s3c2410_read_data();
buf++;
}
}
/* 取消片选信号 */
s3c2410_nand_deselect_chip();

return ;
};

本站声明: 本文章由作者或相关机构授权发布,目的在于传递更多信息,并不代表本站赞同其观点,本站亦不保证或承诺内容真实性等。需要转载请联系该专栏作者,如若文章内容侵犯您的权益,请及时联系本站删除。
换一批
延伸阅读

关于使用烧录器烧录Nand Flash,一直都是很多用户头疼的难点,他们强调已经使用了正确的坏块管理方案,也制定了规范的操作流程,但是烧录的良品率还是无法提高,只能每天眼睁睁看着一盘盘&ldqu

关键字: nandflash 烧录器

5月26日消息,据国外媒体报道,集邦咨询半导体研究中心(DRAMeXchange)在周一发布的一份报告中称,今年第一季度,三星在全球NAND Flash市场上的份额为33.3%,与前一季度相比,环比略

关键字: nandflash 三星 芯片

华为作为美光最大的客户之一,美国将华为列入实体名单一事对美光产生了非常严重的影响,美光业绩已经逐渐露出下滑趋势,上周五美光股价大跌近7%,南亚科、华邦电、威刚等存储器企业也纷纷走低。 近期DRAM及N

关键字: DRAM nandflash 美光 芯片

6月24日消息 日前全球第二大闪存供应商东芝位于日本三重县的闪存工厂因地震遭遇断电事故,虽然停电过程非常短,13分钟之后就恢复供电了,但是工厂却一直停产,直到21日上午才恢复,至少停工了5天时间。 根

关键字: nandflash 东芝 台积电 芯片 闪存

Nandflash芯片以其高性价比,大存储容量在电子产品中广泛应用。但是,在此量大质优的应用领域,很多客户却痛苦于批量质量问题:专用工具无法满足量产,量产工具却可能出现极大的不良品率,那么究竟要如何解决呢?

关键字: nandflash 芯片 烧录技巧

一、 首先先来看看核心板的原理图我们发现数据线才有8条,而并没有地址信号,所以该8条线一定是可以传数据,也可以传地址。而地址线肯定又不够,那么,地址肯定又是多次发出的。从datasheet可以看到它要发出5个周期的

关键字: nandflash ok6410 硬件

实验目的:通过串口显示输入的电压值及采集按下触摸屏的(x,y)坐标值借此掌握S3C2410的ADC和触摸屏的使用。实验环境及说明:恒颐S3C2410开发板H2410。H24X0E扩展板上AIN0~AIN1输出悬空,通过外...

关键字: adc 触摸屏 arm开发

它包含7个文件:head.Sinit.cmain.cMakefilenand.cnand.lds我们之前的程序都是在nandflash的前4k放代码,上电后自动拷贝到SRAM中,之后将SRAM中的代码拷贝到SDRAM中。...

关键字: nandflash 裸机程序

注:此文为部分摘录,并且在原文基础上有改动link这几天一直在摸索s3c2410的启动过程,几天的困惑终于在昨天晚上基本解决.下面详细分析一下它的最前面的启动过程.1.在板子上电的一开始,首先自动判断是否是autoboo...

关键字: nandflash s3c2410 启动过程
关闭
关闭