ARM·Nand Flash的控制

发布者:平和的心态最新更新时间:2015-11-17 来源: eefocus关键字:ARM  Nand  Flash 手机看文章 扫描二维码
随时随地手机看文章
【本章总结】
个人觉得这章内容过于复杂,只需要记住如果nand中4096的程序想要被拷贝出来执行,就把这个代码写进去,红色部分是真正的代码,可以复制过去,直接使用,其他就不做了解了。听了一个小时,这个老师讲的也挺乱的,也没有人能记住这么多东西吧。。。
 
 
 
 
【head.S init.c     main.c       nand.c  Makefile】
代码详解,这里先把一部分代码存放在NAND Flash 地址4096之后,当程序启动后通过NAND Flash控制器将他们读出来、执行。
注意:以前的代码都小于4096,开发板启动后他们被自动复制进“Steppingstone”;
  现在的代码在4096之后,需要控制NAND Flash将他们读出来、执行
【nand.lds】
 
SECTIONS { 
  firtst   0x00000000 : { head.o init.o nand.o}
  second 0x30000000 : AT(4096) { main.o }
 
对于这里,我是这样理解的 。head.o init.o nand.o都放在Nand flash0地址处,0x0000 0000是他的链接地址,也就是放在0x0000 0000处运行;mian.o存放在Nand flash 4096地址处,0x3000 0000是他的链接地址,也就是放在0x3000 0000处运行 
(可能也就是前一阵子看到的链接地址和加载地址的区别)
 
当开发板启动时,前4k的代码被考进SRAM,所以我们需要在SRAM内完成初始化和跳转
 
【head.s】
 
SECTIONS { 
  firtst   0x00000000 : { head.o init.o nand.o}
  second 0x30000000 : AT(4096) { main.o }
} @******************************************************************************
@ File:head.s
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@******************************************************************************       
  
.text
.global _start
_start:
                                            @函数disable_watch_dog, memsetup, init_nand, nand_read_ll在init.c中定义
            ldr     sp, =4096               @设置堆栈 
            bl      disable_watch_dog       @关WATCH DOG
            bl      memsetup                @初始化SDRAM
            bl      nand_init               @初始化NAND Flash
 
                                        @将NAND Flash中地址4096开始的1024字节代码(main.c编译得到)复制到SDRAM中
                                            @nand_read_ll函数需要3个参数:
            ldr     r0,     =0x30000000     @1. 目标地址=0x30000000,这是SDRAM的起始地址
            mov     r1,     #4096           @2.  源地址   = 4096,连接的时候,main.c中的代码都存在NAND Flash地址4096开始处
            mov     r2,     #2048           @3.  复制长度= 2048(bytes),对于本实验的main.c,这是足够了
            bl      nand_read               @调用C函数nand_read
 
            ldr     sp, =0x34000000         @设置栈
            ldr     lr, =halt_loop          @设置返回地址
            ldr     pc, =main               @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转
halt_loop:
            b       halt_loop
 
 
*对于这一串代码,很多都是前面学过的知识,这里我们只关注配置Nand的红色代码
bl  nand_init
*目标地址,源地址,目标长度
    ldr     r0,     =0x30000000     @1. 目标地址=0x30000000,这是SDRAM的起始地址
            mov     r1,     #4096           @2.  源地址   = 4096,连接的时候,main.c中的代码都存在NAND Flash地                                                      址4096开始处
           mov     r2,     #2048           @3.  复制长度= 2048(bytes),对于本实验的main.c,这是足够了
   bl      nand_read               @调用C函数nand_read
这里我们可以跳转到nand_read中可以看一下
 
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;
 
#ifdef LARGER_NAND_PAGE
    if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {
        return ;    
    }
#else
    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return ;    
    }
#endif
 
   
    nand_select_chip();
 
    for(i=start_addr; i < (start_addr + size);) {
     
      write_cmd(0);
 
     
      write_addr(i);
#ifdef LARGER_NAND_PAGE
      write_cmd(0x30);
#endif
      wait_idle();
 
#ifdef LARGER_NAND_PAGE
      for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {
#else
  for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
#endif
          *buf = read_data();
          buf++;
      }
    }
 
 
 
