从nand的启动的uboot
来源:互联网 发布:怎么在淘宝上写评价 编辑:程序博客网 时间:2024/06/05 13:02
从nand启动的uboot 来源: ChinaUnix博客 日期: 2009.06.09 10:21 (共有0条评论) 我要评论 我的开发板只有nand flash,但uboot不支持从nand flash启动,要移植uboot到自己的开发板上,需要对源码做一些修改,这里先来分析一下《ARM嵌入式linux系统开发从入门到精通》中给出的代码,虽然按照这个步骤编译出的二进制文件还有一些问题,但分析一下有助于之后对uboot的调试。由于uboot不支持从nand flash启动,所以将程序复制到DRAM里面去需要新加代码实现,一般通过copy_myself函数来实现。
首先看一下对start.S的修改:
在ldr pc, _start_armboot前添加下面内容。
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
在
http://blog.chinaunix.net/u/29387/showart_244343.html
中提到注释掉一部分relocate代码,但似乎注释的又不彻底,保留了清BSS段的代码。一个疑问是:注释掉这些内容是必须的吗?不过从出发点来说,这段代码确实是没有什么用了。
下面我们来看一下copy_myself都做了哪些事情。此处参考了vivi的copy_myself代码,一些变量的定义需要添加,后面会给出,这里直接给出
这些变量或宏所表达的意义。
#ifdef CONFIG_S3C2410_NAND_BOOT
copy_myself:
mov r10, lr @r10保存返回地址
@ reset NAND @初始化nand,主要是设置相关的控制器
mov r1, #NAND_CTL_BASE @NAND_CTL_BASE=0x4e000000,它是和nand相关的特殊寄存器组的基地址
ldr r2, =0xf830 @ initial value 0x1111,1000,0011,0000,enable nand flash controller Initialize ECC
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip,屏蔽[11],0 : NAND flash nFCE = L (active),NFCE是2410的管脚,与nand
str r2, [r1, #oNFCONF] @的NFCE相连
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD] @ 只传送一个字节到oNFCMD
mov r3, #0 @ wait
1: add r3, r3, #0x1
cmp r3, #0xa
blt 1b @ 延时10个指令周期
2: ldr r2, [r1, #oNFSTAT] @ wait ready,oNFSTAT的位[0]标志nand flash的状态,只读,取决于R/nB管脚。
tst r2, #0x1 @1 = NAND Flash memory ready to operate
beq 2b
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer, DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
mov fp, #0 @ no previous frame, so fp=0????????????????
@ copy UBOOT to RAM
ldr r0, =UBOOT_RAM_BASE @UBOOT_RAM_BASE=0x33f00000
mov r1, #0x0
mov r2, #0x30000 @ 0x30000=192K
bl nand_read_ll @此处nand_read_ll没有给出传递参数,这里猜想其参数依次是r0~r2种的值,这也是最合理的解释
tst r0, #0x0 @此处猜想汇编调用C函数的返回值赋给r0。关于汇编调用C函数的问题,有待考证。
beq ok_nand_read
#ifdef CONFIG_DEBUG_LL
bad_nand_read:
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
1: b 1b @ infinite loop
#endif
ok_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif @ 此段代码打印调试信息,前提是定义了CONFIG_DEBUG_LL,我们没有定义它,跳过!
@ verify
mov r0, #0
ldr r1, =UBOOT_RAM_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes,只验证前4K的内容,一点启示,这里只验证了前4k,并且根据
go_next: @要求我们应该把所有搬运代码的代码段包含在这前
@4k之 中,代码本身并没有问题,关键是所调用
ldr r3, [r0], #4 @的C函数以及相关头文件是否包含在了其中
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4 @S标志着根据结果更新N和Z,
beq done_nand_read
bne go_next
notmatch: @问题会是出在这儿吗?这儿有一个死循环!
#ifdef CONFIG_DEBUG_LL
sub r0, r0, #4
ldr r1, SerBase
bl PrintHexWord
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
#endif
1: b 1b
done_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
mov pc, r10
@ clear memory
@ r0: start address
@ r1: length
mem_clear:
mov r2, #0
mov r3, r2
mov r4, r2
mov r5, r2
mov r6, r2
mov r7, r2
mov r8, r2
mov r9, r2
clear_loop:
stmia r0!, {r2-r9}
subs r1, r1, #(8 * 4)
bne clear_loop
mov pc, lr
#endif @ CONFIG_S3C2410_NAND_BOOT
还要在start.S中添加以下内容,用于定义栈地址变量。
#ifdef CONFIG_S3C2410_NAND_BOOT
.align 2
DW_STACK_START:
.word STACK_BASE+STACK_SIZE-4
#endif
在start.S中,我们调用了nand_read_ll函数,它在nand_read.c中实现,该文件是由我们在/board/mike2410目录下新建的
#include
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
#define NFADDR __REGb(NF_BASE + 0x8)
#define NFDATA __REGb(NF_BASE + 0xc)
#define NFSTAT __REGb(NF_BASE + 0x10)
@定义了NF相关寄存器
#define BUSY 1 @这个BUSY有啥用呢???困惑!呵呵,屏蔽掉NFSTAT的前31位,只inline void wait_idle(void) { @保留最后一位
int i;
while(!(NFSTAT & BUSY)) @如果忙,就延时一会儿
for(i=0; i> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff; @对此处的理解要参考K9S1208的手册,i 对应了一个32位地址,但k9s1208只有date/addr/cmd @共用的八根地址线,要分批次发送到nand flash。
wait_idle();
for(j=0; j
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE; /*可以用NFCE_STATE声明一个枚举类型*/
static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
/*定义了一个指向S3C2410_NAND结构体(定义于s3c24x0.h)的指针nand,基地址是S3C2410_NAND_BASE(定义于S3C2410.h)*/
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFADDR = addr;
}
static inline void NF_SetCE(NFCE_STATE s) //传递参数时s只能取NFCE_LOW或NFCE_HIGH
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1NFCONF |= (1NFSTAT & (1NFDATA = data;
}
static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFDATA);
}
static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |= (1NFECC);
}
#endif
该头文件中定义的函数在修改的smdk2410.c中用到。
下面是对mike2410.c的修改:主要是对nand的初始化。
#include
#include
#include "nandflash.h"
/* ------------------------------------------------------------------------- */
#define FCLK_SPEED 1
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1 /*s3c2410.pdf 7-20*/
#endif
#define USB_CLOCK 1
#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#endif
static inline void delay (unsigned long loops)
{
__asm__ volatile ("1:/n"
"subs %0, %1, #1/n"
"bne 1b":"=r" (loops):"0" (loops));
}
/*
* Miscellaneous platform dependent initialisations
*/
int board_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = ((M_MDIV UPLLCON = ((U_M_MDIV GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555; /*针对我的板子此处应做相应的修改*,=0xBEAAF查看手册P268*/
gpio->GPBUP = 0x000007FF; /* 1: The pull-up function is disabled.GPB[10:0]*/
gpio->GPCCON = 0xAAAAAAAA; /*根据开发板,改为0xAABFFEAB*/
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA; /*改为=0xAABFAAAB*/
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA; /*改为=0x7DEE*/
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA; /*=FFAFFFFA*/
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA; /*0x3[10??]AAAA*/
gpio->GPHUP = 0x000007FF;
/* select USB port to be support for host or device */
gpio->MISCCR |= (1MISCCR &= ~((1bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
/*
* NAND flash initialization.
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i > 10);
}
#endif
int dram_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
gd->bd->bi_dram[0].start = PHYS_SDRAM_1; /*定义见smdk2410.h*/
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return 0;
}
对smdk2410.h的修改:
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */
#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
/* input clock of PLL */
#define CONFIG_SYS_CLK_FREQ 12000000/* the SMDK2410 has 12MHz input clock */
#define USE_920T_MMU 1
#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGS */
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_INITRD_TAG 1
/*
* Size of malloc() pool
*/
#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024)
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
/*
* Hardware drivers
*/
#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
#define CS8900_BASE 0x19000300
#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
/*
* select serial console configuration
*/
#define CONFIG_SERIAL1 1 /* we use SERIAL 1 on SMDK2410 */
/************************************************************
* RTC
************************************************************/
#define CONFIG_RTC_S3C24X0 1
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_BAUDRATE 115200
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS /
(CONFIG_CMD_DFL | /
CFG_CMD_CACHE | /
CFG_CMD_ENV | /
CFG_CMD_PING | /
CFG_CMD_NAND | /
/*CFG_CMD_EEPROM |*/ /
/*CFG_CMD_I2C |*/ /
CFG_CMD_REGINFO | /
CFG_CMD_ELF)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include
#define CONFIG_BOOTDELAY 3
/*#define CONFIG_BOOTARGS "root=ramfs devfs=mount console=ttySA0,9600" */
/*#define CONFIG_ETHADDR 08:00:3e:26:0a:5b */
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.1.10
#define CONFIG_SERVERIP 192.168.1.1
/*#define CONFIG_BOOTFILE "elinos-lart" */
/*#define CONFIG_BOOTCOMMAND "tftp; bootm" */
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
/* what's this ? it's not used anywhere */
#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */
#endif
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "MIKE2410# " /* Monitor Command Prompt */
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
#define CFG_MEMTEST_START 0x30000000 /* memtest works on */
#define CFG_MEMTEST_END 0x33F00000 /* 63 MB in DRAM */
#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
#define CFG_LOAD_ADDR 0x30008000 /* default load address */
/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */
/* it to wrap 100 times (total 1562500) to get 1 sec. */
#define CFG_HZ 1562500
/* valid baudrates */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
/*-----------------------------------------------------------------------
* Stack sizes
*
* The stack sizes are set up in start.S using the settings below
*/
#define CONFIG_STACKSIZE (128*1024) /* regular stack */
#ifdef CONFIG_USE_IRQ
#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
#endif
/*-----------------------------------------------------------------------
* Physical Memory Map
*/
#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
#define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */
#define CFG_FLASH_BASE PHYS_FLASH_1
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
#if 0
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
#endif
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
#endif
/* timeout values are in ticks */
#define CFG_FLASH_ERASE_TOUT (5*CFG_HZ) /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT (5*CFG_HZ) /* Timeout for Flash Write */
#define CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_OFFSET 0x30000
#define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
/*-----------------------------------------------------------------------
* * NAND flash settings
* */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
#define NAND_WAIT_READY(nand) NF_WaitRB()
#define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH)
#define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW)
#define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d)
#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)
#define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d)
#define WRITE_NAND(d, adr) NF_Write(d)
#define READ_NAND(adr) NF_Read()
/* the following functions are NOP's because S3C24X0 handles this in hardware */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define CONFIG_MTD_NAND_ECC_JFFS2 1
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
/*
* * Nandflash Boot
* */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
#define UBOOT_RAM_BASE 0x33f80000
#define NAND_CTL_BASE 0x4E000000
#define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb))
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
#endif
#endif /* __CONFIG_H */
有一个问题:LV800和LV400的选择上,并不清楚自己的板子是哪种????
下一步要看看uboot命令了,我们可以先从SDRAM中调试uboot,调试成功后再移植。而这需要用到一些uboot命令,趁此机会把uboot命令熟悉一下,早晚都要学的。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/82249/showart_1959331.html
首先看一下对start.S的修改:
在ldr pc, _start_armboot前添加下面内容。
#ifdef CONFIG_S3C2410_NAND_BOOT
bl copy_myself
@ jump to ram
ldr r1, =on_the_ram
add pc, r1, #0
nop
nop
1: b 1b @ infinite loop
on_the_ram:
#endif
在
http://blog.chinaunix.net/u/29387/showart_244343.html
中提到注释掉一部分relocate代码,但似乎注释的又不彻底,保留了清BSS段的代码。一个疑问是:注释掉这些内容是必须的吗?不过从出发点来说,这段代码确实是没有什么用了。
下面我们来看一下copy_myself都做了哪些事情。此处参考了vivi的copy_myself代码,一些变量的定义需要添加,后面会给出,这里直接给出
这些变量或宏所表达的意义。
#ifdef CONFIG_S3C2410_NAND_BOOT
copy_myself:
mov r10, lr @r10保存返回地址
@ reset NAND @初始化nand,主要是设置相关的控制器
mov r1, #NAND_CTL_BASE @NAND_CTL_BASE=0x4e000000,它是和nand相关的特殊寄存器组的基地址
ldr r2, =0xf830 @ initial value 0x1111,1000,0011,0000,enable nand flash controller Initialize ECC
str r2, [r1, #oNFCONF]
ldr r2, [r1, #oNFCONF]
bic r2, r2, #0x800 @ enable chip,屏蔽[11],0 : NAND flash nFCE = L (active),NFCE是2410的管脚,与nand
str r2, [r1, #oNFCONF] @的NFCE相连
mov r2, #0xff @ RESET command
strb r2, [r1, #oNFCMD] @ 只传送一个字节到oNFCMD
mov r3, #0 @ wait
1: add r3, r3, #0x1
cmp r3, #0xa
blt 1b @ 延时10个指令周期
2: ldr r2, [r1, #oNFSTAT] @ wait ready,oNFSTAT的位[0]标志nand flash的状态,只读,取决于R/nB管脚。
tst r2, #0x1 @1 = NAND Flash memory ready to operate
beq 2b
ldr r2, [r1, #oNFCONF]
orr r2, r2, #0x800 @ disable chip
str r2, [r1, #oNFCONF]
@ get read to call C functions (for nand_read())
ldr sp, DW_STACK_START @ setup stack pointer, DW_STACK_START: .word STACK_BASE+STACK_SIZE-4
mov fp, #0 @ no previous frame, so fp=0????????????????
@ copy UBOOT to RAM
ldr r0, =UBOOT_RAM_BASE @UBOOT_RAM_BASE=0x33f00000
mov r1, #0x0
mov r2, #0x30000 @ 0x30000=192K
bl nand_read_ll @此处nand_read_ll没有给出传递参数,这里猜想其参数依次是r0~r2种的值,这也是最合理的解释
tst r0, #0x0 @此处猜想汇编调用C函数的返回值赋给r0。关于汇编调用C函数的问题,有待考证。
beq ok_nand_read
#ifdef CONFIG_DEBUG_LL
bad_nand_read:
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
1: b 1b @ infinite loop
#endif
ok_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif @ 此段代码打印调试信息,前提是定义了CONFIG_DEBUG_LL,我们没有定义它,跳过!
@ verify
mov r0, #0
ldr r1, =UBOOT_RAM_BASE
mov r2, #0x400 @ 4 bytes * 1024 = 4K-bytes,只验证前4K的内容,一点启示,这里只验证了前4k,并且根据
go_next: @要求我们应该把所有搬运代码的代码段包含在这前
@4k之 中,代码本身并没有问题,关键是所调用
ldr r3, [r0], #4 @的C函数以及相关头文件是否包含在了其中
ldr r4, [r1], #4
teq r3, r4
bne notmatch
subs r2, r2, #4 @S标志着根据结果更新N和Z,
beq done_nand_read
bne go_next
notmatch: @问题会是出在这儿吗?这儿有一个死循环!
#ifdef CONFIG_DEBUG_LL
sub r0, r0, #4
ldr r1, SerBase
bl PrintHexWord
ldr r0, STR_FAIL
ldr r1, SerBase
bl PrintWord
#endif
1: b 1b
done_nand_read:
#ifdef CONFIG_DEBUG_LL
ldr r0, STR_OK
ldr r1, SerBase
bl PrintWord
#endif
mov pc, r10
@ clear memory
@ r0: start address
@ r1: length
mem_clear:
mov r2, #0
mov r3, r2
mov r4, r2
mov r5, r2
mov r6, r2
mov r7, r2
mov r8, r2
mov r9, r2
clear_loop:
stmia r0!, {r2-r9}
subs r1, r1, #(8 * 4)
bne clear_loop
mov pc, lr
#endif @ CONFIG_S3C2410_NAND_BOOT
还要在start.S中添加以下内容,用于定义栈地址变量。
#ifdef CONFIG_S3C2410_NAND_BOOT
.align 2
DW_STACK_START:
.word STACK_BASE+STACK_SIZE-4
#endif
在start.S中,我们调用了nand_read_ll函数,它在nand_read.c中实现,该文件是由我们在/board/mike2410目录下新建的
#include
#define __REGb(x) (*(volatile unsigned char *)(x))
#define __REGi(x) (*(volatile unsigned int *)(x))
#define NF_BASE 0x4e000000
#define NFCONF __REGi(NF_BASE + 0x0)
#define NFCMD __REGb(NF_BASE + 0x4)
#define NFADDR __REGb(NF_BASE + 0x8)
#define NFDATA __REGb(NF_BASE + 0xc)
#define NFSTAT __REGb(NF_BASE + 0x10)
@定义了NF相关寄存器
#define BUSY 1 @这个BUSY有啥用呢???困惑!呵呵,屏蔽掉NFSTAT的前31位,只inline void wait_idle(void) { @保留最后一位
int i;
while(!(NFSTAT & BUSY)) @如果忙,就延时一会儿
for(i=0; i> 9) & 0xff;
NFADDR = (i >> 17) & 0xff;
NFADDR = (i >> 25) & 0xff; @对此处的理解要参考K9S1208的手册,i 对应了一个32位地址,但k9s1208只有date/addr/cmd @共用的八根地址线,要分批次发送到nand flash。
wait_idle();
for(j=0; j
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
typedef enum {
NFCE_LOW,
NFCE_HIGH
} NFCE_STATE; /*可以用NFCE_STATE声明一个枚举类型*/
static inline void NF_Conf(u16 conf)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
/*定义了一个指向S3C2410_NAND结构体(定义于s3c24x0.h)的指针nand,基地址是S3C2410_NAND_BASE(定义于S3C2410.h)*/
nand->NFCONF = conf;
}
static inline void NF_Cmd(u8 cmd)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCMD = cmd;
}
static inline void NF_CmdW(u8 cmd)
{
NF_Cmd(cmd);
udelay(1);
}
static inline void NF_Addr(u8 addr)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFADDR = addr;
}
static inline void NF_SetCE(NFCE_STATE s) //传递参数时s只能取NFCE_LOW或NFCE_HIGH
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
switch (s) {
case NFCE_LOW:
nand->NFCONF &= ~(1NFCONF |= (1NFSTAT & (1NFDATA = data;
}
static inline u8 NF_Read(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
return(nand->NFDATA);
}
static inline void NF_Init_ECC(void)
{
S3C2410_NAND * const nand = S3C2410_GetBase_NAND();
nand->NFCONF |= (1NFECC);
}
#endif
该头文件中定义的函数在修改的smdk2410.c中用到。
下面是对mike2410.c的修改:主要是对nand的初始化。
#include
#include
#include "nandflash.h"
/* ------------------------------------------------------------------------- */
#define FCLK_SPEED 1
#if FCLK_SPEED==0 /* Fout = 203MHz, Fin = 12MHz for Audio */
#define M_MDIV 0xC3
#define M_PDIV 0x4
#define M_SDIV 0x1
#elif FCLK_SPEED==1 /* Fout = 202.8MHz */
#define M_MDIV 0xA1
#define M_PDIV 0x3
#define M_SDIV 0x1 /*s3c2410.pdf 7-20*/
#endif
#define USB_CLOCK 1
#if USB_CLOCK==0
#define U_M_MDIV 0xA1
#define U_M_PDIV 0x3
#define U_M_SDIV 0x1
#elif USB_CLOCK==1
#define U_M_MDIV 0x48
#define U_M_PDIV 0x3
#define U_M_SDIV 0x2
#endif
static inline void delay (unsigned long loops)
{
__asm__ volatile ("1:/n"
"subs %0, %1, #1/n"
"bne 1b":"=r" (loops):"0" (loops));
}
/*
* Miscellaneous platform dependent initialisations
*/
int board_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
S3C24X0_CLOCK_POWER * const clk_power = S3C24X0_GetBase_CLOCK_POWER();
S3C24X0_GPIO * const gpio = S3C24X0_GetBase_GPIO();
/* to reduce PLL lock time, adjust the LOCKTIME register */
clk_power->LOCKTIME = 0xFFFFFF;
/* configure MPLL */
clk_power->MPLLCON = ((M_MDIV UPLLCON = ((U_M_MDIV GPACON = 0x007FFFFF;
gpio->GPBCON = 0x00044555; /*针对我的板子此处应做相应的修改*,=0xBEAAF查看手册P268*/
gpio->GPBUP = 0x000007FF; /* 1: The pull-up function is disabled.GPB[10:0]*/
gpio->GPCCON = 0xAAAAAAAA; /*根据开发板,改为0xAABFFEAB*/
gpio->GPCUP = 0x0000FFFF;
gpio->GPDCON = 0xAAAAAAAA; /*改为=0xAABFAAAB*/
gpio->GPDUP = 0x0000FFFF;
gpio->GPECON = 0xAAAAAAAA;
gpio->GPEUP = 0x0000FFFF;
gpio->GPFCON = 0x000055AA; /*改为=0x7DEE*/
gpio->GPFUP = 0x000000FF;
gpio->GPGCON = 0xFF95FFBA; /*=FFAFFFFA*/
gpio->GPGUP = 0x0000FFFF;
gpio->GPHCON = 0x002AFAAA; /*0x3[10??]AAAA*/
gpio->GPHUP = 0x000007FF;
/* select USB port to be support for host or device */
gpio->MISCCR |= (1MISCCR &= ~((1bd->bi_arch_number = MACH_TYPE_SMDK2410;
/* adress of boot parameters */
gd->bd->bi_boot_params = 0x30000100;
icache_enable();
dcache_enable();
return 0;
}
/*
* NAND flash initialization.
*/
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
extern ulong nand_probe(ulong physadr);
static inline void NF_Reset(void)
{
int i;
NF_SetCE(NFCE_LOW);
NF_Cmd(0xFF); /* reset command */
for(i = 0; i > 10);
}
#endif
int dram_init (void)
{
DECLARE_GLOBAL_DATA_PTR;
gd->bd->bi_dram[0].start = PHYS_SDRAM_1; /*定义见smdk2410.h*/
gd->bd->bi_dram[0].size = PHYS_SDRAM_1_SIZE;
return 0;
}
对smdk2410.h的修改:
#ifndef __CONFIG_H
#define __CONFIG_H
/*
* High Level Configuration Options
* (easy to change)
*/
#define CONFIG_ARM920T 1 /* This is an ARM920T Core */
#define CONFIG_S3C2410 1 /* in a SAMSUNG S3C2410 SoC */
#define CONFIG_SMDK2410 1 /* on a SAMSUNG SMDK2410 Board */
/* input clock of PLL */
#define CONFIG_SYS_CLK_FREQ 12000000/* the SMDK2410 has 12MHz input clock */
#define USE_920T_MMU 1
#undef CONFIG_USE_IRQ /* we don't need IRQ/FIQ stuff */
#define CONFIG_CMDLINE_TAG 1 /* enable passing of ATAGS */
#define CONFIG_SETUP_MEMORY_TAGS 1
#define CONFIG_INITRD_TAG 1
/*
* Size of malloc() pool
*/
#define CFG_MALLOC_LEN (CFG_ENV_SIZE + 128*1024)
#define CFG_GBL_DATA_SIZE 128 /* size in bytes reserved for initial data */
/*
* Hardware drivers
*/
#define CONFIG_DRIVER_CS8900 1 /* we have a CS8900 on-board */
#define CS8900_BASE 0x19000300
#define CS8900_BUS16 1 /* the Linux driver does accesses as shorts */
/*
* select serial console configuration
*/
#define CONFIG_SERIAL1 1 /* we use SERIAL 1 on SMDK2410 */
/************************************************************
* RTC
************************************************************/
#define CONFIG_RTC_S3C24X0 1
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#define CONFIG_BAUDRATE 115200
/***********************************************************
* Command definition
***********************************************************/
#define CONFIG_COMMANDS /
(CONFIG_CMD_DFL | /
CFG_CMD_CACHE | /
CFG_CMD_ENV | /
CFG_CMD_PING | /
CFG_CMD_NAND | /
/*CFG_CMD_EEPROM |*/ /
/*CFG_CMD_I2C |*/ /
CFG_CMD_REGINFO | /
CFG_CMD_ELF)
/* this must be included AFTER the definition of CONFIG_COMMANDS (if any) */
#include
#define CONFIG_BOOTDELAY 3
/*#define CONFIG_BOOTARGS "root=ramfs devfs=mount console=ttySA0,9600" */
/*#define CONFIG_ETHADDR 08:00:3e:26:0a:5b */
#define CONFIG_NETMASK 255.255.255.0
#define CONFIG_IPADDR 192.168.1.10
#define CONFIG_SERVERIP 192.168.1.1
/*#define CONFIG_BOOTFILE "elinos-lart" */
/*#define CONFIG_BOOTCOMMAND "tftp; bootm" */
#if (CONFIG_COMMANDS & CFG_CMD_KGDB)
#define CONFIG_KGDB_BAUDRATE 115200 /* speed to run kgdb serial port */
/* what's this ? it's not used anywhere */
#define CONFIG_KGDB_SER_INDEX 1 /* which serial port to use */
#endif
/*
* Miscellaneous configurable options
*/
#define CFG_LONGHELP /* undef to save memory */
#define CFG_PROMPT "MIKE2410# " /* Monitor Command Prompt */
#define CFG_CBSIZE 256 /* Console I/O Buffer Size */
#define CFG_PBSIZE (CFG_CBSIZE+sizeof(CFG_PROMPT)+16) /* Print Buffer Size */
#define CFG_MAXARGS 16 /* max number of command args */
#define CFG_BARGSIZE CFG_CBSIZE /* Boot Argument Buffer Size */
#define CFG_MEMTEST_START 0x30000000 /* memtest works on */
#define CFG_MEMTEST_END 0x33F00000 /* 63 MB in DRAM */
#undef CFG_CLKS_IN_HZ /* everything, incl board info, in Hz */
#define CFG_LOAD_ADDR 0x30008000 /* default load address */
/* the PWM TImer 4 uses a counter of 15625 for 10 ms, so we need */
/* it to wrap 100 times (total 1562500) to get 1 sec. */
#define CFG_HZ 1562500
/* valid baudrates */
#define CFG_BAUDRATE_TABLE { 9600, 19200, 38400, 57600, 115200 }
/*-----------------------------------------------------------------------
* Stack sizes
*
* The stack sizes are set up in start.S using the settings below
*/
#define CONFIG_STACKSIZE (128*1024) /* regular stack */
#ifdef CONFIG_USE_IRQ
#define CONFIG_STACKSIZE_IRQ (4*1024) /* IRQ stack */
#define CONFIG_STACKSIZE_FIQ (4*1024) /* FIQ stack */
#endif
/*-----------------------------------------------------------------------
* Physical Memory Map
*/
#define CONFIG_NR_DRAM_BANKS 1 /* we have 1 bank of DRAM */
#define PHYS_SDRAM_1 0x30000000 /* SDRAM Bank #1 */
#define PHYS_SDRAM_1_SIZE 0x04000000 /* 64 MB */
#define PHYS_FLASH_1 0x00000000 /* Flash Bank #1 */
#define CFG_FLASH_BASE PHYS_FLASH_1
/*-----------------------------------------------------------------------
* FLASH and environment organization
*/
#define CONFIG_AMD_LV400 1 /* uncomment this if you have a LV400 flash */
#if 0
#define CONFIG_AMD_LV800 1 /* uncomment this if you have a LV800 flash */
#endif
#define CFG_MAX_FLASH_BANKS 1 /* max number of memory banks */
#ifdef CONFIG_AMD_LV800
#define PHYS_FLASH_SIZE 0x00100000 /* 1MB */
#define CFG_MAX_FLASH_SECT (19) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x0F0000) /* addr of environment */
#endif
#ifdef CONFIG_AMD_LV400
#define PHYS_FLASH_SIZE 0x00080000 /* 512KB */
#define CFG_MAX_FLASH_SECT (11) /* max number of sectors on one chip */
#define CFG_ENV_ADDR (CFG_FLASH_BASE + 0x070000) /* addr of environment */
#endif
/* timeout values are in ticks */
#define CFG_FLASH_ERASE_TOUT (5*CFG_HZ) /* Timeout for Flash Erase */
#define CFG_FLASH_WRITE_TOUT (5*CFG_HZ) /* Timeout for Flash Write */
#define CFG_ENV_IS_IN_NAND 1
#define CFG_ENV_OFFSET 0x30000
#define CFG_ENV_SIZE 0x10000 /* Total Size of Environment Sector */
/*-----------------------------------------------------------------------
* * NAND flash settings
* */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CFG_MAX_NAND_DEVICE 1 /* Max number of NAND devices */
#define SECTORSIZE 512
#define ADDR_COLUMN 1
#define ADDR_PAGE 2
#define ADDR_COLUMN_PAGE 3
#define NAND_ChipID_UNKNOWN 0x00
#define NAND_MAX_FLOORS 1
#define NAND_MAX_CHIPS 1
#define NAND_WAIT_READY(nand) NF_WaitRB()
#define NAND_DISABLE_CE(nand) NF_SetCE(NFCE_HIGH)
#define NAND_ENABLE_CE(nand) NF_SetCE(NFCE_LOW)
#define WRITE_NAND_COMMAND(d, adr) NF_Cmd(d)
#define WRITE_NAND_COMMANDW(d, adr) NF_CmdW(d)
#define WRITE_NAND_ADDRESS(d, adr) NF_Addr(d)
#define WRITE_NAND(d, adr) NF_Write(d)
#define READ_NAND(adr) NF_Read()
/* the following functions are NOP's because S3C24X0 handles this in hardware */
#define NAND_CTL_CLRALE(nandptr)
#define NAND_CTL_SETALE(nandptr)
#define NAND_CTL_CLRCLE(nandptr)
#define NAND_CTL_SETCLE(nandptr)
#define CONFIG_MTD_NAND_VERIFY_WRITE 1
#define CONFIG_MTD_NAND_ECC_JFFS2 1
#endif /* CONFIG_COMMANDS & CFG_CMD_NAND */
/*
* * Nandflash Boot
* */
#if (CONFIG_COMMANDS & CFG_CMD_NAND)
#define CONFIG_S3C2410_NAND_BOOT 1
#define STACK_BASE 0x33f00000
#define STACK_SIZE 0x8000
#define UBOOT_RAM_BASE 0x33f80000
#define NAND_CTL_BASE 0x4E000000
#define bINT_CTL(Nb) __REG(INT_CTL_BASE + (Nb))
#define oNFCONF 0x00
#define oNFCMD 0x04
#define oNFADDR 0x08
#define oNFDATA 0x0c
#define oNFSTAT 0x10
#define oNFECC 0x14
#endif
#endif /* __CONFIG_H */
有一个问题:LV800和LV400的选择上,并不清楚自己的板子是哪种????
下一步要看看uboot命令了,我们可以先从SDRAM中调试uboot,调试成功后再移植。而这需要用到一些uboot命令,趁此机会把uboot命令熟悉一下,早晚都要学的。
本文来自ChinaUnix博客,如果查看原文请点:http://blog.chinaunix.net/u2/82249/showart_1959331.html
- 从nand的启动的uboot
- 从Nand flash启动的uboot
- uboot从nand启动
- [NAND]UBOOT从NAND FLASH启动分析
- [NAND]UBOOT从NAND FLASH启动分析
- uboot 的nand驱动
- uboot 的nand驱动
- 关于AM335X uboot启动的时候找不到nand的问题
- 关于从NAND Flash启动的问题
- 关于从NAND Flash启动的问题
- 关于从NAND Flash启动的问题
- 关于从NAND Flash启动的问题
- 增加从Nand 启动的代码:
- uboot的nand flash常用命令
- nand flash uboot 启动
- uboot启动(nand)
- uboot-2010.03移植到2410(从nand启动)
- TQ2440从nor烧写nand启动uboot和kennel
- hdu--2504 a,b,c (a,c)=b,已知a,b求c
- document.getElementById的一些细节
- KDJ指标及其应用
- 转行做程序员的历程
- Java多线程详解--转载
- 从nand的启动的uboot
- w%r指标及其应用
- MACD指标及其应用
- 去除NSString字符串的前后空格和换行符
- socket学习 同步
- Nutch 的命令
- 时间复杂度分析
- C#导出txt
- c# winform 程序打包部署