S3C2440移植U-BOOT

目录

一、移植高版本u-boot

二、u-boot启动过程概述

三、修改u-boot大致过程

修改时钟、SDRAM、UART

修改u-boot支持nand启动

修改u-boot支持nor flash

修改u-boot支持nand flash读写操作 

修改u-boot支持DM9000

u-boot裁剪并修改默认参数 

支持yaffs与制作补丁

利用补丁直接使用新u-boot


一、移植高版本u-boot

u-boot下载地址:http://www.denx.de/wiki/U-Boot/SourceCode,这里移植2012.04.01版本的u-boot,解压过程如下

tar xjf u-boot-2012.04.01.tar.bz2
cd u-boot-2012.04.01
make smdk2410_config
make

如果gcc版本过低需要在解压之前需要高版本的gcc编译器,添加在根目录后,需要环境变量添加/usr/local/arm/4.3.2/bin,如果不想每次都修改环境变量的话,修改sudo vi /etc/environment后重启

sudo tar xjf arm-linux-gcc-4.3.2.tar.bz2 -C / 
sudo vi /etc/environment

用source insight查看u-boot目录代码,在其目录下添加一个si目录并新建一个工程,工程建立过程,先全部.c,.h,.S加载进去,会弹出两个选项都加上,第二个选项是递归添加,根据下面步骤后同步一下文件

  1. 先处理board(单板)目录,先整个去掉,而只关心samsung/sdmd2410中全部添加
  2. arch目录,先整个去掉,只关心arm目录:在arm目录中先处理cpu目录,对于2440来说是arm920t,只关心里面的s3c24x0目录和其他文件(添加的时候把勾都去掉),再添加dts、lib目录,include目录中只关心我们的arch-s3c24x0还有其他通用的文件(添加的时候把勾都去掉),还有asm目录
  3. include目录,整个去掉,在顶层目录中的文件全部添加,目录只留configs不添加,configs目录中表示各个单板的配置,只关心我们的smdk2410.h

将新版u-boot烧写到2440上无反应,需要我们进一步修改代码

二、u-boot启动过程概述

rm boot,重新编译make,根据最后一条链接命令可以知道u-boot的组成部分是怎么样的

arm-linux-ld  -pie -T u-boot.lds -Bstatic -Ttext 0x0 $UNDEF_SYM arch/arm/cpu/arm920t/start.o...

在u-boot.lds,链接地址是0,因此只能从nor flash运行