【nand.c】
 
#define LARGER_NAND_PAGE
 
#define GSTATUS1        (*(volatile unsigned int *)0x560000B0)
#define BUSY            1
 
#define NAND_SECTOR_SIZE    512
#define NAND_BLOCK_MASK     (NAND_SECTOR_SIZE - 1)
 
#define NAND_SECTOR_SIZE_LP    2048
#define NAND_BLOCK_MASK_LP     (NAND_SECTOR_SIZE_LP - 1)
 
typedef unsigned int S3C24X0_REG32;
 
 
typedef struct {
    S3C24X0_REG32   NFCONF;
    S3C24X0_REG32   NFCMD;
    S3C24X0_REG32   NFADDR;
    S3C24X0_REG32   NFDATA;
    S3C24X0_REG32   NFSTAT;
    S3C24X0_REG32   NFECC;
} S3C2410_NAND;
 
typedef struct {
    S3C24X0_REG32   NFCONF;
    S3C24X0_REG32   NFCONT;
    S3C24X0_REG32   NFCMD;
    S3C24X0_REG32   NFADDR;
    S3C24X0_REG32   NFDATA;
    S3C24X0_REG32   NFMECCD0;
    S3C24X0_REG32   NFMECCD1;
    S3C24X0_REG32   NFSECCD;
    S3C24X0_REG32   NFSTAT;
    S3C24X0_REG32   NFESTAT0;
    S3C24X0_REG32   NFESTAT1;
    S3C24X0_REG32   NFMECC0;
    S3C24X0_REG32   NFMECC1;
    S3C24X0_REG32   NFSECC;
    S3C24X0_REG32   NFSBLK;
    S3C24X0_REG32   NFEBLK;
} S3C2440_NAND;
 
 
typedef struct {
    void (*nand_reset)(void);
    void (*wait_idle)(void);
    void (*nand_select_chip)(void);
    void (*nand_deselect_chip)(void);
    void (*write_cmd)(int cmd);
    void (*write_addr)(unsigned int addr);
    unsigned char (*read_data)(void);
}t_nand_chip;
 
static S3C2410_NAND * s3c2410nand = (S3C2410_NAND *)0x4e000000;
static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;
 
static t_nand_chip nand_chip;
 
void nand_init(void);
void nand_read(unsigned char *buf, unsigned long start_addr, int size);
 
static void nand_reset(void);
static void wait_idle(void);
static void nand_select_chip(void);
static void nand_deselect_chip(void);
static void write_cmd(int cmd);
static void write_addr(unsigned int addr);
static unsigned char read_data(void);
 
static void s3c2410_nand_reset(void);
static void s3c2410_wait_idle(void);
static void s3c2410_nand_select_chip(void);
static void s3c2410_nand_deselect_chip(void);
static void s3c2410_write_cmd(int cmd);
static void s3c2410_write_addr(unsigned int addr);
static unsigned char s3c2410_read_data();
 
static void s3c2440_nand_reset(void);
static void s3c2440_wait_idle(void);
static void s3c2440_nand_select_chip(void);
static void s3c2440_nand_deselect_chip(void);
static void s3c2440_write_cmd(int cmd);
static void s3c2440_write_addr(unsigned int addr);
static unsigned char s3c2440_read_data(void);
 
 
static void s3c2410_nand_reset(void)
{
    s3c2410_nand_select_chip();
    s3c2410_write_cmd(0xff);  // 复位命令
    s3c2410_wait_idle();
    s3c2410_nand_deselect_chip();
}
 
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);
    for(i=0; i<10; i++);    
}
 
static void s3c2410_nand_deselect_chip(void)
{
    s3c2410nand->NFCONF |= (1<<11);
}
 
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;
}
 
 
static void s3c2440_nand_reset(void)
{
    s3c2440_nand_select_chip();
    s3c2440_write_cmd(0xff);  // 复位命令
    s3c2440_wait_idle();
    s3c2440_nand_deselect_chip();
}
 
static void s3c2440_wait_idle(void)
{
    int i;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT;
    while(!(*p & BUSY))
        for(i=0; i<10; i++);
}
 
static void s3c2440_nand_select_chip(void)
{
    int i;
    s3c2440nand->NFCONT &= ~(1<<1);
    for(i=0; i<10; i++);    
}
 
static void s3c2440_nand_deselect_chip(void)
{
    s3c2440nand->NFCONT |= (1<<1);
}
 
static void s3c2440_write_cmd(int cmd)
{
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD;
    *p = cmd;
}
 
static void s3c2440_write_addr(unsigned int addr)
{
    int i;
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->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++);
}
 
[page]
static void s3c2440_write_addr_lp(unsigned int addr)
{
int i;
volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFADDR;
int col, page;
 
col = addr & NAND_BLOCK_MASK_LP;
page = addr / NAND_SECTOR_SIZE_LP;
*p = col & 0xff;
for(i=0; i<10; i++);
*p = (col >> 8) & 0x0f;
for(i=0; i<10; i++);
*p = page & 0xff;
for(i=0; i<10; i++);
*p = (page >> 8) & 0xff;
for(i=0; i<10; i++);
*p = (page >> 16) & 0x03;
for(i=0; i<10; i++);
}
 
 
static unsigned char s3c2440_read_data(void)
{
    volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFDATA;
    return *p;
}
 
 
static void nand_reset(void)
{
    nand_chip.nand_reset();
}
 
static void wait_idle(void)
{
    nand_chip.wait_idle();
}
 
static void nand_select_chip(void)
{
    int i;
    nand_chip.nand_select_chip();
    for(i=0; i<10; i++);
}
 
static void nand_deselect_chip(void)
{
    nand_chip.nand_deselect_chip();
}
 
static void write_cmd(int cmd)
{
    nand_chip.write_cmd(cmd);
}
static void write_addr(unsigned int addr)
{
    nand_chip.write_addr(addr);
}
 
static unsigned char read_data(void)
{
    return nand_chip.read_data();
}
 
 
void nand_init(void)
{
#define TACLS   0
#define TWRPH0  3
#define TWRPH1  0
 
   
    if ((GSTATUS1 == 0x32410000) || (GSTATUS1 == 0x32410002))
    {
        nand_chip.nand_reset         = s3c2410_nand_reset;
        nand_chip.wait_idle          = s3c2410_wait_idle;
        nand_chip.nand_select_chip   = s3c2410_nand_select_chip;
        nand_chip.nand_deselect_chip = s3c2410_nand_deselect_chip;
        nand_chip.write_cmd          = s3c2410_write_cmd;
        nand_chip.write_addr         = s3c2410_write_addr;
        nand_chip.read_data          = s3c2410_read_data;
 
        s3c2410nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);
    }
    else
    {
        nand_chip.nand_reset         = s3c2440_nand_reset;
        nand_chip.wait_idle          = s3c2440_wait_idle;
        nand_chip.nand_select_chip   = s3c2440_nand_select_chip;
        nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;
        nand_chip.write_cmd          = s3c2440_write_cmd;
#ifdef LARGER_NAND_PAGE
        nand_chip.write_addr         = s3c2440_write_addr_lp;
#else
nand_chip.write_addr = s3c2440_write_addr;
#endif
        nand_chip.read_data          = s3c2440_read_data;
 
        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
       
        s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
    }
    
   
    nand_reset();
}
 
 
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
    int i, j;
 
#ifdef LARGER_NAND_PAGE
    if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) {
        return ;    
    }
#else
    if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {
        return ;    
    }
#endif
 
   
    nand_select_chip();
 
    for(i=start_addr; i < (start_addr + size);) {
     
      write_cmd(0);
 
     
      write_addr(i);
#ifdef LARGER_NAND_PAGE
      write_cmd(0x30);
#endif
      wait_idle();
 
#ifdef LARGER_NAND_PAGE
      for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) {
#else
 for(j=0; j < NAND_SECTOR_SIZE; j++, i++) {
#endif
          *buf = read_data();
          buf++;
      }
    }
 
   
    nand_deselect_chip();
    
    return ;
}
 
这一长串红色的代码也就是Nand Flash的初始化,我们可以仔细的分析一下Nand的控制寄存器
再看代码,从head.s中也就跳转到了nand.c中的灰色部分 ;
1)S3C2410和S3C2440的一个判断
2)定义了一个结构体
 {
        nand_chip.nand_reset         = s3c2440_nand_reset;
        nand_chip.wait_idle          = s3c2440_wait_idle;
        nand_chip.nand_select_chip   = s3c2440_nand_select_chip;
        nand_chip.nand_deselect_chip = s3c2440_nand_deselect_chip;
        nand_chip.write_cmd          = s3c2440_write_cmd;
#ifdef LARGER_NAND_PAGE
        nand_chip.write_addr         = s3c2440_write_addr_lp;
#else
nand_chip.write_addr = s3c2440_write_addr;
#endif
        nand_chip.read_data          = s3c2440_read_data;
 
        s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4);
       
        s3c2440nand->NFCONT = (1<<4)|(1<<1)|(1<<0);
 }
*上面定义了结构体,右边一列都是s3c2440中可以调用的函数 ;
*在设置时序中:【NFCONF】寄存器
使能NAND Flash控制器,初始化ECC,禁止片选 :【NFCONT】寄存器
(我觉得了解一下就好了,还真的去看时序啊,那个老师都没说的清楚,估计是默认值)
【ARM·Nand <wbr>Flash的控制】
 
【NFCONF】
【ARM·Nand <wbr>Flash的控制】
【ARM·Nand <wbr>Flash的控制】
 
【NFCONT】
 
【ARM·Nand <wbr>Flash的控制】
 
关键字:ARM  Nand  Flash 引用地址:ARM·Nand Flash的控制

上一篇:ARM·MMU
下一篇:ARM·系统时钟(MPLL,UPLL)

推荐阅读最新更新时间:2024-03-16 14:39

三星增产重心为DRAM、NAND明年续旺?
  明年NAND flash究竟是涨是跌,多空激烈争辩。摩根士丹利(大摩)唱衰NAND flash的报告,开了第一枪 。 如今IHS Markit也跟进,预测明年NAND将供过于求。 但是美系外资力排众议,高喊各方错看,明年NAND供应将持续吃紧。下面就随网络通信小编一起来了解一下相关内容吧。   韩媒BusinessKorea 5日报导(见此),IHS Markit报告预估,明年全球NAND flash供给将提高39.6%、至2,441亿GB。 其中 三星 电子将带头增产,预料供给将增39%至879亿GB。 与此同时,明年全球NAND需求提高36.7%至2,424亿GB,供给超出需求17亿GB,供给过剩比率约为0.7%。   
