实验(7)、Nand Flash读,直接从Nand读到SDRAM中运行

一、编写使用Nand Flash程序

1、程序功能:把一部分代码存放在Nand Flash地址4096之后,当程序启动后通过Nand Flash控制器将它们读出来,搬移到SDRAM中,然后执行。特别要注意的是,如果makefile中出现-O2的优化,则在main中的delay函数将无法运行的,这里特别指出来。下面给出完整的工程代码,已经调试过,可以顺利在天嵌开发板运行:

2、写程序如下:head.S、init.c、main.c、nand.c、makefile、nand.lds

(1)head.S

@******************************************************************************

@ 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 clock_init

bl memsetup @初始化SDRAM

bl nand_init @初始化NAND Flash

bl RdNF2SDRAM1

ldr sp, =0x34000000 @设置栈

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

ldr pc, =main @b指令和bl指令只能前后跳转32M的范围,所以这里使用向pc赋值的方法进行跳转

halt_loop:

b halt_loop

(2)inc.c

/* WOTCH DOG register */

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

#defineCLKDIVN(*(volatile unsigned long *)0x4c000014)

#defineMPLLCON(*(volatile unsigned long *)0x4c000004)

/* SDRAM regisers */

#define S3C2440_MPLL_400MHZ ((0x7f<<12)|(0x02<<4)|(0x01))

#define MEM_CTL_BASE0x48000000

void disable_watch_dog();

void memsetup();

void clock_init(void);

/*上电后,WATCH DOG默认是开着的,要把它关掉*/

void disable_watch_dog()

{

WTCON= 0;

}

void clock_init(void)

{

// LOCKTIME = 0x00ffffff; //使用默认值即可

CLKDIVN = 0x05; // FCLK:HCLK:PCLK=1:4:8, HDIVN=2,PDIVN=1

/*如果HDIVN非0,CPU的总线模式应该从“fast bus mode”变为“asynchronous bus mode”*/

__asm__(

"mrc p15, 0, r1, c1, c0, 0\n" /*读出控制寄存器*/

"orr r1, r1, #0xc0000000\n" /*设置为“asynchronous bus mode”*/

"mcr p15, 0, r1, c1, c0, 0\n" /*写入控制寄存器*/

);

MPLLCON = S3C2440_MPLL_400MHZ; /*现在,FCLK=400MHz,HCLK=100MHz,PCLK=50MHz */

}

/*设置控制SDRAM的13个寄存器*/

void memsetup()

{

int i = 0;

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

/* SDRAM 13个寄存器的值*/

unsigned long const mem_cfg_val[]={ 0x22011110, //BWSCON

0x00000700, //BANKCON0

0x00000700, //BANKCON1

0x00000700, //BANKCON2

0x00000700, //BANKCON3

0x00000700, //BANKCON4

0x00000700, //BANKCON5

0x00018005, //BANKCON6

0x00018005, //BANKCON7

0x008C07A3, //REFRESH

0x000000B1, //BANKSIZE

0x00000030, //MRSRB6

0x00000030, //MRSRB7

};

for(; i < 13; i++)

p[i] = mem_cfg_val[i];

}

(3)main.c

#define GPBCON (*(volatile unsigned long *)0x56000010)

#define GPBDAT (*(volatile unsigned long *)0x56000014)

#define led1out (1<<2*5)

//实验中跑马灯有四个灯要循环,故此需要四组输出控制来配置GPBCON

#define led2out (1<<2*6)

#define led3out (1<<2*7)

#define led4out (1<<2*8)

void delay(unsigned long i)

{

while(i--);

}

int main()

{

GPBCON |= led1out|led2out|led3out|led4out; //配置GPB5到GPB8端口输出属性

int i=0;

while(1)

{

GPBDAT = ~(1<<(i%4+5)); //亮灯

delay(10000); //延时

i++; //换灯变量

}

return 0;

}

(4)nand.c

#define TACLS 1

#define TWRPH0 5

#define TWRPH1 0

#define NFDATA (*(volatile unsigned char *)0x4e000010)//nand flash数据寄存器

typedef unsigned int S3C24X0_REG32;

/* NAND FLASH (see S3C2440 manual chapter 6, www.100ask.net) */

typedef struct {

S3C24X0_REG32 NFCONF;

S3C24X0_REG32 NFCONT;

S3C24X0_REG32 NFCMD;

S3C24X0_REG32 NFADDR;

S3C24X0_REG32 NFDATA0;

S3C24X0_REG32 NFMECCD0;

S3C24X0_REG32 NFMECCD1;

S3C24X0_REG32 NFSECCD;

S3C24X0_REG32 NFSTAT;

} S3C2440_NAND;

static S3C2440_NAND * s3c2440nand = (S3C2440_NAND *)0x4e000000;

void SendAD(unsigned long AD)

{

//s3c2440nand->NFADDR=AD;

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

*p=AD;

}

/*发出片选信号*/

static void s3c2440_nand_select_chip(void)

{

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

}

/*取消片选信号*/

static void s3c2440_nand_deselect_chip(void)

{

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

}

/* S3C2440的NAND Flash操作函数*/

/*复位*/

static void s3c2440_nand_reset(void)

{

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

s3c2440nand->NFSTAT |= (1<<2);

s3c2440nand->NFCMD = (0xff);

while(!(s3c2440nand->NFSTAT&(1<<2))); //test busy

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

}

/*等待NAND Flash就绪*/

void s3c2440_wait_idle(void)

{

int i;

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

while(!(*p & (1<<2)));

}

/*初始化NAND Flash */

void nand_init(void)

{

s3c2440nand->NFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(3<<2)|(1<<1);

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

s3c2440nand->NFSTAT =0x0;

s3c2440_nand_reset();

}

void nand_read(unsigned int block,unsigned int page,unsigned char *dstaddr)

{

int i;

unsigned int blockpage=(block<<6)+page;

s3c2440_nand_reset();

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

s3c2440nand->NFSTAT |= (1<<2);

s3c2440nand->NFCMD = (0x00);//send_cmd(readp1);

SendAD(0x00);

SendAD(0x00);

SendAD((blockpage)&0xff);

SendAD((blockpage>>8)&0xff);

SendAD((blockpage>>16)&0x01);

s3c2440nand->NFCMD = (0x30);//send_cmd(readp2);

while(!(s3c2440nand->NFSTAT&(1<<2))); //test busy

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

{

dstaddr[i]=NFDATA;

}

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

return ;

}

void RdNF2SDRAM(void)//将nand flash的代码复制到sdram中去

{

unsigned int i;

unsigned int start_addr =4096;//4096表示第4096个字节

unsigned char * dstaddr = (unsigned char *)0x30000000;/*留心指针类型转换*/

unsigned int size = 2048; //大小2018 B

for(i = (start_addr >> 11); size > 0;i ++ )//因为NAND_SECTOR_SIZE等于2048个字节,所以page就等于start_addr右移了11位,因为

{//2^11=2048。这里i表示页的绝对地址,即该页距离第0页的绝对地址

nand_read(i/64,i%64, dstaddr);

size -= 2048;

dstaddr += 2048;

}

}

/*发出地址*/

static void s3c2440_write_addr(unsigned int addr)

{

int i;

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

*p = addr&0xff;

*p = addr&0xf0;

*p = (addr >> 11) & 0xff;

*p = (addr >> 19) & 0xff;

*p = (addr >> 27) & 0x01;

}

void RdNF2SDRAM1(void)//将nand flash的代码复制到sdram中去

{

unsigned int i,j;

unsigned int start_addr =4096;//4096表示第4096个字节

unsigned char * dstaddr = (unsigned char *)0x30000000;/*留心指针类型转换*/

unsigned int size = 2048; //大小2048B

unsigned int blockpage=start_addr>>11;

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

{

s3c2440_nand_reset();

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

s3c2440nand->NFSTAT |= (1<<2);

s3c2440nand->NFCMD = (0x00);//send_cmd(readp1);

s3c2440_write_addr(i);

s3c2440nand->NFCMD = (0x30);//send_cmd(readp2);

while(!(s3c2440nand->NFSTAT&(1<<2))); //test busy

for(j=0;j<size;j++,i++)

{

dstaddr[j]=NFDATA;

}

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

}

}

(5)Makefile

objs := head.o init.o nand.o main.o

nand.bin : $(objs)

arm-linux-ld -Tnand.lds-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 -nostdlib -Wall -c -o $@ $<

%.o:%.S

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

clean:

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

(6)nand.lds

SECTIONS {

firtst 0x00000000 : { head.o init.o nand.o }

second0x30000000 : AT(4096){main.o}

}

��������ֆ�,

results matching ""

    No results matching ""

    results matching ""

      No results matching ""