2010年8月23日 星期一

Android Proting 首部曲--- 環境建置與原始碼下載

最近針對Android移植部分做了點練習稍有心得,分享最近 Porting 心得看是否可以增加部落格瀏覽人氣 。  ^_^

Android Porting的方法在網路上已經有很多的教學,本系列文章是針對ARM S3C6410的開發版進行Android 2.1移植,移植流程如下圖:


上圖移植流程分別參考了一些資料後我把它分成三個部分我就把它當作移植的三部曲,首部曲是針對黃色框框內容屬於環境建置部分、二部曲指的是綠色框框編譯核心內容至於三部曲紅色框框是編譯Android,本篇文章先針對黃色框框內容先做一個心得分享。

在環境設定部分可以參考我的環境本文實作是以下列所示的環境來完成的,當然環境或軟體版本可以不用一模一樣也是可以進行。


(1) Host System Setup
作業系統的安裝屬於基本配備,就不再此多述;其他軟體部分可以使用:
sudo apt-get install git-core gnupg flex bison gperf libsdl1.2-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl libncurses5-dev zlib1g-dev
至於JDK 5.0部分,由於Ubuntu 10.04版用apt-get安裝的話只能裝JDK 6的版本,如果要使用apt-get安裝 JDK 5.0的話先編輯/etc/apt/sources.list
$ sudo vi /etc/apt/sources.list
在檔案最後面加入下列兩行:
deb http://tw.archive.ubuntu.com/ubuntu/ jaunty multiverse
deb http://tw.archive.ubuntu.com/ubuntu/ jaunty-updates multiverse
完成後存檔並執行:
$ sudo apt-get update
$ sudo apt-get install sun-java5-jdk
此時會開始安裝JDK 5.0,在安裝完成後可以用java -version確認版本,如顯示的版本非 "1.5.0_xx"的話可以用:
$ sudo update-alternatives --config java
來選擇"1.5.0_xx"版本。
另外一個安裝方法是直接到Java官網直接下載Linux版本的JDK: http://java.sun.com/products/archive/j2se/5.0_22/index.html
下載的檔案為: jdk-1_5_0_22-linux-i586.bin,然後安裝這個檔案及環境設定,我的環境使使用這方式;出現的JDK版本是"1.5.0_22"
不過使用前者的安裝方式似乎比較容易在Ubuntu上也比較多人使用。

(2) Get Source Cord
完成上述軟體的安裝,接著下來就是下載Kernel了,Kernel取得的方式有兩種;一種是放在開發版中的光碟內容中或者是直接向開發版廠商/代理商索取,這是最快也是最完整的方法一經取得只要執行make應該就可以了完成kernel的編譯。

另外一個方式比較進階是直接到Android官網下載,對於想測試比較新的版本,此方式是唯一途徑;例如目前市面上的開發版廠商大多提供kernel版本為2.6.29(Android 2.1),如果要測試Android 2.2版的話kernel版本為2.6.32廠商如果沒有提供的情況下就必須上官網取得了。


以下是針對如何自己做出Kernel的步驟,由於手上的開發版核心是Samsung S3C6410,使用Samsung提供的 kernel 與 Android kernel 做結合是最佳方式,直接使用git來進行就可以了。
首先建立一個自己定義名稱的目錄(Ex: My_kernel),加入Samsung與Android遠端 repositories:

接著取回遠端 repositories的資訊:

看看取回的資訊中有那些版本可使用:

接著將Android kernel合併到 samsung kernel,在合併前先定義一個儲存的地方給修改後的結果,然後用 git rebase 指令,開始合併 v2.6.29 到 android/android-2.6.29 到 samsung-android 這個 branch 中:


此時會開始進行下載與合併,過程中會遇到合併的衝突如下圖:

這時候使用git status來看有哪些檔案出現合併的衝突:

上圖所示,目前產生合併衝突的檔案有三個,因此我們開始編輯這三個檔案:
$ vi drivers/misc/pmem.c
找到 <<<<<<< HEAD、 >>>>>>> pmem: Add pmem driver 代表結束;中間會有 ======= 代表上下兩邊發生衝突,如下圖:

以上圖來說,在 ======= 上下方皆出現了:io.h及uaccess.h,此時就要去查出這四個檔案的差異以及我們要使用的,又或者如果無法判斷的話參考廠商所提供的舊版kernel也可以,
以此例來說只要將:
<<<<<<< HEAD
#include < linux/sched.h >
#include < linux/proc_fs.h >
#include < linux/io.h >
#include < linux/uaccess.h >
#include < linux/io.h >
#include < linux/uaccess.h >
=======
#include < asm/io.h >
#include < asm/uaccess.h >
>>>>>>> pmem: Add pmem driver

改成:

#include < linux/sched.h >

#include < asm/io.h >
#include < asm/uaccess.h >

記得將<<<<<<< HEAD 及 >>>>>>> pmem: Add pmem driver還有======= 刪除掉,然後存檔;
刪除<<<<<<< HEAD 到 ======= 之間內容為最多。

這個過程十分冗長耗時,需一步一步慢慢進行,如果遇到覺得修改沒問題但git rebase --continue又一直告訴你該檔有衝突的情況可以使用git rebase --skip去忽略這個錯誤。
使用git rebase --abort則取消整個動作,將會回到合併前原來的環境。
以上是針對取得kernel的部分說明,如果合併過程中遇到在問題的話建議可以參考一下開發版廠商所提供的kernel應該就可以解掉問題了。

取得Kernel完成後,接著下來就是取的Android Source code部分,此部分可以參照Android官網方式來進行:
http://source.android.com/source/download.html
首先安裝Reop
$ cd ~
$ mkdir bin
$ curl http://android.git.kernel.org/repo > ~/bin/repo
$ chmod a+x ~/bin/repo
接著初始化Repo Client
$ mkdir mydroid
$ cd mydroid
$ repo init -u git://android.git.kernel.org/platform/manifest.git
上述指令是取的目前Android Source code 最新版的方式,如果要取得Eclair (2.1)版本的話在後面加-b參數再輸入所要下載版本的代號,如下:
$ repo init -u git://android.git.kernel.org/platform/manifest.git -b eclair
接著看到下面訊息後,執行repo sync就會開始下載約3G容量的程式碼了。
repo initialized in /mydroid
$ repo sync

以上是針對取得Android Source code的部分說明,至此整個流程中黃色區塊部分已經完成,下次再針對綠色及紅色部分的寫出心得。
===== 08/31 補充用repo取的Google官方Kernel =====
在上述執行 repo init .... 後,會出現一個 .repo 的隱藏目錄,在該目錄下新建一個檔名為 local_manifest.xml 檔案;其內容如下:

其中android-2.6.29就是我們要抓的官方kernel版本,只要改一下版本號碼就可以取的其他版本的android官方kernel。
此時編輯好存檔後再回到 /mydroid 目錄下執行 repo sync 就會看到一個kernel的目錄。該目錄就是Google官方的Android Kernel。

===== 11/14 補充Android 2.2 Froyo 32bit環境的方法 =====
Android 2.2編譯支援32bit環境的方法
http://cheng-min-i-taiwan.blogspot.com/2010/11/android-2232bit.html

