編輯:關於Android編程
前面分析過 u-boot1.1.6 三個階段的啟動過程,也嘗試自己寫了一個簡單的 bootloader ,是時候嘗試移植一個相對較新一點的 u-boot 了,看過韋東山老師移植 u-boot2012 的教學視頻,我決定按照自己的思路來移植它。
u-boot:u-boot2012.04.1
開發板:MINI2440 ,天下 2440 都一樣
編譯器:4.3.2
2440 平台在移植時,均參考 SMDK2410 ,以它作為母版進行修改,所以,我們需要對 SMDK2410 在 u-boot 中的代碼非常熟悉,才能做到移植起來得心應手,沒有別的好辦法,移植之前先進行分析,或者邊移植邊分析。u-boot2012相對於 u-boot1.1.6 有了哪些變化,對於 u-boot2012 的大框架,我們也是需要提前分析和了解的。移植之前的分析工作,請參考我之前的博客:http://blog.csdn.net/lizuobin2/article/details/52089474 ,最大的變化就是代碼的組織規則發生了變化,這裡簡單提一下:在老的 uboot 中,鏈接地址是固定的,是 uboot 跑在 sdram 的實際地址,而在 uboot2012 等較新的版本中,鏈接地址為 0 ,代碼重定位到 sdram 之後,更正位置有關碼,從而讓代碼正確執行。這樣一來,uboot中多了兩個段,體積增大,邏輯復雜。
由於 smdk2410 代碼默認只支持 Nor 啟動,那我們我們第一個目標,就是移植一個 支持 nor 啟動的u-boot ,采用默認的鏈接地址為 0 的方式(因為不用修改)。
一、創建單板
仿照 SMDK2410 創建我們自己的單板,SMDK2410 位於 board/samsung 目錄
cp -r board/samsung/smdk2410 board/samsung/smdk2440
cdboard/samsung/smdk2440
將 smdk2410.c 重命名為 smdk2440.c
修改該目錄下的 Makefile ,將 COBJS:= smdk2410.o 改為COBJS:= smdk2440.o
每一個單板都有一個配置相關的頭文件位於 include/configs 目錄
cp include/configs/smdk2410.h include/configs/smdk2440.h
修改 smdk2440.h 中#define CONFIG_S3C2410 為#define CONFIG_S3C2440 ,代碼中的宏開關
修改smdk2440.h 中#define CONFIG_SMDK2410 為#define CONFIG_SMDK2440 ,編譯時才會編譯我們所創建的smdk2440.c 文件
編譯之前要先配置,配置命令是 make $(boardname)_config 以 smdk2410 為例就是 make smdk2410_config
執行報錯!回想 uboot1.1.6 中,是在頂層的 makefile 中添加了一個配置選項如下:
smdk2410_config: unconfig
@$(MKCONFIG) $(@:_config=) arm arm920t smdk2410 NULL s3c24x0
那麼,我們也要做類似的修改,看了下 2012 的頂層 makefile ,沒有發現具體某個單板的配置選項,但是有這麼一行:
%_config:: unconfig
@$(MKCONFIG) -A $(@:_config=)
sinclude $(obj).boards.depend
$(obj).boards.depend: boards.cfg
大概的意思,配置選項依賴於 boards.cfg 這個文件,OK 打開看一看。
照葫蘆畫瓢,我們新增一行
smdk2410 arm arm920t - samsung s3c24x0
再來make smdk2410_config 一下,提示Configuring for smdk2440 board...
然後 make ,悲劇發生編譯不過
它說 s3c2410_get_base_nand 這個函數沒有聲明,打開drivers\mtd\nand\s3c2410_nand.c 查找錯誤,在s3c2410_hwcontrol 等4個函數中,都引用了struct s3c2410_nand *nand = s3c2410_get_base_nand();
s3c2410_get_base_nand 函數聲明在arch\arm\include\asm\arch-s3c24x0\s3c2410.h 中,而我們的單板是smdk2440.c ,那麼它引用的頭文件應該是arch\arm\include\asm\arch-s3c24x0\s3c2440.h
在 s3c2440.h 中,s3c2410_get_base_nand 已經更新為s3c2440_get_base_nand ,而且返回值類型為structs3c2440_nand ,這個結構體在 s3c2440.h 中聲明。
那麼,我們要做的就是在s3c2410_nand.c
將所有的struct s3c2410_nand *nand = s3c2410_get_base_nand()
改成 struct s3c2440_nand *nand = s3c2440_get_base_nand() ,共計 4 處
修改完 make 一下,你會發現還有一個類似的錯誤 ,依舊是在 s3c2410_nand.c 中
將board_nand_init 函數中struct s3c2410_nand *nand_reg = s3c2410_get_base_nand();
修改為struct s3c2440_nand *nand_reg = s3c2440_get_base_nand();
再來 make 一下,不出意外,編譯通過生成 u-boot.bin
檢查一下我們新建的單板目錄文件是否被編譯進去board/samsung/smdk2410 board/samsung/smdk2440
.o 文件已經生成,真是極好的,第一部分新建單板完成。
經過這一階段,我們也應該留意到struct s3c2410_nand 和struct s3c2440_nand 寄存器數目不同,我們在後邊對 nandflash 相關部分進行移植的時候還需要修改,這裡留意一下。
二、第一階段代碼移植
arch\arm\cpu\arm920t\start.S 是我們需要分析修改的第一個文件,做過裸機實驗的同學對這部分應該相當熟悉,要求改的內容不過是因為 2410 和 2440 的一些寄存器差異,我這裡是針對 mini2440 的修改,請結合自己的開發板進行移植(都差不多)。
1、中斷屏蔽
# if defined(CONFIG_S3C2400) # define pWTCON 0x15300000 # define INTMSK 0x14400008 /* Interrupt-Controller base addresses */ # define CLKDIVN 0x14800014 /* clock divisor register */ # elif defined(CONFIG_S3C2410) # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interrupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ # elif defined(CONFIG_S3C2440) //新增 # define pWTCON 0x53000000 # define INTMSK 0x4A000008 /* Interupt-Controller base addresses */ # define INTSUBMSK 0x4A00001C # define CLKDIVN 0x4C000014 /* clock divisor register */ # define MPLLCON 0x4C000004 # endif /* turn off the watchdog */ ldr r0, =pWTCON mov r1, #0x0 str r1, [r0] /* * mask all IRQs by setting all bits in the INTMR - default */ mov r1, #0xffffffff ldr r0, =INTMSK str r1, [r0] # if defined(CONFIG_S3C2410) ldr r1, =0x3ff ldr r0, =INTSUBMSK str r1, [r0] #elif defined(CONFIG_S3C2440)//新增 ldr r1, =0x7fff ldr r0, =INTSUBMSK str r1, [r0] # endif2、修改時鐘,這個是重點,時鐘不對的話後邊的串口 nandflash sdram 時序都會受到影響,這裡我們直接將FCLK 設置為 400MhzFCLK:HCLK:PCLK=1:4:8 ,HCLK 100Mhz PCLK 50Mhz
#if defined(CONFIG_S3C2400) || defined(CONFIG_S3C2410) //修改 /* FCLK:HCLK:PCLK = 1:2:4 */ /* default FCLK is 120 MHz ! */ ldr r0, =CLKDIVN mov r1, #3 str r1, [r0] #elif defined(CONFIG_S3C2440) //新增 ldr r0, =CLKDIVN mov r1, #0x05 // FCLK:HCLK:PCLK=1:4:8, HDIVN=2,PDIVN=1 str r1, [r0] mrc p15, 0, r1, c1, c0, 0 /* 讀出控制寄存器*/ orr r1, r1, #0xc0000000 /* 設置為“asynchronous bus mode?*/ mcr p15, 0, r1, c1, c0, 0 /* 寫入控制寄存器*/ ldr r0, =MPLLCON ldr r1, =0x5c011 //MPLL_400MHZ (0x5c<<12)|(0x01<<4)|(0x01)) str r1, [r0]3、內存控制器初始化部分修改board\samsung\smdk2440\lowlevel_init.S ,修改13個值就可以了
SMRDATA: .long 0x22011110 @ BWSCON .long 0x00000700 @ BANKCON0 .long 0x00000700 @ BANKCON1 .long 0x00000700 @ BANKCON2 .long 0x00000700 @ BANKCON3 .long 0x00000700 @ BANKCON4 .long 0x00000700 @ BANKCON5 .long 0x00018005 @ BANKCON6 .long 0x00018005 @ BANKCON7 .long 0x008C07A3 @ rEFrESH .long 0x000000B1 @ BANKSIZE .long 0x00000030 @ MrSrB6 .long 0x00000030 @ MrSrB7然後,代碼就跳轉到arch\arm\lib\board.c ->board_init_f ,這個函數的作用是調用函數指針數組init_sequence 中的每一個初始化函數,還有進行內存劃分,先來看一下init_sequence 中的初始化函數。
4、單板相關初始化修改 board\samsung\smdk2440\smdk2440.c->board_early_init_f
這裡邊有一次初始化了時鐘,而且與我們在start.S中初始化的不同,果斷刪掉
/* 注釋掉以下代碼 */ /*writel((M_MDIV << 12) + (M_PDIV << 4) + M_SDIV, &clk_power->mpllcon); */簡單修改至此,make 將u-boot.bin 燒寫到 norflash 啟動開發板 還不錯,串口已經能正確打印信息了,時鐘 sdram 已經正確初始化,但是 norflash 和 nandflash 未能識別出來。他們如何修改將在後面的文章中說明。
前言 為了更好地閱讀本文,你需要先閱讀Android apk動態加載機制的研究這篇文章,在此文中,博主分析了Android中apk的動態加載機制,並在文章的
如果你想在你的Android程序中自動打印MainActivity.onCreate(line:37)這種類名.方法名(行數)的日志該如何實現呢? 1.引入Java的線程
普通按鈕也就那麼幾種樣式,看著都審美疲勞,先放效果圖: 你會不會以為這個按鈕是集結了很多動畫的產物,我告訴你,並沒有。所有的實現都是基於自定義View,采用最底
本文實例講述了Android編程之View簡單學習示例。分享給大家供大家參考,具體如下:View,是Android的一個超類,這個類幾乎包含了所有的屏幕類型。每一個Vie