OUTPUT_FORMAT("elf32-littlearm", "elf32-littlearm", "elf32-littlearm")
  2 OUTPUT_ARCH(arm)
  3 ENTRY(_start)
  4 SECTIONS
  5 {
  6  . = 0x00000000;
  7  . = ALIGN(4);
  8  .text :
  9  {
 10   __image_copy_start = .;
 11   arch/arm/cpu/arm920t/start.o (.text)
 12   *(.text)
 13  }
 14  . = ALIGN(4);
 15  .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
 16  . = ALIGN(4);
 17  .data : {
 ...

对于之前自己的u-boot启动过程如下, 进而来分析arch/arm/cpu/arm920t/start.c

a. 初始化硬件:关看门狗、设置时钟、设置SDRAM、初始化NAND FLASH
b. 如果bootloader比较大,要把它重定位到SDRAM
c. 把内核从NAND FLASH读到SDRAM
d. 设置"要传给内核的参数"
e. 跳转执行内核

 在start.c中有些宏我们可以通过反汇编u-boot来查看

arm-linux-objdump -D u-boot > u-boot.dis

 分析2012版u-boot,大概过程

2.1 set the cpu to SVC32 mode  //设置为管理模式
2.2 turn off the watchdog  //关看门狗
2.3 mask all IRQs by setting all bits in the INTMR  //屏蔽中断
2.4 设置时钟比例                        
2.5 设置内存控制器  //cpu底层初始化
2.6 设置栈,调用C函数board_init_f       
2.7 调用函数数组init_sequence里的各个函数   

设置栈的值为30000f80,调用C函数board_init_f,在board_init_f.c中有个宏,这种格式定义一个寄存器变量,因此读gd的值的实际上就是读r8的值,在编译程序的时候有个-ffixed-r8(固定的r8参数),即编译的时候不用r8保留r8不变留给程序使用

/* Set stackpointer in internal RAM to call board_init_f */
call_board_init_f:
	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */
	ldr	r0,=0x00000000
	bl	board_init_f

-----------------------------------------------------------------
board_init_f.c
#define DECLARE_GLOBAL_DATA_PTR     register volatile gd_t *gd asm ("r8")

在board_init_f.c中,gd一开始指向30000f80,而sp也指向30000f80,对于栈是往下增长的, 因此这一块不会冲突,根据gd和反汇编可以推算出内存的大致分配,其中到最后执行了重定位代码relocate_code函数,在链接地址中是从0开始,这里还继续重定位,在此u-boot加入了另外一个技巧,在链接的时候加上了-pie选项,查看pie选项,链接的时候生成位置无关可执行程序,加上pie选项后,那些重定位变量函数地址就会生成信息然后放在段中,relocate_code是以汇编实现的,实现了将程序复制到内存中,并且将地址修改为新地址

relocate_code(addr_sp, id, addr);
------------------------------------------------
arm-linux-ld --help | grep pie
 -pie, --pic-executable      Create a position independent executable   

分析反汇编,其中1表示第一个循环

#ifndef CONFIG_SPL_BUILD
	/*
	 * fix .rel.dyn relocations
	 */
	ldr	r0, _TEXT_BASE		/* r0 <- Text base */  // r0=0, 代码基地址	
	sub	r9, r6, r0		/* r9 <- relocation offset */  // r9 = r6-r0 = 0x33f41000 - 0 = 0x33f41000
	ldr	r10, _dynsym_start_ofs	/* r10 <- sym table ofs */   // r10 = 00073608 动态符号表的地址 	
	add	r10, r10, r0		/* r10 <- sym table in FLASH */  // r10 = 00073608 + 0 = 00073608		
	ldr	r2, _rel_dyn_start_ofs	/* r2 <- rel dyn start ofs */  // r2=0006b568		
	add	r2, r2, r0		/* r2 <- rel dyn start in FLASH */  // r2=r2+r0=0006b568
	ldr	r3, _rel_dyn_end_ofs	/* r3 <- rel dyn end ofs */  // r3=00073608	
	add	r3, r3, r0		/* r3 <- rel dyn end in FLASH */  // r3=r3+r0=00073608	
	
fixloop: //把原来的地址改为新地址 
	ldr	r0, [r2]		/* r0 <- location to fix up, IN FLASH! */
	1. r0=[0006b568]=00000020
	add	r0, r0, r9		/* r0 <- location to fix up in RAM */
	1. r0=r0+r9=00000020 + 0x33f41000 = 0x33f41020
	ldr	r1, [r2, #4]
	1. r1=[0006b568+4]=00000017
	and	r7, r1, #0xff
	1. r7=r1&0xff=00000017	
	cmp	r7, #23			/* relative fixup? */
	1. r7 == 23(0x17)	
	beq	fixrel
	cmp	r7, #2			/* absolute fixup? */	
	beq	fixabs
	/* ignore unknown type of fixup */
	b	fixnext
fixabs:
	/* absolute fix: set location to (offset) symbol value */
	mov	r1, r1, LSR #4		/* r1 <- symbol index in .dynsym */	
	add	r1, r10, r1		/* r1 <- address of symbol in table */
	ldr	r1, [r1, #4]		/* r1 <- symbol value */
	add	r1, r1, r9		/* r1 <- relocated sym addr */
	b	fixnext
fixrel:
	/* relative fix: increase location by offset */
	ldr	r1, [r0]
	1. r1=[00000020]=000001e0	
	add	r1, r1, r9
	1. r1=r1+r9=000001e0 + 0x33f41000 = 33F411E0
	
fixnext:
	str	r1, [r0]
	1. [0x33f41020] = 33F411E0	
	add	r2, r2, #8		/* each rel.dyn entry is 8 bytes */
	1. r2=r2+8=0006b568+8=6B570
	cmp	r2, r3
	1. 
	blo	fixloop
#endif

过程大致如下,这种重定位的方法需要在程序中保留地址的信息,会使程序加大

2.8 重定位代码:  
2.8.1 从NOR FLASH把代码复制到SDRAM
2.8.2 程序的链接地址是0,访问全局变量、静态变量、调用函数时是使"基于0地址编译得到的地址"
      现在把程序复制到了SDRAM
      需要修改代码,把"基于0地址编译得到的地址"改为新地址
2.8.3 程序里有些地址在链接时不能确定,要到运行前才能确定:fixabs
2.9 clear_bss
2.10 调用C函数board_init_r:第2阶段的代码

三、修改u-boot大致过程

修改时钟、SDRAM、UART

对于u-boot中没有支持2440的单板,只有2410,但2440与2410相似,因此可以在2410的基础上修改,在u-boot目录下复制2410来新建一个2440单板

cd board/samsung/
cp smdk2410 smdk2440 -rf
cd ../../include/configs/
cp smdk2410.h smdk2440.h

执行make smdk2440_config的还需要修改boards.cfg

仿照
smdk2410                     arm         arm920t     -                   samsung        s3c24x0
添加:
smdk2440                     arm         arm920t     -                   samsung        s3c24x0

UBOOT里先以60MHZ的时钟计算参数来设置内存控制器,但是MPLL还未设置,把MPLL的设置放到start.S里,取消board_early_init_f里对MPLL的设置,编译出来的uboot非常大,可以先烧写之前的u-boot.bin到nor flash,然后用这个uboot来烧写新的uboot,对于之前的u-boot分区不够大,因此利用DNW(usb)来下载

usb 1 30000000
protect off all        //把nor flahs的写保护去掉
erase 0 7FFFF          //512K第一个参数为开始地址,第二个参数为结束地址
cp.b 30000000 0 80000  //把30000000烧到0地址,烧写大小80000

主要修改思路:启动新的u-boot,发现没有任何反应,利用JTAG调试工具,进行调试,在SDRAM内存的地址读写,读写结果不一样,因此还要修改SDRAM的初始化;修改完后发现u-boot可以启动,但是出现乱码,查看串口波特率的设置,发现在get_HCLK里没有定义CONFIG_S3C2440,在include/configs/smdk2440.h中去掉CONFIG_S3C2410,定义#define CONFIG_S3C2440,重新编译u-boot发现nand的错误,这里先不使用nand,在drivers/mtd/nand/Makefile,只有定义了CONFIG_CMD_NAND,s3c2410_nand.c才会被编译,一样在smdk2440.h中去掉CONFIG_CMD_NAND

S3C2440移植U-BOOT_第1张图片

一样需要先烧写之前的u-boot利用DNW来烧写新的u-boot,重启开发板后串口就输出了

修改u-boot支持nand启动

原来的代码在链接时加了"-pie"选项, 使得u-boot.bin里多了"*(.rel*)", "*(.dynsym)",使得程序非常大,不利于从NAND启动(重定位之前的启动代码应该少于4K),去掉 "-pie"选项

arch/arm/config.mk:75:LDFLAGS_u-boot += -pie 去掉这行

 以下方法可以固定住地址,如果,如果使用起始地址_start来,_start复杂的话ldr伪指令会先把它存在一个无法掌握的地址,此地址由编译器决定的,对nand来说有可能存在4k之外,把链接地址定在0x33f80000的位置,对于SDRAM是64M,0x34000000相差512K,一般u-boot不会超过这么大

start.S
.globl _TEXT_BASE
_TEXT_BASE:
	.word	CONFIG_SYS_TEXT_BASE
-----------------------------------------------------

smdk2440.h
//#define CONFIG_SYS_TEXT_BASE 0
#define CONFIG_SYS_TEXT_BASE 0x33f80000

在start.S中先初始化nand,再拷贝程序到0x33f80000的位置,然后跳到SDRAM中执行,在call_board_init_f中有实现重定位的代码,因此把relocate_code去掉

ldr sp,=(CONFIG sYs INIT SP ADDR) /*sp = 30000f80*/
bic sp,sp,#7  /*8-byte alignment for ABI compliance*/
bl nand_init_ll

mov r0, #0

//ldr r1, =_start
ldr r1,_TEXT_BASE

ldr r2,_bss_start_ofs

bl copy_code_to_sdram
bl clear_bss

ldr pc, =call_board_init_f

初始化nand为自己实现的init.c,因此需要把init.c放入board/samsung/smdk2440目录, 修改Makefile,在C文件后面添加init.o

COBJS  := smdk2410.o init.o

修改链接脚本 /arch/arm/cpu/u-boot.lds,在board/samsung/smdk2440/libsmdk2440.c会将c文件编译进这个库中,因此只需要在u-boot.lds前面加入libsmdk2440.c的text段

在start.s中第二阶段会执行board_init_r,需要id参数还有目标地址,其id参数在第一阶段board_init_f中relocate_code代码重定位的参数,因此在board_init_f中返回其id,还需要修改内存分步中u-boot存储的空间,直接定死为CONFIG_SYS_TEXT_BASE

call board_init_f:
ldr r0,=0x00000000
bl boardlinit_f

/* unsigned int的值存在r0里,正好给board_init_r */

ldr r1,_TEXT_BASE  //参数二需要修改后重定位的位置

/*调用第2阶段的代码*/
bl board_init_r

重新编译后反汇编查看bss到起始地超过700K,因此需要修改重定位的基地址0x33f80000改为0x33f00000,留1M的空间

修改u-boot支持nor flash

drivers\mtd\jedec_flash.c 加上新的型号,#define CONFIG_SYS_MAX_FLASH_SECT    (128),修复重定位留下来的bug:SP要重新设置(在内存分布中新u-boot对栈设置了两次),重新编译,利用新的u-boot烧写修改的flash,由于没有设置网卡,因此利用PC端的串口超级终端进行烧写,在u-boot中有loady可以利用串口来烧写,测试nor

protect off all
erase 80000 8ffff
cp.b 30000000 80000 10000  
cmp.b 30000000 80000 10000

修改u-boot支持nand flash读写操作 

让nand支持读写操作,修改:include/configs/smdk2440.h:把之前的宏重新定义上#define CONFIG_CMD_NAND,把drivers\mtd\nand\s3c2410_nand.c复制为s3c2440_nand.c


分析过程:
nand_init
    nand_init_chip
        board_nand_init
            设置nand_chip结构体, 提供底层的操作函数
        nand_scan
            nand_scan_ident
                nand_set_defaults
                    chip->select_chip = nand_select_chip;
                    chip->cmdfunc = nand_command;
                    chip->read_byte = busw ? nand_read_byte16 : nand_read_byte;
                    
                nand_get_flash_type
                    chip->select_chip  //默认函数不适合,自己写
                    chip->cmdfunc(mtd, NAND_CMD_RESET, -1, -1);
                            nand_command()  // 即可以用来发命令,也可以用来发列地址(页内地址)、行地址(哪一页)
                                chip->cmd_ctrl
                                        s3c2440_hwcontrol //修改默认函数,实现读写操作nand控制器
                                
                    chip->cmdfunc(mtd, NAND_CMD_READID, 0x00, -1);
                    *maf_id = chip->read_byte(mtd);
                    *dev_id = chip->read_byte(mtd);

利用修改的u-boot(nor启动)测试

nand erase 0 80000 //擦除nand从0到80000
nand write 0 0 80000 //烧写从片内0到nand的0一共80000
nand read 30000000 0 80000 //总nand的0读到30000000
cmp.b 0 30000000 80000

修改u-boot支持DM9000

在u-boot已经支持DM9000,修改配置文件把DM9000编译到,dm9000x.c在drivers/net中,在该目录的Makfile搜索,dm9000x,需要定义CONFIG_DRIVER_DM9000来支持DM9000

COBJS-$(CONFIG_DRIVER_DM9000) += dm9000x.o

在smdk2440.h把CS8900(2400上的网卡为DM9000没有CS8900)去掉加上CONFIG_DRIVER_DM9000

if 0
#define CONFIG_CS8900		/* we have a CS8900 on-board */
#define CONFIG_CS8900_BASE	0x19000300
#define CONFIG_CS8900_BUS16	/* the Linux driver does accesses as shorts */
#else
#define CONFIG_DRIVER_DM9000
#endif

重新编译u-boot,在错误中提示还需要定义DM9000_DATA,在u-boot目录中搜索DM9000_DATA,参考别的单板是怎么设置的,复制过来修改,对于2400来说设置DM9000分两步,设置内存控制器(时序、位宽)、确定访问地址,CONFIG_DM9000_BASE对于2400是0x20000000,其中ADDR2是用接到网卡的CMD,ADDR2对应bit2因此加上4

#define CONFIG_DRIVER_DM9000
#define CONFIG_DM9000_BASE               0x20000000
#define DM9000_IO                       CONFIG_DM9000_BASE
#define DM9000_DATA                       (CONFIG_DM9000_BASE + 4)

 还需要根据网卡芯片手册时序设置内存控制器,修改start.S中CPU初始化内存控制器

S3C2440移植U-BOOT_第2张图片

用PC的超级终端下载新u-boot到30000000,再从30000000拷贝0,重启打印出Net : No ethernet found,在u-boot目录中搜索"Net:",可以追踪到board_eth_init没有初始化SDRAM

board.c
	puts("Net:   ");
	eth_initialize(gd->bd);
#if defined(CONFIG_RESET_PHY_R)
	debug("Reset Ethernet PHY\n");
	reset_phy();

------------------------------------------------------
int eth_initialize(bd_t *bis)
{
	int num_devices = 0;
	eth_devices = NULL;
	eth_current = NULL;

	bootstage_mark(BOOTSTAGE_ID_NET_ETH_START);
#if defined(CONFIG_MII) || defined(CONFIG_CMD_MII)
	miiphy_init();
#endif

#ifdef CONFIG_PHYLIB
	phy_init();
#endif

	/*
	 * If board-specific initialization exists, call it.
	 * If not, call a CPU-specific one
	 */
	if (board_eth_init != __def_eth_init) {
		if (board_eth_init(bis) < 0)
			printf("Board Net Initialization Failed\n");
	} else if (cpu_eth_init != __def_eth_init) {
		if (cpu_eth_init(bis) < 0)
			printf("CPU Net Initialization Failed\n");
	} else
		printf("Net Initialization Skipped\n");

	if (!eth_devices) {
		puts ("No ethernet found.\n");
		bootstage_error(BOOTSTAGE_ID_NET_ETH_START);

------------------------------------------------------

int board_eth_init(bd_t *bis)
{
	int rc = 0;
#ifdef CONFIG_CS8900
	rc = cs8900_initialize(0, CONFIG_CS8900_BASE);
#endif
	return rc;
}
#endif

在dm9000x.c中搜索dm9000_initialize,需要将其添加到board_eth_init中

int dm9000_initialize(bd_t *bis)
{
	struct eth_device *dev = &(dm9000_info.netdev);

	/* Load MAC address from EEPROM */
	dm9000_get_enetaddr(dev);

	dev->init = dm9000_init;
	dev->halt = dm9000_halt;
	dev->send = dm9000_send;
	dev->recv = dm9000_rx;
	sprintf(dev->name, "dm9000");

	eth_register(dev);

	return 0;
}

在u-boot中搜索别的单板是怎么使用dm9000_initialize的,修改board_eth_init

int board_eth_init(bd_t *bis)
{
	int rc = 0;
#ifdef CONFIG_CS8900
	rc = cs8900_e(0, CONFIG_CS8900_BASE);
#endif
	return rc;

#ifdef CONFIG_DRIVER_DM9000
		rc = dm9000_initialize(bis);
#endif
		return rc;

}

编译并启动新u-boot,想ping通同一网段需要设置ipaddr、thaddr,想要远程烧录需要设置serverip

*** ERROR: `ethaddr' not set
set ipaddr 192.168.0.19
set ethaddr 00:0c:29:ba:fc:c1   //参考ubuntu的HWaddr
set serverip 192.168.0.104

这样就可以利用tftp来烧写,设置工作目录就可以在新的u-boot执行tftp命令烧写

 S3C2440移植U-BOOT_第3张图片

u-boot裁剪并修改默认参数 

在u-boot设置ipaddr、thaddr等称为环境变量,u-boot启动的时候会先读这些参数,判断是否有效,有效则用,无效则用默认参数,在env_common.c设置默认环境变量,bootargs是传给内核的参数,u-boot根据bootcmd命令来启动内核

const uchar default_environment[] = {
#ifdef	CONFIG_BOOTARGS
	"bootargs="	CONFIG_BOOTARGS			"\0"
#endif
#ifdef	CONFIG_BOOTCOMMAND
	"bootcmd="	CONFIG_BOOTCOMMAND		"\0"
#endif
#ifdef	CONFIG_RAMBOOTCOMMAND
	"ramboot="	CONFIG_RAMBOOTCOMMAND		"\0"
#endif
#ifdef	CONFIG_NFSBOOTCOMMAND
	"nfsboot="	CONFIG_NFSBOOTCOMMAND		"\0"
#endif
#if defined(CONFIG_BOOTDELAY) && (CONFIG_BOOTDELAY >= 0)
	"bootdelay="	MK_STR(CONFIG_BOOTDELAY)	"\0"
#endif
#if defined(CONFIG_BAUDRATE) && (CONFIG_BAUDRATE >= 0)
	"baudrate="	MK_STR(CONFIG_BAUDRATE)		"\0"
#endif
#ifdef	CONFIG_LOADS_ECHO
	"loads_echo="	MK_STR(CONFIG_LOADS_ECHO)	"\0"
#endif
.....

先将nand flash规划为4个区域:boot、参数、内核、文件系统,由于还没设置参数保留在哪里,所在在u-boot中设置参数不能用save命令,否则可能破坏nand flash内容,在smdk2440.h中定义参数的默认值,由于还没规划分区,先nand read的时候地址先保留着

#define CONFIG_BOOTARGS "console=ttySAS0 root=/dev/mtdblock3"
#define CONFIG_BOOTCOMMAND "nand read 30000000 0xabc 0x200000;bootm 30000000" //从0xabc读200000到30000000
#define CONFIG_NETMASK          255.255.255.0
#define CONFIG_IPADDR           192.168.0.19
#define CONFIG_SERVERIP         192.168.0.104
#define CONFIG_ETHADDR      00:0c:29:ba:fc:c1

裁剪u-boot主要是在smdk2440.h中将不需要的宏去掉,重新编译u-boot会发现u-boot变小很多在smdk2440.h,环境变量的地址,我们不知道怎么设置,根据save命令的帮助信息来找到对应的文件,根据文件来确定用什么宏

if 0
#define CONFIG_ENV_ADDR                 (CONFIG_SYS_FLASH_BASE + 0x070000)
#define CONFIG_ENV_IS_IN_FLASH
#define CONFIG_ENV_SIZE                 0x10000
/* allow to overwrite serial and ethaddr */
#define CONFIG_ENV_OVERWRITE
#endif 

SMDK2410 # ? save
saveenv - save environment variables to persistent storage

Usage:
saveenv 

 搜索saveenv就可以搜索到env_nand.c,在common目录的makefile查看需要定义CONFIG_ENV_IS_IN_NAND宏

env_nand.c (common) line 226 : int saveenv(void)

COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o

根据env_nand.c来设置这些宏,CONFIG_ENV_OFFSET表示偏移值,CONFIG_ENV_SIZE表示块的大小,对于nand flash来说一个块最小128K,CONFIG_ENV_RANGE为擦除大小

212 #define CONFIG_ENV_IS_IN_NAND
213 #define CONFIG_ENV_OFFSET      0x00040000
214 #define CONFIG_ENV_SIZE        0x20000
215 #define CONFIG_ENV_RANGE       CONFIG_ENV_SIZE

加载新u-boot,会出现倒数计时,因为设置bootcmd,在计时前如果没按下空格,就会执行bootcmd启动内核,这个时候就可以用save命令保存参数了

在smdk2440.h定义分区如下,只是用宏来代替,并不会对内核产生影响,对于u-boot中mtd_parts命令需要设置相关的宏,并且根据mtd_parts的帮助信息还需要在单板中调用run_command("mtdparts default", 0)

0x00000000-0x00040000 : "bootloader"
0x00040000-0x00060000 : "params"
0x00060000-0x00260000 : "kernel"
0x00260000-0x10000000 : "root"

217 #define CONFIG_CMD_MTDPARTS
218 #define CONFIG_MTD_DEVICE   //根据错误查找需要定义这个宏
219 #define MTDIDS_DEFAULT          "nand0=jz2440-0"  /* 表示哪一个设备 */
220 #define MTDPARTS_DEFAULT        "mtdparts=jz2440-0:256k(u-boot),"       \
221                                                 "128k(params),"         \
222                                                 "2m(kernel),"   \
223                                                 "-(rootfs)"             \  /* 表示剩下的区域 */

 执行nand erase.part kernel就可以直接擦除kernel分区了,同时可以设置bootcmd从哪里烧写kernel到SDRAM

tftp 30000000 uImage
nand erase.part kernel
nand write 30000000 kernel 

set bootcmd 'nand read 30000000 kernel 0x200000;bootm 30000000'

支持yaffs与制作补丁

对于jffs2文件系统,需要在bootargs中添加rootfstype=jffs2,3b8e30是烧写jffs2文件的大小

set bootargs console=ttySAC0,115200 root=/dev/mtdblock3 rootfstype=jffs2  

tftp 30000000 uImage_new; nand erase.part kernel ; nand write 30000000 kernel 
tftp 30000000 fs_mini_mdev_new.jffs2; nand erase.part rootfs; nand write.jffs2 30000000 0x00260000 3b8e30

对于yaffs,需要在cmd_nand.c表示需要定义CONFIG_CMD_NAND_YAFFS这个宏,同理需要在配置文件中定义

#endif
#ifdef CONFIG_CMD_NAND_YAFFS
		} else if (!strcmp(s, ".yaffs")) {
			if (read) {
				printf("Unknown nand command suffix '%s'.\n", s);
				return 1;
			}

在nand_util.c中,判断位写错了,oob不对应导致yaffs只能烧写一页

				rval = nand->write_oob(nand, offset, &ops);
				if (rval)  //原本是if(!rval)
					break;

这样就可以烧写yaffs2文件系统,其中791340表示tftp烧写yaffs2文件系统

tftp 30000000 fs_mini_mdev_new.yaffs2; nand erase.part rootfs; nand write.yaffs 30000000 260000 791340 

制作补丁

    1.make distclean, rm u-boot.dis (保留u-boot目录原样
    2.将u-boot-2012.04.01命名为u-boot-2012.04.01_100ask
    3.解压u-boot-2012.04.01
    4.对比制作补丁
    diff -urN u-boot-2012.04.01 u-boot-2012.04.01_100ask > u-boot-2012.04.01_100ask.patch

利用补丁直接使用新u-boot

tar xjf u-boot-2012.04.01.tar.bz2
cd u-boot-2012.04.01
patch -p1 < ../u-boot-2012.04.01_100ask.patch
将u-boot.bin烧写在nor或者nand都可以
set bootargs console=ttySAC0,115200 root=/dev/mtdblock3
set bootcmd 'nand read 30000000 kernel 0x200000;bootm 30000000' //需要先把内核烧写在0x60000-0x260000的地方,这里有kernel代替

 

 

 

你可能感兴趣的:(Linux驱动)