ARM·Nand Flash的控制
【本章总结】 现在的代码在4096之后,需要控制NAND Flash将他们读出来、执行
firtst 0x00000000 : { head.o init.o nand.o} second 0x30000000 : AT(4096) { main.o } firtst 0x00000000 : { head.o init.o nand.o} second 0x30000000 : AT(4096) { main.o } @函数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赋值的方法进行跳转 b halt_loop 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 int i, j; if ((start_addr & NAND_BLOCK_MASK_LP) || (size & NAND_BLOCK_MASK_LP)) { return ; } if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) { return ; } nand_select_chip(); for(i=start_addr; i < (start_addr + size);) { write_cmd(0); write_addr(i); write_cmd(0x30); wait_idle(); for(j=0; j < NAND_SECTOR_SIZE_LP; j++, i++) { for(j=0; j < NAND_SECTOR_SIZE; j++, i++) { *buf = read_data(); buf++; } } S3C24X0_REG32 NFCONF; S3C24X0_REG32 NFCMD; S3C24X0_REG32 NFADDR; S3C24X0_REG32 NFDATA; S3C24X0_REG32 NFSTAT; S3C24X0_REG32 NFECC; 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; 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); s3c2410_nand_select_chip(); s3c2410_write_cmd(0xff); // 复位命令 s3c2410_wait_idle(); s3c2410_nand_deselect_chip(); int i; volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFSTAT; while(!(*p & BUSY)) for(i=0; i<10; i++); int i; s3c2410nand->NFCONF &= ~(1<<11); for(i=0; i<10; i++); s3c2410nand->NFCONF |= (1<<11); volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFCMD; *p = cmd; 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++); volatile unsigned char *p = (volatile unsigned char *)&s3c2410nand->NFDATA; return *p; s3c2440_nand_select_chip(); s3c2440_write_cmd(0xff); // 复位命令 s3c2440_wait_idle(); s3c2440_nand_deselect_chip(); int i; volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFSTAT; while(!(*p & BUSY)) for(i=0; i<10; i++); int i; s3c2440nand->NFCONT &= ~(1<<1); for(i=0; i<10; i++); s3c2440nand->NFCONT |= (1<<1); volatile unsigned char *p = (volatile unsigned char *)&s3c2440nand->NFCMD; *p = cmd; 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++);
个人觉得这章内容过于复杂,只需要记住如果nand中4096的程序想要被拷贝出来执行,就把这个代码写进去,红色部分是真正的代码,可以复制过去,直接使用,其他就不做了解了。听了一个小时,这个老师讲的也挺乱的,也没有人能记住这么多东西吧。。。
【head.S init.c main.c nand.c Makefile】
代码详解,这里先把一部分代码存放在NAND Flash 地址4096之后,当程序启动后通过NAND Flash控制器将他们读出来、执行。
注意:以前的代码都小于4096,开发板启动后他们被自动复制进“Steppingstone”;
【nand.lds】
SECTIONS {
}
对于这里,我是这样理解的 。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 {
} @******************************************************************************
@ File:head.s
@ 功能:设置SDRAM,将程序复制到SDRAM,然后跳到SDRAM继续执行
@******************************************************************************
.text
.global _start
_start:
halt_loop:
*对于这一串代码,很多都是前面学过的知识,这里我们只关注配置Nand的红色代码
bl nand_init
*目标地址,源地址,目标长度
这里我们可以跳转到nand_read中可以看一下
void nand_read(unsigned char *buf, unsigned long start_addr, int size)
{
#ifdef LARGER_NAND_PAGE
#else
#endif
#ifdef LARGER_NAND_PAGE
#endif
#ifdef LARGER_NAND_PAGE
#else
#endif
【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 {
} S3C2410_NAND;
typedef struct {
} S3C2440_NAND;
typedef struct {
}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)
{
}
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(void)
{
}
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)
{
}

加入微信
获取电子行业最新资讯
搜索微信公众号:EEPW
或用微信扫描左侧二维码
相关文章
-
嵌入式系统 2016-11-24