編輯:關於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初始化代碼前,增加判斷
#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天,整理博客用了一天半~~醉醉的。自己剛學Android的時候在這上面花了不少時間,資料沒少找。學習別人的“關鍵代碼”,自己寫起來不是缺這就是缺那的。希望後來的同學在這上面少浪費些時間。 其實很簡單,就是
什麼是dex文件他是Android系統的可執行文件,包含應用程序的全部操作指令以及運行時數據。由於dalvik是一種針對嵌入式設備而特殊設計的java虛擬機,所以dex文
1.介紹MPAndroidChart GitHub地址 MPAndroidChart的強大之處就不在多說了,目前最新的版本是3.0.1,在新版本中很多方法都被
在這裡先看看效果圖: OK,有時候,在我們的項目中會要求TextView中文本有一部分的字體顏色不一樣,這時我們應該使用 SpannableStrin