[网络通信]
简述ARM微处理器的隧道照明智能控制器
引 言 隧道是高速公路的重要组成部分,隧道照明系统是车辆能够安全地进入、通过和离开隧道区域必不可少的基本保证。目前长隧道的照明分为入口段、过渡段、基本段、出口段,每段的灯具按功能又分为应急灯、全日灯和加强灯三种。应急灯除在停电时用作应急照明外还兼作全日照明,全日灯24小时不间断工作,加强灯根据洞口不同的亮度来开启。 隧道内不同区域的亮度要求各不相同,它们和洞外亮度、交通流量、洞内废气的多少、行车速度、灯具的养护周期等诸多因素有关,甚至与路面的材料和洞壁的装修材料有关。这些灯的控制目前基本上是靠开关照明回路来进行控制的。一般隧道都有七八个照明控制回路,建设投资大,施工难度高,隧道开通后管理者仅能在有限的回路里进行控制,很难兼顾到
[单片机]
简述<font color='red'>ARM</font>微处理器的隧道照明智能控制器
高通发首款VR/AR芯片XR1 可大幅提高产品性价比
目前,无论是VR(虚拟现实)又或是AR(增强现实),如果它们无法变得更流畅或者更便宜,那么它们可能永远都无法流行起来!高通公司却试图解决这一窘况。近日,高通推出了一款名为“Snapdragon XR1”(骁龙XR1)的全新移动平台,其主要目的在于帮助AR/VR产品生产者开发出更加实惠的可穿戴设备,并且,该芯片还可能用于人工智能领域产品的开发。 资料显示,Snapdragon XR1将采用高通的异构计算架构,内部结构包括基于ARM的多核 CPU、向量处理器、图形处理器(GPU)等,其他关键特性还有诸如 XR 软件服务层、机器学习、骁龙 XR 软件开发包(SDK)以及高通的连接与安全技术。 根据高通公司发布的消
[手机便携]
高通发首款VR/AR芯片XR1 可大幅提高产品性价比
扩大SoC工具利用 ARM拟收购Duolog
ARM正与爱尔兰 IP 整合工具供应商Duolog Technologies洽谈收购事宜。 过去一年来,两家公司持续其合作夥伴关系,为今年即将推出的ARM CoreLink与CoreSight产品共同开发除错与追踪工具。ARM公司系统与软体部门总经理James McNiven表示,这些工具将提供一种图形化介面,为多核心以及未来大规模的多核心SoC实现除错与追踪功能的配置与自动化。 「我们的CoreLink在目前的一个SoC中可互连多达48核心的作业,未来的SoC还会变得更加复杂,」McNiven,「而随着事情变得更加复杂,我们瞭解到必须让合作夥伴易于制造低风险的SoC。」 当今的8核心ARM SoC必须配置除
[单片机]
使用J-Link ARM烧录FLASH
//===================================================================== //TITLE: // 使用J-Link ARM烧录FLASH //AUTHOR: // norains //DATE: // February 21-September-2010 //Environment: // J-Link ARM //===================================================================== 如果大家使用的是MDK开发环境的话,并且选择调试的工具是J-Link,那么当我们点击deb
[单片机]
使用J-Link <font color='red'>ARM</font>烧录<font color='red'>FLASH</font>
Arm造芯速度有多快:每秒钟产出842个
作为上一季度报告的一部分,Arm公司透露,他们的处理器设计的受欢迎程度继续成倍增长。制造业合作伙伴已经记录了基于Arm设计的67亿颗芯片的出货量,这大约相当于每秒钟生产842颗芯片,这是一个前所未有的速度。 Arm也毫无疑问是世界上最高效的处理器设计者:比如的Mali GPU系列发展至今只包含9个型号,但自2015年以来一直是出货量第一的GPU。如果Arm只卖他们最受欢迎的产品--Cortex-M CPU系列,那么他们仍然是世界上最大的处理器设计者,因为仅上个季度,基于Cortex-M架构设计的出货量就有44亿颗。 Cortex-M设计的流行并不神秘,Arm的广泛成功也不神秘。在物联网领域,最实惠、最高效的选择就是Cor
[嵌入式]
<font color='red'>Arm</font>造芯速度有多快:每秒钟产出842个
英特尔加紧收购挑战ARM
     8月底英特尔连续启动两笔收购案,78亿美元收购杀毒软件厂商McAfee,19亿美元收购德国芯片巨头英飞凌的手机芯片部门,外界普遍认为这是英特尔入侵移动计算领域的再一次尝试,英特尔在手机芯片领域最大的竞争对手是英国ARM公司,目前市面上95%以上的智能手机使用ARM架构的处理器,此外包括iPad在内的已上市和规划中绝大部分平板电脑也会使用ARM架构的处理器。打败ARM意味着得到一个预计规模100亿美元的市场。     总部在英国剑桥的ARM,前身是Acorn Computer,1985年第一个ARM处理器ARM1诞生,次年又推出了ARM2。ARM2具有32位资料总线、26位寻址空间,采用了精简指令集(RISC,Redu
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved