(1)流水灯

  1>我们来看原理图

        

      

     

     

   2>datasheet

 

      

   

      

     

  3>leds.c

      

     #define GPFCON  (*(volatile unsigned long *)0x56000050)  //address

     #define GPFDAT  (*(volatile unsigned long *)0x56000054)

  

     #define GPF4_reset (3<<(4*2))

     #define GPF5_reset (3<<(5*2))

     #define GPF6_reset (3<<(6*2)) //reset

 

     #define GPF4_out  (1<<(4*2))

     #define GPF5_out  (1<<(5*2))

     #define GPF6_out  (1<<(6*2))//output

     void Delay_ms(volatile unsigned long ms);

     int main(void)

 {

   GPFCON &=~(GPF4_reset | GPF5_reset | GPF6_reset);

   GPFCON |= (GPF4_out | GPF5_out | GPF6_out);

     

   while(1)

 {

    GPFDAT &=~(1<<4);

    Delay_ms(30000);

    GPFDAT |=(1<<4);//led1

   

    GPFDAT &=~(1<<5);

    Delay_ms(30000);

    GPFDAT |=(1<<5);//led2

    GPFDAT &=~(1<<6);

    Delay_ms(30000);

    GPFDAT |=(1<<6);//led3

   return 0;

}

     void Delay_ms(volatile unsigned long ms)

{

   for(; ms>0; ms--);

}

 

  (2)由于我们的程序所占用的空间会出现大于s3c2440的cpu的sram的空间,所以内存无法满足我们的需求,就需要在片外内存中进行运行。这里通过一个链接脚本将一部分程序放在nand flash的前4k的地方,将另一部分放在nand flash 的4k以后,这样的话,我们将nand flash的4K以后的程序拷贝到sram中进行运行就可以的。

     

  在开发板在nand flash模式下启动,开发板只能将前4K的程序拷贝到sram中运行。

  链接脚本:nand.lds

   SECTION{

     first   0x00000000  : {nand.o init.o crt.o}

     second  0x30000000  : AT(4096) {leds.o}

}

 (3) nand.c

    

   #define  LANGE_PAGE

   typedef unsigned int  uint32;

   //s3c2440控制寄存器

  typedef struct{

     uint32  NFCONF;  //nand flash 配置寄存器

     uint32  NFCONT;  //nand flash 控制寄存器(s3c2410没有此寄存器)

     uint32  NFCMMD;  //nand flash 命令寄存器

     uint32  NFADDR;  //nand flash 地址寄存器

     uint32  NFDATA;  //nand flash 数据寄存器

     uint32  NFMECCD0; 

     uint32  NFMECCD1;

     uint32  NFSECCD;

     uint32  NFSTAT;  //状态寄存器

     uint32  NFESTAT0;

     uint32  NFESTAT1;

     uint32  NFMECC0;

     uint32  NFMECC1;

     uint32  NFSECC;

     uint32  NFSBLK;

     uint32  NFEBLK;

}s3c2440_NAND;

  

   //s3c2410寄存器

  typedef struct{

    

    uint32  NFCONF;

    uint32  NFCMD:

    uint32  NFADDR;

    uint32  NFDATA;

    uint32  NFSTAT;

    uint32  NFECC;

}s3c2410_NAND;

  typedef struct{

    void (*nand_reset)(void); //复位

    void (*nand_select_chip)(void);//片选信号

    void (*write_cmd)(unsigned int cmd); //写命令

    void (*nand_wait)(void);

    void (*write_addr)(unsigned int addr);//写地址

    unsigned char (*read_data)(void);//读地址

    void (*nand_deselect_chip)(void);//取消片选信号,节能

}t_nand_chip;

   t_nand_chip  nand_chip;

   s3c2440_NAND * s3c2440_nand =(s3c2440_NAND*)0x4e000000;

   s3c2410_NAND * s3c2410_nand =(s3c2410_NAND*)0x4e000000;  //NFCONF的地址0x4e000000

   

   void s3c2410_nand_select_chip(void)

  {

    int i;

    s3c2410_nand->NFCONF &=~(1<<11);  //nFCE==0片选

    for(i=0;i<10.i++); //等待

}

   

   void s3c2410_write_cmd(unsigned int cmd)

 {

     volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFCMD;

     *p=cmd;

}

  void s3c2410_nand_wait(void)

 {

     int i;

     volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFSTAT;

     while(!(*p & 1)); //是否忙碌   //1--ready  0--busy

     

     for(i=0;i<10;i++);

}

  void s3c2410_write_addr(unsigned int addr)

 {

     int i;

     volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFADDR;

     *p=addr&0xff;  /*A0-A7 */

     for(i=0;i<10;i++);

     *p=(addr>>9)&0xff;/*A9-A16 */

     for(i=0;i<10;i++);

     *p=(addr>>17)&0xff; /*A17-A24 */

     for(i=0;i<10;i++);

     *p=(addr>>25)&0x01; //A25

     for(i=0;i<10;i++);

}

  unsigned char s3c2410_read_data(void)

 {

     volatile unsigned char *p =(volatile unsigned char *)s3c2410_nand->NFDATA;

     return *p;

}

  void s3c2410_nand_deselect_chip(void)

 {

     s3c2410_nand->NFCONF |=(1<<11);

 }

  void s3c2410_nand_reset(void)

  {

     s3c2410_nand_select_chip();

     s3c2410_write_cmd(0xff);  //针对不同的nand flash 对应的nand falsh所要求nand控制器发出的命令有所不同 

     s3c2410_nand_wait();

     s3c2410_nand_deselect_chip();

//s3c2440

  void s3c2440_nand_select(void)

  {

     int i;

     s3c2440_nand->NFCONT &=~(1<<1);

     for(i=0;i<10;i++);

}

  void s3c2440_write_cmd(unsigned int cmd)

 {

     volatile unsigned char *p =(volatile unsignd char *)s3c2440_nand->NFCMMD;

     *p =cmd;

 }

  void s3c2440_nand_wait(void)

  {

     int i;

     volatile unsignd char *p=(volatile unsigned char *)s3c2440_nand->NFSTAT;

     while(!(*p & 1)); //判断是否忙碌

     for(i=0;i<10;i++);

}

  void s3c2440_write_addr(unsigned int addr)//小页--521byte (K9F1208U0M)

  {

     int i;

     volatile unsigned char *p=(volatile unsigned char *)s3c2440_nand->NFADDR;

     *p=addr&0xff;     //A0-A7共8根线,可寻址2^8=256byte --半页(通过不同的命令 00h--上半页,01h--下半页)

     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)&0x01;  //A9-A25 共17根线,可寻址 2^17=2^7k=4(层)*1024(块)*32(页)=2^7k page

     for(i=0;i<10;i++);

}

    

   void s3c2440_write_addr_lp(unsigned int addr)//大页--2K(512*4)(K9F2G08x0A)

 {

     int i;

     int col,row;//col分两次,row分三次发送

     volatile unsigned char *p = (volatile unsigned char *)s3c2440->NFADDR;

     col=addr &(2048-1);  //addr & (11111111111)--取低11位

     row=addr/2048;   //取高位 --(2048==一页的大小)

     *p=col &0xff; /* A0-A7*/

     for(i=0;i<10;i++);

     *p=col & 0x0f;  /* A8-A11*/  --A0==A11共12根线,可寻空间2^12=2*2K,而一页是1K,留有余量,A11用来访问spare区域,也就是      for(i=0;i<10;i++);             -- oob区域用来存放校验信息, spare区域并不在编址范围内,需要使用A11控制访问

     *p=row & 0xff; /* A12-A19*/

     for(i=0;i<10;i++);

     *p=row & 0xff; /* A20-A27*/

     for(i=0;i<10;i++);

     *p=row & 0xff;  /* A28-A29*/  --A12==A28共17根线,可寻空间2^18=2^8k=2(层)*1024(块)*64(页)=2^7k page,同时留有                                    --余量,用来兼容大容量flash

}

    

unsigned char s3c2440_read_data(void)

 {

     volatile unsigned char *p=(volatile unsigned char *)s3c2440_nand->NFDATA;

     return 0;

 } 

  void s3c2440_nand_deselect_chip(void)

 {

     s3c2440_nand->NFCONT |=(1<<1);

}

  void s3c2440_nand_reset(void)

 {

     s3c2440_nand_select_chip();

     s3c2440_write_cmd(0xff); 

     s3c2440_nand_wait();

     s3c2440_nand_deselect_chip();

 }

GSTATUS1是芯片的ID,对于不同的芯片有对应的ID,s3c2440的ID是0x32440001,s3c2410的ID是0x32410000或0x32410002

   s3c2440的ID:

 

 

   s3c2410的ID:

   

  //nand初始化

  void nand_init(void)

 {

     #define  TACLS    0

     #define  TWRPH0   3

     #define  TWRPH1   0

   if((GSTATUS1==0x32410000)||(GSTATUS1==0x32410002)) //s3c2410

    {

       nand_chip.nand_reset =s3c2410_nand_reset;

       nand_chip.nand_select_chip =s3c2410_nand_select_chip;

       nand_chip.write_cmd =s3c2410_write_cmd;

       nand_chip.nand_wait =s3c2410_nand_wait;

       nand_chip.write_addr =s3c2410_write_addr;

       nand_chip.read_data =s3c2410_read_data;

       nand_chip.nand_deselect_chip =s3c2410_nand_deselect_chip;

       

       

       //使能nand flash控制器

       //初始化ECC

       //禁止片选信号

       //设置时序

       s3c2410_nand->NFCONF = (1<<15)|(1<<12)|(1<<11)|(TACLS<<8)|(TWRPH0<<4)|(TWRPH1<<0);

    }

   else                   //s3c2440

    {

       nand_chip.nand_select_chip =s3c2440_nand_select_chip;

       nand_chip.write_cmd =s3c2440_write_cmd;

       nand_chip.nand_wait =s3c2440_nand_wait;

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

       nand_chip.nand_deselect_chip =s3c2440_nand_deselect_chip;

       

   

       //使能nand flash控制器

      //初始化ECC

      //禁止片选信号nFCE 

      s3c2440_nand->NFCONT =(1<<4) | (1<<1) | (1<<0);

      

      

      //设置时序

     s3c2440_nand->NFCONF =(TACLS<<12) | (TWRPH0<<8) | (TWRPH1<<4);

    }

    nand_chip.nand_reset(); //复位nand flash

 }

  void nand_read(unsigned char *buf, unsigned long start_addr, int size)//读数据

 {

    int i,j;

     //地址或长度对齐

     //NAND Flash 每次读操作是以page为单位的,一个page在此是2048byte(不同的NAND Flash的page大小不一定相同),

     //因为2047的二进制表示是11个1, 即11111111111, 一个数如果是2048的倍数,低11bit必须是0, 即 ****00000000000

     //所以把一个数跟2047按位与就可判断它是不是2048的倍数。

    #define LANGE_PAGE  

     if(strat_addr & (2048-1) || (size & (2048-1))) //大页--2048byte

       return;

    #else

       //512的倍数

     if(start_addr & (512-1) || (size & (512-1)) ) //小页--512byte

       return;

     #endif  

    

   //选中芯片

   nand_chip.nand_select_chip();

    

   对于小页而言,进行读取数据需要发命令00h/01h;

   对于大页而言,进行读取数据需要发命令00h ,30h;

   

   小页:

  

   

   

   大页:

   

   for(i=strat_addr;i<(start_addr + size);){

   //发出命令

   nand_chip.write_cmd(0); //00h

   

   //写地址

   nand_chip.write_addr(i);

  

  #ifdef LANGE_PAGE

    nand_chip.write_cmd(0x30);

  #endif

  //等待  

  nand.chip.nand_wait();

  #ifdef LANGE_PAGE

    for(j=0;j<2048;j++,i++){

  #else

    for(j=0;j<512;j++,i++){

  #endif

    //读数据

    *buf=nand_chip.read_data();

     buf++;

  }

 }

   //取消片选信号 

   nand_chip.nand_deselect_chip();

   return ;

 }

  (4)关看门狗和配置存储管理器

   init.c

   

   #define WHITCH_DOG  (*(volatile unsigned long*)0x53000000)

   #define MEM_BASE  0x48000000  //存储管理器寄存器的起始地址

   void disable_watch_dog(void)

   {

     WATCH_DOG = 0;

  

   }  

   void mem_setup(void)

  {

     int i=0;

     unsigned long *p=(unsigned long *)MEM_BASE;

     unsigned long const mem_cfg_val[]={

 

                      0x22011110,

                      0x00000700,

                      0x00000700,

                      0x00000700,

                      0x00000700,

                      0x00000700,

                      0x00000700,

                      0x00018005,

                      0x00018005,

                      0x008C07A3,

                      0x000000B1,

                      0x00000030,

                      0x00000030

      };

    for(i=0;i<13;i++)

     {

       p[i]=mem_cfg_val[i];

     }

  }

  (5)crt.S

  .text

    .global _strat

    _strat:

       ldr sp,=4096

           bl disable_watch_dog

           bl mem_setup

           bl nand_init

    

           ldr r0,=0x30000000 @buf

           mov r1,#4096       @strat_addr

           mov r2,#2048       @size

           bl nand_read

           ldr sp,=0x34000000

           ldr pc,=main

halt_loop:

           b halt_loop

  (6)Makefile 

  objs := crt.o nand.o init.o leds.o

  nand.bin :$(objs)

    arm-linux-ld -Tnand.dis -o nand_elf $^

        arm-linux-objcopy -O binary -S nand_elf $@

        arm-linux-objdump -D -m arm nand_elf > nand.dis

  %.o :%.c

    arm-linux-gcc -Wall -c -O2 -o $@ $<

  %.o :%.S

    arm-linux-gcc -Wall -c -O2 -o $@ $<

  clean:

    rm -f nand.dis nand.bin nand_elf *.o

   

   

Nand flash code的更多相关文章

  1. 嵌入式Linux驱动学习之路(二十三)NAND FLASH驱动程序

    NAND FLASH是一个存储芯片. 在芯片上的DATA0-DATA7上既能传输数据也能传输地址. 当ALE为高电平时传输的是地址. 当CLE为高电平时传输的是命令. 当ALE和CLE都为低电平时传输 ...

  2. s3c2440 移值u-boot-2016.03 第2篇 支持Nand flash启动

    1, 要求:在4K 的代码以内,完成 NOR NAND 类型判断,初始化 NAND 复制自身到 SDRAM ,重定向. 2, 在 /arch/arm/cpu/arm920t/ 文件夹里 添加一个 in ...

  3. ECC校验原理以及在Nand Flash中的应用

         本篇文章主要介绍ECC基本原理以及在Nand Flash中的应用,本文记录自己对ECC校验原理的理解和学习. ECC介绍      ECC,全称为Error Correcting Code, ...

  4. WinCE NAND flash - FAL

    http://blog.csdn.net/renpine/article/details/4572347 http://msdn.microsoft.com/en-US/library/ee48203 ...

  5. STM32学习笔记——FSMC 驱动大容量NAND FLASH [复制链接]

    本文原创于观海听涛,原作者版权所有,转载请注明出处. 近几天开发项目需要用到STM32驱动NAND FLASH,但由于开发板例程以及固件库是用于小页(512B),我要用到的FLASH为1G bit的大 ...

  6. Samsung K9F1G08U0D SLC NAND FLASH简介(待整理)

    Samsung  K9F1G08U0D,数据存储容量为128M,采用块页式存储管理.8个I/O引脚充当数据.地址.命令的复用端口.详细:http://www.linux-mtd.infradead.o ...

  7. NAND FLASH特性说明

    1.NAND FLASH 的特殊性. 1)存在坏块.由于NAND生产工艺的原因,出厂芯片中会随机出现坏块.坏块在出厂时已经被初始化,并在特殊区域中标记为不可用,在使用过程中如果出现坏块,也需要进行标记 ...

  8. NAND FLASH ECC校验原理与实现

    ECC简介 由于NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生产中及使用过程中会产生坏块.为了检测数据的可靠性,在应用NAND  ...

  9. Nand Flash基础知识与坏块管理机制的研究

    概述 Flash名称的由来,Flash的擦除操作是以block块为单位的,与此相对应的是其他很多存储设备,是以bit位为最小读取/写入的单位,Flash是一次性地擦除整个块:在发送一个擦除命令后,一次 ...

随机推荐

  1. sitecore中的两种编辑工具介绍

    在Sitecore中,有两种编辑工具,您可以在其中创建和编辑网站上的内容: 内容编辑器 - 专为熟悉Sitecore及其包含的功能的经验丰富的内容作者而设计的应用程序. 体验编辑器 - 一种直观的编辑 ...

  2. 浏览器页面请求js、css大文件处理

    当页面引用一个比较大的js和css文件时,会出现较大下载延迟,占用带宽的问题,如果一个应用里有很多这样的js或CSS文件,那么就需要优化了. 比如ext-all.js有1.4M,页面引用这个文件,正常 ...

  3. Linux 操作系统镜像下载

    http://mirror.centos.orghttp://mirrors.163.comhttp://mirrors.suhu.com 例如:下载centos http://mirrors.163 ...

  4. 【Alpha版本】冲刺阶段——Day1

    [Alpha版本]冲刺阶段--Day1 阅读目录 Alpha 阶段成员分工及任务量 团队成员贡献值的计算规则 明日任务 今日贡献量 站立式会议 TODOlist [Alpha 阶段成员分工及任务量] ...

  5. Codeforce 835B - The number on the board (贪心)

    Some natural number was written on the board. Its sum of digits was not less than k. But you were di ...

  6. P1192 台阶问题

    递推问题,要用到递推式: 设f(n)为n个台阶的走法总数,把n个台阶的走法分成k类:第1类:第1步走1阶,剩下还有n-1阶要走,有f(n-1)种方法: 第2类:第1步走2阶,剩下还有n-2阶要走,有f ...

  7. vue angular 分别实现分页

    1 vue实现分页组件 paginate组件 <template> <div class="pagination-wrap" v-cloak v-if=" ...

  8. jt项目菜单页面实现

    jt项目菜单页面实现 一. 业务描述: 1) 数据呈现时使用bootstrap中的treeGrid插件(基于jquery实现). bootstrap特点:简洁.直观.强悍.移动设备优先的前端开发框架, ...

  9. 每日linux命令学习-rpm命令

    rpm命令 rpm是一款强大的Redhat软件包管理工具,可创建.安装.查询.验证.升级和卸载每个软件包,软件包是存储文件,包括需要安装的文件和名称.版本.说明等报信息. rpm默认支持7种操作模式, ...

  10. 打印一个浮点值%f和%g

    详见代码 后续或有更新 #include <stdio.h> #include <stdlib.h> int main(int argc, char *argv[]) { fl ...