微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > FS2410 开发板上 Nand Flash 到内存的代码搬移

FS2410 开发板上 Nand Flash 到内存的代码搬移

时间:11-10 来源:互联网 点击:
一、目的

前面做过一个实验,搬移 Nand Flash 里的前 4k 代码到内存指定位置,这其实是把

SRAM 从 0x40000000 开始的 4K 代码复制到 SDRAM 的指定位置,并没有涉及到对 Nand

Flash 的操作。究其原因,开发板上电后,Nand Flash 开始的前 4K 数据会被自动复制到

SRAM 0x40000000 开始的 4K 区域里,这个区域被称为 "Steppingstone"。那我们这次就来

操作 Nand Flash,读取它 4K 后的代码到 SDRAM 指定位置,并执行 SDRAM 中的代码。

二、代码

通过前面做的几个实验,我们已经熟悉了 ARM 开发的基本流程,这可以让我们更关注于

代码的逻辑。好,先来分析文件 head.s:

@ 文件 head.s

@ 作用:关闭看门狗、SDRAM 的初始化设置、搬移 Nand Flash 4K 以后

@ 的代码到 SDRAM 的指定位置、执行 SDRAM 中的代码

.text

.global _start

_start:

ldr r0, =0x53000000@ Close Watch Dog Timer

mov r1, #0x0

str r1, [r0]

bl memory_setup @ Initialize memory setting

bl flash_to_sdram@ Copy code to sdram

ldr sp, =0x34000000@ Set stack pointer

ldr pc, =main @ execute the code in SDRAM

@ 文件 mem.s

@ 作用:SDRAM 的初始化设置

@ 关于初始化的更多细节,请参考我的前一篇随笔

.global memory_setup @ 导出 memory_setup, 使其对链接器可见

memory_setup:

mov r1, #0x48000000

adrl r2, mem_cfg_val

add r3, r1, #13*4

1:

@ write initial values to registers

ldr r4, [r2], #4

str r4, [r1], #4

cmp r1, r3

bne 1b

mov pc, lr

.align 4

mem_cfg_val:

.long 0x22111110 @ BWSCON

.long 0x00000700 @ BANKCON0

.long 0x00000700 @ BANKCON1

.long 0x00000700 @ BANKCON2

.long 0x00000700 @ BANKCON3

.long 0x00000700 @ BANKCON4

.long 0x00000700 @ BANKCON5

.long 0x00018005 @ BANKCON6

.long 0x00018005 @ BANKCON7 9bit

.long 0x008e07a3 @ REFRESH

.long 0x000000b2 @ BANKSIZE

.long 0x00000030 @ MRSRB6

.long 0x00000030 @ MRSRB7

@ 文件 flash.s

@ 作用:设置 Nand Flash 的控制寄存器、读取 Nand Flash

@ 中的代码到 SDRAM 的指定位置

.equ NFCONF, 0x4e000000

.equ NFCMD, 0x4e000004

.equ NFADDR, 0x4e000008

.equ NFDATA, 0x4e00000c

.equ NFSTAT, 0x4e000010

.equ NFECC, 0x4e000014

.global flash_to_sdram

flash_to_sdram:

@ Save return addr

mov r10,lr

@ Initialize Nand Flash

mov r0,#NFCONF

ldr r1,=0xf830

str r1,[r0]

@ First reset and enable Nand Flash

ldr r1,[r0]

bic r1, r1, #0x800

str r1,[r0]

ldr r2,=NFCMD

mov r3,#0xff

str r3,[r2]

@ for delay

mov r3, #0x0a

1:

subs r3, r3, #1

bne 1b

@ Wait until Nand Flash bit0 is 1

wait_nfstat:

ldr r2,=NFSTAT

ldr r3,[r2]

tst r3,#0x01

beq wait_nfstat

@ Disable Nand Flash

ldr r0,=NFCONF

ldr r1,[r0]

orr r1,r1,#0x8000

str r1,[r0]

@ Initialzie stack

ldr sp,=4096

@ Set arguments and call

@ function nand_read defined in nand_read.c

ldr r0,=0x30000000

mov r1,#4096

mov r2,#1024

bl nand_read

@ return

mov pc,r10

/* 文件 nand_read.c

* 作用:从 Nand Flash 中读取一块数据到 SDRAM 中的指定位置

*/

#define NFCONF (*(volatile unsigned long *)0x4e000000)

#define NFCMD (*(volatile unsigned long *)0x4e000004)

#define NFADDR (*(volatile unsigned long *)0x4e000008)

#define NFDATA (*(volatile unsigned long *)0x4e00000c)

#define NFSTAT (*(volatile unsigned long *)0x4e000010)

#define NFECC (*(volatile unsigned long *)0x4e000014)

#define NAND_SECTOR_SIZE 512

#define NAND_BLOCK_MASK 0x1ff

void wait_idle() {

int i;

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

}

int nand_read(unsigned char *buf, unsigned long start_addr, int size){

int i, j;

/*

* detect the argument

*/

if ((start_addr & NAND_BLOCK_MASK) || (size & NAND_BLOCK_MASK)) {

return -1;

}

/* chip Enable */

NFCONF &= ~0x800;

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

;

}

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

NFCMD = 0;

/* Write Address */

NFADDR = i & 0xff;

NFADDR = (i >> 9) & 0xff;

NFADDR = (i >> 17) & 0xff;

NFADDR = (i >> 25) & 0xff;

wait_idle();

for(j=0; j < NAND_SECTOR_SIZE; j++) {

*buf++ = (NFDATA & 0xff);

}

}

NFCONF |= 0x800; /*

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top