Android教程網
  1. 首頁
  2. Android 技術
  3. Android 手機
  4. Android 系統教程
  5. Android 游戲
 Android教程網 >> Android技術 >> 關於Android編程 >> 移植u-boot2012.04.1 -》2440 (五)支持 nand nor 兩種啟動方式(完結)

移植u-boot2012.04.1 -》2440 (五)支持 nand nor 兩種啟動方式(完結)

編輯:關於Android編程

前邊4篇文章,成功將 u-boot2012 移植到了 2440 開發板上,但是它僅僅支持 norflash 啟動並不夠完善,下面我們設法讓它支持兩種啟動方式。

首先,我們得先分析一下目前的啟動流程:

鏈接地址為 0

第一階段:start.S中的匯編部分,包括時鐘、sdram 等初始化

第二階段:board_init_f 先是調用了大量C函數進行串口什麼的初始化,然後進行內存劃分

第三階段:根據第二階段的內存劃分 start.S 中進行代碼重定位,清BSS,修正位置有關碼,跳到sdram裡去執行board_init_r

那麼,如果我們想 nandflash 啟動,那麼我們必須在前4K代碼中就進行 nandflash 的初始化,用nandflash的讀函數將代碼進行重定位到sdram裡,現在有一個矛盾擺在我們面前。首先是,原來的重定位的地方在第三階段,而且第二階段調用了大量的C函數,重定位的時候早就在 4K 之外了。如果我們把重定位放在第一階段和第二階段之間,那麼那時內存還沒有進行劃分,我們不知道重定位到哪裡去。

解決辦法:采用 uboot1.1.6 那種老的方式,在第一階段和第二階段之間進行重定位,重定位到固定地址 0x33f00000 中去,第二階段進行內存劃分時,將u-boot的起始地址也固定為 0x33f0000 ,在鏈接時,指定鏈接地址為0x33f00000,這樣,我們也可以去掉 *.rel 段,實際上是去掉編譯時的 -pie 選項。

還有一個問題,我們nandflash啟動時,norflash對cpu是不可見的,因此我們根本無法對Norflash進行初始化,更無法將環境變量保存在Norflash上了。

解決辦法:判斷如果是nandflash啟動,不進行Norflash的初始化。無論那種方式啟動,均將環境變量保存在nandflash上。

1、去掉 -pie 選項

grep "\-pie" * -nRw

arch/arm/config.mk:75:LDFLAGS_u-boot += -pie

直接注釋掉即可。

2、指定鏈接地址

grep "Ttext" * -nRw

找到一個宏CONFIG_SYS_TEXT_BASE 搜索這個宏,發現是在 smdk2440.h 中定義,修改為

#defineCONFIG_SYS_TEXT_BASE 0x33f00000

3、在第二階段內存劃分時,固定u-boot的起始地址

在 arch/aem/lib/board.c 中的

addr -= gd->mon_len;
addr &= ~(4096 - 1); 這兩行後邊,新增一行
addr = 0x33f00000;//增加

4、實現判斷 nor 啟動還是 nand 啟動的 C 函數

nor啟動時,片內ram位於0x40000000處,可以直接讀寫,0-2M的空間可以直接讀,但是沒法直接寫入。

nand啟動時,片內ram位於0x0處,0-4k,可以直接讀寫。

我一開始嘗試在 0x40000000 處寫值,然後讀取回來看是否成功,發現 nand 啟動時訪問0x40000000會觸發異常直接死掉。那麼只好嘗試讀寫0地址了。

 

int isNandBoot(){
#define     RAMSTART  	(*(volatile unsigned long *)0x00000000)
	unsigned long temp = RAMSTART;
	RAMSTART = 0xbadc0de;
	if(RAMSTART == 0xbadc0de){
		RAMSTART = temp;
		return 1;
	}else{
		RAMSTART = temp;
		return 0;
	}
}
nand啟動返回1,Nor啟動返回0

 

5、將nandflash的初始化函數、讀函數和上邊的判斷函數統一放入 smdk2440.c 中,同時,我們需要改變鏈接順序,將 smdk2440.o 盡量靠前放,索性放在 start.o 的後邊好了。但是經過我的嘗試,smdk2440.c 和lowlevel_init.S 會被鏈接成libsmdk2440.o ,只把smdk2440.o放到前面的話,會造成函數的重定義,解決辦法就是把libsmdk2440.o 放到前邊。

更改鏈接腳本:/arc/arm/cpu/u-boot.lds

在CPUDIR/start.o (.text) 後邊添加一行
board/samsung/smdk2440/libsmdk2440.o (.text)

嘗試編譯一下,正常應該沒問題。

6、在第一階段和第二階段之間增加代碼重定位等相關操作

 

#ifndef CONFIG_SKIP_LOWLEVEL_INIT
	bl	cpu_init_crit
#endif
/******************此行之前的代碼保持不變,增加*************************/
	ldr	sp, =(CONFIG_SYS_INIT_SP_ADDR)
	bic	sp, sp, #7 /* 8-byte alignment for ABI compliance */

	
	/* 判斷是 nand 還是 nor 啟動 */
	bl isNandBoot
	mov r1,#0x01
	cmp r0,r1
	bne copy_nor		/* 不相等nor 相等nand*/
	
copy_nand:
	bl my_nand_init
	ldr r0, =0x33f00000
	mov r1, #0x00
	ldr r2, =_bss_start_ofs
	bl my_nand_read
	bl  	clear_bss
	
copy_nor:
	mov	r0, #0x00
	ldr	r1, =0x33f00000	/* r1 <- scratch for copy_loop */
	ldr	r3, _bss_start_ofs
	add	r2, r0, r3		/* r2 <- source end address	    */
	
copy_loop:
	ldmia	r0!, {r9-r10}		/* copy from source address [r0]    */
	stmia	r1!, {r9-r10}		/* copy to   target address [r1]    */
	cmp	r0, r2			/* until source end address [r2]    */
	blo	copy_loop
	bl  	clear_bss
/*****************call_board_init_f 中去掉sp的設置***********************/	
call_board_init_f:
	
	ldr	r0,=0x00000000
	bl	board_init_f
	
/*************** 將 clear_bss 提升至 relocate_code 的前面****************/
clear_bss:
#ifndef CONFIG_SPL_BUILD
	ldr	r0, _bss_start_ofs
	ldr	r1, _bss_end_ofs
	ldr	r4, =0x33f00000			/* reloc addr */
	add	r0, r0, r4
	add	r1, r1, r4
	mov	r2, #0x00000000		/* clear			    */

clbss_l:str	r2, [r0]		/* clear loop...		    */
	add	r0, r0, #4
	cmp	r0, r1
	bne	clbss_l
	ldr 	pc, =call_board_init_f  // 增加跳轉到sdram的指令
#endif
/*************** 去掉原有的代碼重定位操作****************/
	.globl	relocate_code
relocate_code:
	mov	r4, r0	/* save addr_sp */
	mov	r5, r1	/* save addr of gd */
	mov	r6, r2	/* save addr of destination */
	mov sp, r0  /* 設置棧 */  

	/* setup parameters for board_init_r */
	mov	r0, r5		/* gd_t */
	mov	r1, r6		/* dest_addr */
	/* jump to it ... */
	bl	board_init_r


/*
 ***********************之後代碼保持不變**********************************
 *
 * CPU_init_critical registers
 *
 * setup important registers
 * setup memory timing
 *
 *************************************************************************
 */
7、在norflash初始化代碼前,增加判斷
在arch\arm\lib\board.c ->board_init_r 中將

#if !defined(CONFIG_SYS_NO_FLASH) 作用域之內的代碼放入 if(!isNandBoot()) 條件語句。

8、將環境變量存儲到 nandflash

首先,我查看了一下 common 目錄下,env_flash.c 是被編譯進u-boot了,但是 env_nand.c 並沒有,看下makefile 它依賴於哪個宏。

COBJS-$(CONFIG_ENV_IS_IN_FLASH) += env_flash.o

COBJS-$(CONFIG_ENV_IS_IN_NAND) += env_nand.o

搜索一下,發現CONFIG_ENV_IS_IN_FLASH 在 smdk2440.h 中定義

去掉#define CONFIG_ENV_IS_IN_FLASH

增加#defineCONFIG_ENV_IS_IN_NAND

實際在編譯測試的過程中,只定義CONFIG_ENV_IS_IN_NAND 是不夠的,會打印出錯誤信息

Need to define CONFIG_ENV_OFFSET when using CONFIG_ENV_IS_IN_NAND

意思很明確,我們需要定義環境變量在 nandflash 中的偏移地址,如果對 u-boot 進行分區的話,環境變量應該是存在於 params 區域,為了和內核保持一致,我們干脆分區得了。

9、查看內核啟動打印信息

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

這是內核的分區劃分,我們按照內核的分區,也給 u-boot 進行分區。

添加分區,smdk2440.h 中要有一下宏定義:

#define CONFIG_CMD_MTDPARTS
#define CONFIG_MTD_DEVICE
#define CONFIG_MTD_PARTITIONS
加入MTD分區信息:
#define MTDIDS_DEFAULT "nand0=2440_nand"
#define MTDPARTS_DEFAULT "mtdparts=2440_nand:256k@0(bootloader)," \
"128k(params)," \
"2M(kernel)," \
"-(root)"

這個內核比較小,因此內核分區只有2M,如果內核比較大的話,在修改就是了。

環境變量的位置確定了,我們需要在smdk2440.h中定義偏移地址

#define CONFIG_ENV_OFFSET0x40000

同時,在smdk2440.h 中定義的CONFIG_ENV_SIZE 默認為0x10000 修改為 0x20000

10、剪裁u-boot

我嘗試nand啟動時,發現啟動不了,是因為我們的u-boot有400多K,而我們的 bootloader 只有256k,要麼修改分區,要麼剪裁u-boot,是它小於256k,如何剪裁,就是修改smdk2440.h宏咯。

在 smdk2440.h 中去掉

#define CONFIG_CMD_FAT
#define CONFIG_CMD_EXT2
#define CONFIG_CMD_UBI
#define CONFIG_CMD_UBIFS
#define CONFIG_YAFFS2
#define CONFIG_RBTREE
#define CONFIG_USB_OHCI
#define CONFIG_USB_KEYBOARD
#define CONFIG_USB_STORAGE
#define CONFIG_DOS_PARTITION
#define CONFIG_BOOTP_BOOTFILESIZE
#define CONFIG_BOOTP_BOOTPATH
#define CONFIG_BOOTP_GATEWAY
#define CONFIG_BOOTP_HOSTNAME
#define CONFIG_CMD_USB
#define CONFIG_CMD_BSP

make clean

make

編譯完你會發現體積大大減小,不到200K

11、燒寫測試,不出意外,我們的 nor nand 都能啟動了

\ 可以看到,我們的環境變量已經保存在 nandflash 中了,需要注意的是,我們需要使用 mtdparts default 命令將分區信息保存在環境變量中,才可以在命令中像使用變量一樣引用分區名字。如果是第一次劃分分區,或者擦出了 params 區,記得 mtdparts default 然後 save 一下。 12、修改機器ID u-boot 在引導內核時,會向內核傳遞機器ID,機器ID不對,直接無法啟動或者導致內核使用了其他單板的初始化函數,那麼 u-boot2012 的機器ID 在哪裡設置的呢? board\samsung\smdk2410\smdk2410.c ->board_init gd->bd->bi_arch_number = MACH_TYPE_SMDK2410; gd->bd->bi_boot_params = 0x30000100; 13、個性化修改 如果你想像上邊那幅圖一樣,控制台每一樣默認出現“MINI2440 #”該如何設置? 在 smdk2440.h 中,修改宏定義 #define CONFIG_SYS_PROMPT"MIMI2440 # " 14、制作補丁文件 將修改好的u-boot2012文件夾重命名為 u-boot2012.04.1_OK 然後再解壓一份源碼 制作補丁前先清理生成的文件: make clean rm u-boot u-boot.bin u-boot.map u-boot.srec System.map find -name "*.depend*"|rm -rf diff -urNu-boot2012.04.1u-boot2012.04.1_OK u-boot2012.04.1.patch   OK ,整個 u-boot2012 的移植工作至此告一段落~,移植耗時2天,整理博客用了一天半~~醉醉的。
  1. 上一頁:
  2. 下一頁:
熱門文章
閱讀排行版
Copyright © Android教程網 All Rights Reserved