之前编译出来的二进制,能用nandflash加载吗?不能,是吧,这就对啦。为什么不能呢?因为,代码中没有加从nandflash启动所需要的代码。因此,这就是我们今天码字的由来。
1.先修改cpu/arm1176/start.S文件,修改代码如下:
-
#ifndef CONFIG_NAND_SPL
-
/*
-
* flush v4 I/D caches
-
*/
-
mov r0, #0
-
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
-
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
-
-
/*
-
* disable MMU stuff and caches
-
*/
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
-
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
-
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
-
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
-
/* Prepare to disable the MMU */
-
adr r1, mmu_disable_phys
-
/* We presume we're within the first 1024 bytes */
-
and r1, r1, #0x3fc
-
ldr r2, _TEXT_PHY_BASE
-
ldr r3, =0xfff00000
-
and r2, r2, r3
-
orr r2, r2, r1
-
b mmu_disable
-
-
.align 5
-
/* Run in a single cache-line */
-
mmu_disable:
-
mcr p15, 0, r0, c1, c0, 0
-
nop
-
nop
-
mov pc, r2
-
#endif
更改为:
-
#ifndef CONFIG_NAND_SPL
-
/*
-
* flush v4 I/D caches
-
*/
-
mov r0, #0
-
mcr p15, 0, r0, c7, c7, 0 /* flush v3/v4 cache */
-
mcr p15, 0, r0, c8, c7, 0 /* flush v4 TLB */
-
-
/*
-
* disable MMU stuff and caches
-
*/
-
mrc p15, 0, r0, c1, c0, 0
-
bic r0, r0, #0x00002300 @ clear bits 13, 9:8 (--V- --RS)
-
bic r0, r0, #0x00000087 @ clear bits 7, 2:0 (B--- -CAM)
-
orr r0, r0, #0x00000002 @ set bit 2 (A) Align
-
orr r0, r0, #0x00001000 @ set bit 12 (I) I-Cache
-
#if 0
-
/* Prepare to disable the MMU */
-
adr r1, mmu_disable_phys
-
/* We presume we're within the first 1024 bytes */
-
and r1, r1, #0x3fc
-
ldr r2, _TEXT_PHY_BASE
-
ldr r3, =0xfff00000
-
and r2, r2, r3
-
orr r2, r2, r1
-
b mmu_disable
-
-
.align 5
-
/* Run in a single cache-line */
-
mmu_disable:
-
mcr p15, 0, r0, c1, c0, 0
-
nop
-
nop
-
mov pc, r2
-
#endif
-
#endif
找到lowlevel_init在其下面添加如下代码:
-
bl lowlevel_init /* go setup pll,mux,memory */
-
/*
-
* When we already run in ram, we don't need to relocate U-Boot
-
* and actually, memory controller mest to configured before U-Boot
-
* is running in ram.
-
*/
-
ldr r0, =0xff000fff
-
bic r1, pc, r0 /*r0 <- current base addr of code*/
-
ldr r2, _TEXT_BASE /*r1 <- original base addr in ram*/
-
bic r2, r2 ,r0 /*ro <- current base addr of code*/
-
cmp r1, r2 /*compare r1 , r2*/
-
beq after_copy /* if r1 == r2 then skip flash copy*/
-
-
#ifdef CONFIG_BOOT_NAND
-
mov r0, #0x1000
-
bl copy_from_nand
-
#endif
简述一下:
bic是位清除指令:就是r0中的值取反与pc值相与存入r1,且r1值为0;此时,_TEXT_BASE的值不是0x57e00000就是0xc7e00000;那么执行完bic r2, r2, r0之后r2就为0x00e00000;然后比较r1,r2如果相等则跳转到after_copy;很显然不相等,执行下面的函数copy_from_nand;这个就是从nandflash中拷贝到内存的函数。
在
-
#ifdef CONFIG_ENABLE_MMU
-
_mmu_table_base:
-
.word mmu_table
-
#endif
上面这些代码的下面加上如下代码:
-
#ifndef CONFIG_NAND_SPL
-
/*
-
* we assume that cache operation is done before. (eg. cleanup_before_linux())
-
* actually, we don't need to do anything about cache if not use d-cache in
-
* U-Boot. So, in this function we clean only MMU. by scsuh
-
*
-
* void theLastJump(void *kernel, int arch_num, uint boot_params);
-
*/
-
/*
-
* copy U-Boot to SDRAM and jump to ram (from NAND or OneNAND)
-
* r0: size to be compared
-
* Load 1'st 2blocks to RAM because U-boot's size is larger than 1block(128k) size
-
*/
-
.globl copy_from_nand
-
copy_from_nand:
-
mov r10, lr /* save return address */
-
mov r9, r0
-
/* get ready to call C functions */
-
ldr sp, _TEXT_PHY_BASE /* setup temp stack pointer */
-
sub sp, sp, #12
-
mov fp, #0 /* no previous frame, so fp=0 */
-
mov r9, #0x1000
-
bl copy_uboot_to_ram
-
3: tst r0, #0x0
-
bne copy_failed
-
ldr r0, =0x0c000000
-
ldr r1, _TEXT_PHY_BASE
-
1: ldr r3, [r0], #4
-
ldr r4, [r1], #4
-
teq r3, r4
-
bne compare_failed /* not matched */
-
subs r9, r9, #4
-
bne 1b
-
4: mov lr, r10 /* all is OK */
-
mov pc, lr
-
copy_failed:
-
nop /* copy from nand failed */
-
b copy_failed
-
compare_failed:
-
nop /* compare failed */
-
b compare_failed
2.在cpu/arm1176/目录下面添加文件nand_cp.c。文件内容如下:
-
#include <common.h>
-
-
#ifdef CONFIG_S3C64XX
-
#include <asm/io.h>
-
#include <linux/mtd/nand.h>
-
#include <asm/arch/s3c6410.h>
-
-
static int nandll_read_page(uchar *buf, ulong addr, int large_block)
-
{
-
int i;
-
int page_size = 512;
-
-
if (large_block == 1)
-
{
-
page_size = 2048;
-
}
-
-
if(large_block == 2)
-
{
-
page_size = 4096;
-
}
-
-
NAND_ENABLE_CE();
-
NFCMD_REG = NAND_CMD_READ0;
-
NFADDR_REG = 0; /*Write address*/
-
-
if(large_block)
-
{
-
NFADDR_REG = 0;
-
}
-
-
NFADDR_REG = addr & 0xff;
-
NFADDR_REG = (addr >> 8) & 0xff;
-
NFADDR_REG = (addr >> 16) & 0xff;
-
if (large_block)
-
{
-
NFCMD_REG = NAND_CMD_READSTART;
-
}
-
NF_TRANSRnB();
-
for(i=0; i < page_size; i++)
-
{
-
*buf++ = NFDATA8_REG;
-
}
-
NAND_DISABLE_CE();
-
return 0;
-
}
-
static int nandll_read_blocks (ulong dst_addr, ulong size, int large_block)
-
{
-
uchar *buf = (uchar *)dst_addr;
-
int i;
-
uint page_shift = 9;
-
if (large_block==1)
-
page_shift = 11;
-
/* Read pages */
-
if(large_block==2)
-
page_shift = 12;
-
if(large_block == 2)
-
{
-
/* Read pages */
-
for (i = 0; i < 4; i++, buf+=(1<<(page_shift-1)))
-
{
-
nandll_read_page(buf, i, large_block);
-
}
-
/* Read pages */
-
for (i = 4; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift))
-
{
-
nandll_read_page(buf, i, large_block);
-
}
-
}
-
else
-
{
-
for (i = 0; i < (0x3c000>>page_shift); i++, buf+=(1<<page_shift))
-
{
-
nandll_read_page(buf, i, large_block);
-
}
-
-
}
-
return 0;
-
}
-
int copy_uboot_to_ram(void)
-
{
-
int large_block = 0;
-
int i;
-
vu_char id;
-
-
/*
-
NFCONT_REG = ( *( (volatile u32 *) (0x70200004) ) )
-
NFCONT 0x70200004 读/写NAND Flash 控制寄存器
-
[0]1:NAND Flash 控制器使能
-
*/
-
NAND_ENABLE_CE();
-
-
NFCMD_REG = NAND_CMD_READID;
-
-
/*
-
NFADDR_REG = ( *( (volatile u32 *) (0x7020000C) ) )
-
NFADDR 0x7020000C NAND Flash 地址设置寄存器 */
-
NFADDR_REG = 0x00;
-
-
-
/*
-
NFDATA8_REG = ( *( (vu_char *) (0x70200010) ) )
-
NFDATA 0x70200010 读/写NAND Flash 数据寄存器
-
NAND Flash 读/烧写数据值用于I/O
-
*/
-
/* wait for a while */
-
for (i=0; i<200; i++);
-
id = NFDATA8_REG;
-
id = NFDATA8_REG;
-
if (id > 0x80)
-
large_block = 1;
-
if(id == 0xd5)
-
large_block = 2;
-
/* read NAND Block.
-
* 128KB ->240KB because of U-Boot size increase. by scsuh
-
* So, read 0x3c000 bytes not 0x20000(128KB).
-
*/
-
/*CONFIG_SYS_PHY_UBOOT_BASE = 0x57e0 0000
-
0x3 c000 = 1M
-
*/
-
return nandll_read_blocks(CONFIG_SYS_PHY_UBOOT_BASE, 0x3c000, large_block);
-
}
-
#endif
3.修改cpu/arm1176/makefile文件中
4.修改cpu/arm1176/u-boot.lds文件中
-
.text :
-
{
-
cpu/arm1176/start.o (.text)
-
cpu/arm1176/s3c64xx/cpu_init.o (.text)
-
board/samsung/smdk6410/lowlevel_init.o (.text)
-
cpu/arm1176/nand_cp.o (.text)
-
lib_arm/board.o (.text)
-
*(.text)
-
}
5.修改board/samsung/smdk6410/u-boot-nand.lds文件中
-
.text :
-
{
-
cpu/arm1176/start.o (.text)
-
cpu/arm1176/s3c64xx/cpu_init.o (.text)
-
board/samsung/smdk6410/lowlevel_init.o (.text)
-
cpu/arm1176/nand_cp.o (.text)
-
lib_arm/board.o (.text)
-
*(.text)
-
}
6.修改nand_spl/board/samsung/smdk6410/Makefile文件中
-
# from SoC directory
-
$(obj)cpu_init.S:
-
@rm -f $@
-
@ln -s $(TOPDIR)/cpu/arm1176/s3c64xx/cpu_init.S $@
-
-
# from from cpu directory
-
$(obj)nand_cp.c:
-
@rm -f $@
-
@ln -s $(TOPDIR)/cpu/arm1176/nand_cp.c $@
7.修改根目录下u-boot.lds文件
-
.text :
-
{
-
cpu/arm1176/start.o (.text)
-
cpu/arm1176/s3c64xx/cpu_init.o (.text)
-
board/samsung/smdk6410/lowlevel_init.o (.text)
-
cpu/arm1176/nand_cp.o (.text)
-
lib_arm/board.o (.text)
-
*(.text)
-
}
8.修改include/configs/sdmk6410.h文件
-
#if !defined(CONFIG_NAND_SPL) && (TEXT_BASE >= 0xc0000000)
-
#define CONFIG_ENABLE_MMU
-
#ifdef CONFIG_ENABLE_MMU
-
#define virt_to_phys(x) virt_to_phy_smdk6410(x)
-
#else
-
#define virt_to_phys(x) (x)
-
#endif
-
#endif
添加nand_pc.c中用到的那些宏定义
-
#define NAND_DISABLE_CE() (NFCONT_REG |= (1 << 1))
-
#define NAND_ENABLE_CE() (NFCONT_REG &= ~(1 << 1))
-
#define NF_TRANSRnB() do { while(!(NFSTAT_REG & (1 << 0))); } while(0)
-
#define CFG_PHY_UBOOT_BASE CONFIG_SYS_PHY_UBOOT_BASE
9.再次编译。使用make smdk6410_config; make ;生成u-boot-nand.bin,放到开发板上。
这次能够从nandflash启动了。^@^
附加:通过网络烧写到nandflash;
tftp 50000000 u-boot-nand.bin;
nand erase;/*擦除nandflash*/
nand scrub;/*标记坏块*/
nand write 50000000 0 40000 /*写在0~40000 地址之间*/
阅读(2008) | 评论(0) | 转发(0) |