12 則留言:

  1. 請問合併後您是否有這個問題
    arch/arm/mach-s3c6410/mach-smdk6410.c:107: error: variable 'smdk6410_fb_win0' has initializer but incomplete type
    arch/arm/mach-s3c6410/mach-smdk6410.c:109: error: unknown field 'win_mode' specified in initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:109: error: extra brace group at end of initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:109: error: (near initialization for 'smdk6410_fb_win0')
    arch/arm/mach-s3c6410/mach-smdk6410.c:119: warning: excess elements in struct initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:119: warning: (near initialization for 'smdk6410_fb_win0')
    arch/arm/mach-s3c6410/mach-smdk6410.c:120: error: unknown field 'max_bpp' specified in initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:120: warning: excess elements in struct initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:120: warning: (near initialization for 'smdk6410_fb_win0')
    arch/arm/mach-s3c6410/mach-smdk6410.c:121: error: unknown field 'default_bpp' specified in initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:121: warning: excess elements in struct initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:121: warning: (near initialization for 'smdk6410_fb_win0')
    arch/arm/mach-s3c6410/mach-smdk6410.c:125: error: variable 'smdk6410_lcd_pdata' has initializer but incomplete type
    arch/arm/mach-s3c6410/mach-smdk6410.c:126: error: unknown field 'setup_gpio' specified in initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:126: error: 's3c64xx_fb_gpio_setup_24bpp' undeclared here (not in a function)
    arch/arm/mach-s3c6410/mach-smdk6410.c:126: warning: excess elements in struct initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:126: warning: (near initialization for 'smdk6410_lcd_pdata')
    arch/arm/mach-s3c6410/mach-smdk6410.c:127: error: unknown field 'win' specified in initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:127: warning: excess elements in struct initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:127: warning: (near initialization for 'smdk6410_lcd_pdata')
    arch/arm/mach-s3c6410/mach-smdk6410.c:128: error: unknown field 'vidcon0' specified in initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:128: warning: excess elements in struct initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:128: warning: (near initialization for 'smdk6410_lcd_pdata')
    arch/arm/mach-s3c6410/mach-smdk6410.c:129: error: unknown field 'vidcon1' specified in initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:129: warning: excess elements in struct initializer
    arch/arm/mach-s3c6410/mach-smdk6410.c:129: warning: (near initialization for 'smdk6410_lcd_pdata')
    arch/arm/mach-s3c6410/mach-smdk6410.c: In function 'smdk6410_machine_init':
    arch/arm/mach-s3c6410/mach-smdk6410.c:167: error: implicit declaration of function 's3c_fb_set_platdata'
    make[1]: *** [arch/arm/mach-s3c6410/mach-smdk6410.o] Error 1
    make: *** [arch/arm/mach-s3c6410] Error 2

    回覆刪除
  2. TO:Tedc
    我這邊也是出現同樣內容的,這是因為
    在arch/arm/mach-s3c6410/mach-smdk6410.c:107行部分是LCD的framebuffer,所以這部分應該無法直接使用合併後的檔案,mach-smdk6410.c這隻檔案在開發版中算是很重要的一般廠商都會重寫mach-smdk6410.c這隻檔案,如果您要編譯Kernel的話,後續還要整合驅動,這部分就debug就比較耗時。
    可以的話在編譯出現問題時可以參考該行上面的註解,如果是沒用的話就刪掉,然後整合屬於自己開發版的驅動進去(還是老話一句參考考開發板廠商所提供的檔案這樣學得會快些也比較有成就感的^^)

    回覆刪除
  3. 是合併的問題
    修正 arch/arm/plat-s3c/include/plat/fb.h
    就可以了

    回覆刪除
  4. TO:Tedc
    厲害,又學習到一招了~等等也來試試,Thx!

    回覆刪除
  5. 請問一下你合併完成過嗎,因為我看了一下合併的結果好像不是很好,因為 devp_audio.c 的 header file 就有很大的問題,我想是不是要用手工diff會比較好,好像有人有作patch,但是沒有可下載的地方

    回覆刪除
  6. 使用 apt-get 安裝 JDK 5 應該比較容易管理。

    另外,除了使用 update-alternatives 來設定 java 版本外,個人比較推薦使用 update-java-alternatives 這支工具。

    回覆刪除
  7. TO:Tedc
    關於arch/arm/plat-s3c64xx/dev-audio.c錯誤的問題,我覺得是該git所提供的map.h裡面沒有定義完整,你可以參考2.6.32中的map.h改改看:
    http://git.kernel.org/?p=linux/kernel/git/kki_ap/linux-2.6-samsung.git;a=blob;f=arch/arm/mach-s3c64xx/include/mach/map.h;h=e1eab3c94aea9b5110dc438b586bbe49e154f892;hb=master
    因為除了dev-audio.c好像MMC及S3C_MEM也有類似的困擾。

    回覆刪除
  8. TO:6wing.hsieh
    謝啦!又學到一招啦^^

    回覆刪除
  9. 今天又補充了一段 "用repo取的Google官方Kernel "見文章最後一段落。

    回覆刪除
  10. 今天又補充了一段 "Android 2.2 Froyo 32bit環境的方法"
    http://cheng-min-i-taiwan.blogspot.com/2010/11/android-2232bit.html

    回覆刪除
  11. "使用Samsung提供的 kernel 與 Android kernel 做結合是最佳方式" 請問一下為什麼要把kernel結合呢?
    直接下android common的kernel來修改沒辦法嗎?
    在其他網站上看到是android kernel和linux官方kernel作結合,可是為什麼要這樣作我搞不太清楚耶,可以教我一下嗎,謝謝

    回覆刪除
  12. 其實直接使用android kernel也是可行的,只是有些地方需要手動修改,預設的android kernel是沒有,如果能整合兩家的Kernel成功的話,修改的地方少些些剩下客製的部分,例如NAND的配置等。不過這部分我也同樣在摸索中,目前還是用android kernel慢慢來改成我想要的Kernel。

    回覆刪除