arm第七天(Nand Flash下)
NFSTAT寄存器 当RnB信号由低电平跳变成高电平时,该bit位会被自动置1(硬件完成),表示Flash可以读,读NFDATA寄存器; 案例:读Nand flash的第0页的主数据 #define __NAND_H__
#define __NAND_H__
//定义寄存器
#define NFCONF (*((volatile unsigned int*)0xBOE00000));
#define NFCONT (*((volatile unsigned int*)0xBOE00004));
#define NFCMMD (*((volatile unsigned int*)0xBOE00008));
#define NFADDR (*((volatile unsigned int*)0xBOE0000C));
#define NFDATA (*((volatile unsigned int*)0xBOE00010));
#define NFSTAT (*((volatile unsigned int*)0xBOE00028));
//声明函数原型
extern void nand_init(void);
extern void nand_read_id(void);
//buf:保存读取页数据的首地址
//page:表示要读的页号
extern void nand_page_read(unsigned int *buf,unsigned int page);
#endif
nand_page.c #include "nand.h"
#include "uart.h"
#include "itoa.h"
void nand_init(void)
{
//nand flash 控制器使用的管脚配置,
//因为我们使用的nand flash启动方式,所以关于GPIO管脚功能配置可以不做
//如果使用的不是nand flash启动,将需要配置
NFCONF = (0xF<<12) | (0xF<<8) |(0xF<<4) | (1<<1);
NFCONT = (3<<12) | (3<<8) | 7;
}
void nand_read_id(void)
{
//1,nand falsh片选信号拉低,使能nand falsh芯片
//操作 NFCONT bit[1] = 0;
NFCONT &= ~(1<<1);// 1<<1 ==> 10
//2,向NFCMMD寄存器写入0x90
NFCMMD = 0x90;
//3,向NFADDR寄存器写入0x0
NFADDR = 0x0;
//4,延时
int i;
for(i = 0;i < 256; i++)
{
;
}
//5,读NFDATA 寄存器(字)ID
//读5个字节的ID号
unsigned int id1;
unsigned int id2;
id1 = NFDATA;
id2 = (NFDATA & 0xFF);//只要低八位
//6,Nand flash片选信号拉高
//操作 NFCONT bit[1] = 1;
NFCONT |= (1<<1) ;
//7,显示读出来的nand flash的ID号
char buf[16];
uart0_puts("n ID1 = ");
itoa(buf,id1);//转换(整型无法直接打印,打印前转换成字符串)
uart0_puts(buf);//输出
uart0_puts("n ID2 = ");
itoa(buf2,id2);//转换
uart0_puts(buf2);//输出
}
void nand_page_read(unsigned int *buf,unsigned int page)
{
//1.Nand Flash 片选信号拉低
NFCON &= ~(1<<1);
//2。发送第一次读命令 0x0
NFCMD = 0x0;
//3,发送页内地址,分两个周期
//由于读一页,给该页第0个
//字节的页内地址,即0
NFADDR = 0x0;
NFADDR = 0x0;
//4,发送页号,分三个周期
NFADDR = (page & 0xFF);//低8bit
//bit[15:8]
NFADDR = ((page >> 8) & 0xFF);//中间的8 bit
//bit[18:16]
NFADDR = ((page >> 16) & 0xFF);
//5,发送第二次读命令 0x30
NFCMMD = 0x30
//6,清除标志NFSTAT 写1清bit[4]
NFSTAT |= (1<<4);
//7,等待NFSTAT bit[4]自动置 1
while(!(NFSTAT & (1<<4)))
{
;
}
//8,读取数据(2048)NFDATA
//以字读NFDATA
int i;
for(i=0;i<512;i++)//512*4 = 2048
{
buf[i] = NFDATA;
}
//9,nand flash片选信号拉高
NFCONT |= (1<<1) ;
}
cmd.c #include "cmd.h"
#include "led.h"
#include "nand.h"
#include "nand_page.h"
void cmd_ledon(void)
{
//调用开灯函数
led_on();
}
void cmd_nid(void)
{
//调用读nand flash Id函数
nand_read_id();
}
void cmd_ledoff(void)
{
//调用关灯函数
led_off();
}
static unsinged int test_buf[512];
void cmd_read(void)
{
char itoa_buf[16];
uart0_puts("n nand read...");
nand_page_read(test_buf,0);
}
void cmd_boot_linux(void)
{
//后面实现
}
const cmd_t cmd_tb1[] =
{
{"ledon",cmd_ledon},{"ledoff",cmd_ledoff},{"nid",cmd_nid},{"nread",cmd_read},{"bootlinux",cmd_boot_linux},//启动内核的命令,后面会用到
};
int cmd_tab1_num = sizeof(cmd_tb1)/sizeof(cmd_tb1[0]);
cmd_t *find_cmd(const char *name)
{
for(int i=0;i<cmd_tab1_num;i++)
{
if(name == cmd_tb1[i].name)
{
return cmd_tb1[i];
}
}
return NULL;
}
案例:如何把linux内核读到内存中? cmd.c中的cmd_boot_linux函数实现如下: typedef void (*func_t)(int r0,int r1,int r2);//函数指针,无返回值,三个整型参数
void cmd_boot_linux(void)
{
//1,从nand falsh的0x600000读取内核Image到内存的
//0x20008000,大小0xC00000
uart0_puts("n Loading kerenl");
unsigned int *ptr = (unsigned int *)0x200080000
//求起始页 6MB(0x600000)
//每一页2048字节大小
unsigned int page = 0x600000/2048;
int i;
for(i=0;i<0xC00000/2048;i++)
{
uart0_putc('.');
nand_page_read(ptr,page);
page++;//读下页
ptr += 2048/4;//读过来的起始地址
}
uart0_puts("n Run linux...");
//2,调用内存0x20008000处的Image(内核)
func_t = kernel_start;
kernel_start = (func_t)0x20008000;//把这个地址强制转换为一个函数的地址,为了后面执行这个函数
kernel_start(0,2456,0);//这里与移植有关,先忽略
}
链接脚本 shell.lds //1,告诉链接器如何组织可执行文件
//2,描述了程序在内存中执行时的大致内存布局,注意各个段的顺序
SECTIONS
{
.= 0x23000000;
.text:
{
main.o(.text);
*.o(.text);
}
.rodata:
{
*.o(.rodata);
}
. = ALIGN(4);//4字节对齐
.data://数据段
{
*.o(.data);
}
.=ALIGN(4);
__bss__start = .;
.bss :
{
.o(.bss);
}
__end =.;
}
将makefile文件中的”-Ttext 0x20008000” 修改为”-T shell.lds”即可,链接过程就会按照链接脚本的方式往下执行。 坏块处理 Nand falsh 8192块 main区: 0块 好块: 坏块: 1块 2块 3块 在nandread.h中增加 //读page的len个字节到buf
extern void nand_page_oob(char *buf,int len,unsigned int page);
//判断是否坏块
extern int nand_blk_check(unsigned int page_no);
在对应的.c文件中 //读page的len个字节到buf
extern void nand_page_oob(char *buf,unsigned int page)
{
//1,Nand flash 的片选信号拉低
NFCONT &= ~(1<<1);
//2,发送读命令 1: 0x0
NFCMMD = 0x0;
//3,发送页内地址,2次,2048
NFADDR = 0x0;
NFADDR = 0x8;
//4,发送页号地址,3次
NFADDR = (page & 0xFF);
NFADDR = (page >>8) & 0xFF);
NFADDR = (page >>16) & 0xFF);
//5,发送读命令 2:0x30
NFADDR = 0x30;
//6,清等待标志,清NFSTAT bit[4],写1清0
//7,等待NFSTAT bit[4]跳变成1
//8,读取一个字节的坏块标志
//由于是读一个字节,
int i;
for(i=0;i<len;i++)
{
// buf[] = ;
}
//9,nand flash片选信号拉高
NFCONT |=(1<<1);
}
//判断是否坏块
extern int nand_blk_check(unsigned int page_no)
{
unsigned char flag;
nand_page_read_oob(&flag,1,page_no);
if(flag != 0xFF){
return 1;//坏块
}
nand_page_read_oob(&flag,page_no++);
if(flag != 0xFF){
return 1;//坏块
}
return 0;
}
cmd.c增加命令nbad void cmd_nandbad(void)
{
int i;
char ibuf[16];
for(i=0;i<;i++)//循环一次判断一块
{
if(nand_blk_check(i)) //页号是每块的起始页号
{
uart0_puts("n Bad B lock:");
itoa(ibuf,i);//将i转成字符
uart0_puts(ibuf);
}
}
}
(编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |