s3c2440 CPU内置NAND FLASH控制器。相关寄存大器起始地址为0x4e000000。

通过设置NFCONF寄存器,设置NAND FLASH 时序。

通过设置NFCONT寄存器,使能NAND FLASH、初始化ECC等。

代码:


#define GSTATUS1 (*(volatile unsigned int *)0x560000B0) //读此寄存器可以知道CPU芯片型号
#define BUSY 1

#define NAND_SECTOR_SIZE_LP 2048 //大页每页2048字节
#define NAND_BLOCK_MASK_LP (NAND_SECTOR_SIZE_LP - 1) //大页掩码???

typedef unsigned int S3C24X0_REG32;

//s3c2440 NAND FLASH相关寄存器
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;

static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;//s3c2440 Nand flash 相关寄存器起始地址

//供外部调用的函数声明
void nand_init(void); //初始化
void nand_read(unsigned char *buf, unsigned long start_addr, int size);//读取数据到缓冲区

/* S3C2440的NAND Flash处理函数 */
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_lp(unsigned int addr);
static unsigned char s3c2440_read_data(void);

//复位
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;
  //最后一位为1表示忙,忙就一直等
  while (!(*p & BUSY))
  for (i = 0; i < 10; i++);
}

//片选
static void s3c2440_nand_select_chip()
{
  s3c2440nand->NFCONT &= ~(1 << 1); //NFCONT寄存器[1]位Reg_nCE置0
  int i ;
  for (i = 0; i < 10; i++); //等待片选?
}

//取消片选
static void s3c2440_nand_deselect_chip()
{
  s3c2440nand->NFCONT |=(1<<1); //NFCONT寄存器[1]位Reg_nCE置1
}

//发送命令
static void s3c2440_write_cmd(int cmd)
{
  volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD; //p指向NFCMD寄存器
  *p = cmd; //命令写入命令寄存器
}

//发送地址
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; //得到页内地址。 每页2K,页内地址为bit[0-10]
  page = addr / NAND_SECTOR_SIZE_LP; //得到页号。256M为2的28次方,地址总位数为27,即bit[11-27]为页号,共17位
  *p = col & 0xff; //地址后8位 ,A0-A7;
  for (i = 0; i < 10; i++);
  *p = (col >> 8) & 0x0f; //A8-A10
  for (i = 0; i < 10; i++);
  *p = page & 0xff; //页号后后位 A11-A18
  for (i = 0; i < 10; i++);
  *p = (page >> 8) & 0xff;//A19-A26
  for (i = 0; i < 10; i++);
  *p = (page >> 16) & 0x1; //A27
  for (i = 0; i < 10; i++);}

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

//初始化Nand Flash
void nand_init(void)
{
  //设置时序
  //这里假设cpu频率100MHz,即一个时钟周期为10ns
  #define TACLS 0
  #define TWRPH0 3 //nand flash手册 twp最低要求12ns,即2个时钟周期以上,所以这里可以取1的,3可以保证400MHz时可用
  #define TWRPH1 0 //nand flash手册 tCLH最低要求5ns,取值0要求CPU频200Mhz以下
  s3c2440nand->NFCONF = (TACLS << 12) | (TWRPH0 << 8) | (TWRPH1 << 4);
  //使能Nand Flash,禁止片选,初始化ECC
  s3c2440nand->NFCONT = (1 << 4) | (1 << 1) | (1 << 0);
  s3c2440_nand_reset(); //复位
}

//读数据
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
  //Nand Flash的读取单位最小是page,长度必须是page的整数倍。所以必须对齐
  if ((start_addr & NAND_BLOCK_MASK_LP)||(size & NAND_BLOCK_MASK_LP))
  {
    return;
  }
  s3c2440_nand_select_chip();//发出片选信号

  int i, j;
  for (i = start_addr; i < (start_addr+size);)
  {
    s3c2440_write_cmd(0); //发出READ0命令
    s3c2440_write_addr_lp(i);
    s3c2440_write_cmd(0x30);
    s3c2440_wait_idle();
    //读取页数据
    for ( j = 0; j <NAND_SECTOR_SIZE_LP;j++,i++)
    {
      *buf = s3c2440_read_data();
      buf++;
    }

  }

  s3c2440_nand_deselect_chip();//取消片选
}


LCD实验学习笔记(七):NAND FLASH的更多相关文章

  1. LCD实验学习笔记(二):head.S

    ARM加电后从0地址开始取指执行. 连接为bin文件时时,连接脚本lcd.lds指定将head.o放在开头,所以head.S就是系统起步的地方. head.S开头就是异常向量定义,0地址就是reset ...

  2. LCD实验学习笔记(四):系统时钟

    一般CPU频率(FCLK)高于内存.网卡等设备频率(HCLK),而串口.USB.I2C等设备频率(PCLK)更低. 系统时钟: 系统时钟源为晶振,初始频率12MHz. 通过设置MPLLCON寄存器的M ...

  3. LCD实验学习笔记(一):Makefile

    主Makefile总领全局的就这句—— lcd.bin: $(objs) 要生成lcd.bin,依赖于objs列举的一堆文件:head.o init.o nand.o interrupt.o seri ...

  4. LCD实验学习笔记(十):TFT LCD

    硬件组成: REGBANK是LCD控制寄存器组,含17个寄存器及一块256*16的调色板,用来设置参数. LCDCDMA中有两个FIFO,当FIFO空或数据减少到阈值,自动发起DMA传输,从内存获取图 ...

  5. LCD实验学习笔记(九):UART

    s3c2440包含三个通用异步收发器,可工作于中断模式或DMA模式.每个UART包含两个64字节的FIFOs用于接收和发送数据.可编程设置波特率.1或2个停止位,5/6/7/8个数据位和奇偶校验状态. ...

  6. LCD实验学习笔记(八):中断

    s3c2440有60个中断源(其中15个为子中断源). 31个32位的通用寄存器,6个程序状态寄存器.有6种工作模式(系统/用户模式,快中断模式,管理模式,数据访问中止模式,中断模式,未定指令中止模式 ...

  7. LCD实验学习笔记(六):存储控制器

    s3c2440可使用地址空间为1GB(0x00000000到0x40000000). 1G空间分为8个BANK,每个BANK为128MB. 设27条地址线,和8个片选引脚(nGCS0-nGCS7). ...

  8. LCD实验学习笔记(五):MMU

    内存管理分别页表机制和内存分配机制两块. 页表机制就是管理设备真实物理地址与虚拟地址的动态或静态的映射,基于cpu内部的mmu(内存管理单元)进行. CP15(协处理器)的C0(缓存)是一级页表,含4 ...

  9. LCD实验学习笔记(三):WATCH DOG

    看门狗是为了能够防止程序跑飞用的.程序应该定时的去喂狗.如果程序跑飞了,那么就不会去喂狗了.如果超过了喂狗的时间,那么狗就会生成一个信号来reset CPU.一般程序不需要,特殊情况下需要这种机制. ...

随机推荐

  1. Windows2008安装启用无线网卡

    昨天给本子换了系统来着,本来想法是好的,想在本子上安装Hyper-v来搭建多平台VPS,这样的话就能玩多个系统了,对于我自己来说对娱乐没啥兴趣,扯多了,正文 笔记本安装什么都很顺利,但是无线网卡把我难 ...

  2. android异常Unable to instantiate activity ComponentInfo解决方法

    我是下面提到的第四条: 在Order and Export 中 把新加的 android-support-v4.jar的前面的对号打上勾 保存:就可以了: 做android开发的可能都碰到" ...

  3. Delphi Code Editor 之 快捷菜单

    Code Editor的快捷菜单分为两个部分:编辑器菜单项和调试器菜单项. 调试器菜单项留作以后讲解调试应用程序时再讲,这里只讲讲Code Editor的编辑器快捷菜单项. 下面列出了全部菜单项及描述 ...

  4. js 关键字 in 判断 一个属性或方法是否属于一个对象

    判断对象是否为数组/对象的元素/属性: 格式:(变量 in 对象)......注意,,, 当“对象”为数组时,“变量”指的是数组的“索引”: 当“对象”为对象是,“变量”指的是对象的“属性”. 判断 ...

  5. 【bzoj5085】最大 二分+暴力

    题目描述 给你一个n×m的矩形,要你找一个子矩形,价值为左上角左下角右上角右下角这四个数的最小值,要你最大化矩形的价值. 输入 第一行两个数n,m,接下来n行每行m个数,用来描述矩形 n, m ≤ 1 ...

  6. 存储引擎(Mysql)

    最常使用的2种存储引擎:1.Myisam是Mysql的默认存储引擎,当create创建新表时,未指定新表的存储引擎时,默认使用Myisam.每个MyISAM在磁盘上存储成三个文件.文件名都和表名相同, ...

  7. BZOJ4650:[NOI2016]优秀的拆分——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=4650 https://www.luogu.org/problemnew/show/P1117 如果 ...

  8. ZOJ3874 Permutation Graph 【分治NTT】

    题目链接 ZOJ3874 题意简述: 在一个序列中,两点间如果有边,当且仅当两点为逆序对 给定一个序列的联通情况,求方案数对\(786433\)取模 题解 自己弄了一个晚上终于弄出来了 首先\(yy\ ...

  9. UVA.540 Team Queue (队列)

    UVA.540 Team Queue (队列) 题意分析 有t个团队正在排队,每次来一个新人的时候,他可以插入到他最后一个队友的身后,如果没有他的队友,那么他只能插入到队伍的最后.题目中包含以下操作: ...

  10. 关于xml文件头部xmlsn

    样本: <?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://ww ...