您的位置 首页 培训

ARM开发步步深化之NandFlash 4KB包围

实验目的:突破4KB的Steppingstone存储空间限制,读取NandFlash中4KB后的代码实现“点灯大法”,借此掌握NandFlash的操作。实验环境及说明:恒颐S3C2410开发板

  试验意图:打破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://www.arm79.com/attachment/Mon_1005/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持续履行。

  .equ MEM_CTL_BASE, 0x48000000

  .text

  .global _start

  _start:

  bl disable_watch_dog @关门喂狗

  bl mem_control_setup @设置存储操控器

  ldr sp, =4096 @设置栈指针,以下C函数调用前需求设好栈

  bl nand_init @初始化NandFlash

  @将NandFlash中地址4096开端的1024字节代码(led.c编译得到)仿制到SDRAM中

  ldr r0, =0x30000000 @方针地址=0x30000000,SDRAM开端地址

  mov r1, #4096 @源地址=4096,衔接的时分led代码在4096开端处

  mov r2, #1024 @仿制长度=1024,关于本试验的led满足

  bl nand_read @调用C函数nand_read

  ldr lr, =halt_loop @设置回来地址

  ldr sp, =0x34000000 @从头设置栈

  ldr pc, =main @运用向pc赋值的办法进行跳转到点灯代码

  halt_loop:

  b halt_loop

  ★nand.c文件完成NandFlash的初始化和数据读取

  #define BUSY 1

  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 TWRPH0 2

  #define TWRPH1 0

  /* 初始化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_SIZE 512

  #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 ;

  };

声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/changshang/peixun/243761.html

为您推荐

联系我们

联系我们

在线咨询: QQ交谈

邮箱: kf@86ic.com

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

返回顶部