linux下編譯運行驅動 嵌入式linux下設備驅動的運行和linux x86 pc下運行設備驅動是類似的,由於手頭沒有嵌入式linux設備,先在vmware上的linux上學習驅動開發。 按照如下方法就可以成功編譯出hello world模塊驅動
2. 匯編:這幾句代碼怎麼不能編譯
INLCUDE Irvine32.inc
:
INCLUDE Irvine32.inc
3. 嵌入式開發,選擇編譯器問題。
linux嵌入式系統的開發的應用資料,交叉編譯器等等,這方面的資料, 到「工搜網資料文庫」索取吧。那裡有詳細的資料
4. 全志A20 怎麼單獨編譯boot
索了一下fastboot,但是燒錄失敗,提示找不到分區。於是就想到用TF卡燒錄boot.img,因為只修改了內核,不想打包全部燒錄一遍。
啟動到uboot命令行,輸入mmcinfo初始化mmc,不過提示:No MMC avaliable什麼的,查找uboot源代碼,發現,
u-boot/arch/arm/lib/board.c裡面,
if(!storage_type){
puts("NAND: ");
nand_init(); /* Go init the NAND */
}
else{
puts("MMC: ");
mmc_initialize(bd);
}
紅色代碼地方表明,uboot命令行只支持NAND或者MMC中的一種,這沒有道理啊。於是去掉else,無論什麼情況下都初始化MMC。也就是修改為:
if(!storage_type){
puts("NAND: ");
nand_init(); /* go init the NAND */
5. ftd232H驅動在linux平台(CPU全志A20)上的安裝問題
一、編譯過程是不需要動態庫文件參與的。
二、試著放到同目錄下運行一次,如果還是同樣的錯誤,說明庫文件的版本不兼容。雖然名字是對的。
6. ad怎麼pcb封裝成功後為什麼編譯時顯示不出來
pcb封裝成功後編譯時顯示不出來,可能有以下情況:
可以全局瀏覽一下 再看看你的封裝對不對,看看是不是參考點沒有設置好,超出顯示範圍了,建議設置到到1腳或中心:懷疑封裝的原點沒有設置到中心上。
Altium Designer編譯常見錯誤
[Error] Compiler Duplicate Component Designators C19 at 668,972 and 795,650
元器件標號重復,這里給出了元器件標號和坐標
Compiler Floating Power Object GND
懸浮的電源接地元件
出現此類警告的原因:在POWER.SCH文件中電源標號Global Power-Object 3.3V和埠port重復定義.
解決的辦法:對 POWER.SCH文件中去掉多餘的電源標號Global Power-Object 3.3V。
Compiler Net AA10 has no driving source (Pin U11-A20,Pin U14-26)
輸入型引腳未連接或沒有信號出入
解法一:你使用的元件對應的引腳是輸入的,可以改變原理圖中對應元器件的引腳屬性解決。
解答二:在protel中,軟體會檢查你的輸入管腳有沒有連,這樣的好處是提醒畫圖的人還有輸入管腳懸空的,我們知道,在電路系統中,大部分輸入管腳是不允許懸空的.所以建議畫圖的人在做原理圖庫的時候盡量把元件管腳的屬性加上,這樣可以不讓自己出錯.如果有輸入哪個管腳必須懸空的話,可以在上面添加忽略ERC檢查.這樣編譯的時候就沒有警告了!
解答三:在做元件封裝的時候,管腳的electrical type有很多選擇,一般情況下,選擇passive就沒事了
Compiler Off sheet Pin -3 at 1594,608
原理圖圖紙小了,換大一點的錯誤就會消失
Compiler Extra Pin U31-1 in Normal of part U31A
貌似是封裝不可用,重新載入一下PCB封裝
懸浮的網路標號
某個網路標簽沒有放置好還在漂浮(應該連接在導線或者引腳上面). 在放置網路標簽時,當游標捕捉到導線時,游標上顯示紅色星行標簽,此時單擊滑鼠放置.
在引腳放置忽略標記
7. 最近剛買了一個開發板,全志A20,編譯時遇到如下錯誤。請大蝦解答,多謝。
'gcc-linaro/arm-linux-gnueabi/bin/ranlib' 這個目錄下找不到這個文件,不能硬鏈到這個文件 看你這個地址是個相對路徑,是不是環境變數沒配全
8. 編譯a20 lunch後面應該選擇哪個
android的優勢就在於其開源,手機和平板生產商可以根據自己的硬體進行個性定製自己的手機產品,
如小米,LePhone,M9等,因此,在我們在對Android的源碼進行定製的時候,很有必要了解下,Android的編譯過程。
如果你從來沒有做過Android代碼的編譯,那麼最官方的編譯過程就是查看Android的官方網站:
http://source.android.com/source/building.html
但是,這兒只是告訴你了如何去編譯一個通用的系統,並沒有詳細告訴你細節,我們跟著編譯過程來了解下
+-------------------------------------------------------------------------------------------------------------+
本文使用Android版本為2.1,採用開發板為華清遠見研發的FS_S5PC100 A8開發板。
+-------------------------------------------------------------------------------------------------------------+
按照google給出的編譯步驟如下:
1> source build/envsetup.sh:載入命令
2> lunch:選擇平台編譯選項
3> make:執行編譯
我們按照編譯步驟來分析編譯過程的細節,最終添加自己的平台編譯選項。
1. source build/envsetup.sh
這個命令是用來將envsetup.sh里的所有用到的命令載入到環境變數里去,我們來分析下它。
envsetup.sh里的主要命令如下:
function help() # 顯示幫助信息
function get_abs_build_var()# 獲取絕對變數
function get_build_var()# 獲取絕對變數
function check_proct()# 檢查proct
function check_variant()# 檢查變數
function setpaths() # 設置文件路徑
function printconfig()# 列印配置
function set_stuff_for_environment() # 設置環境變數
function set_sequence_number() # 設置序號
function settitle() # 設置標題
function choosetype() # 設置type
function chooseproct() # 設置proct
function choosevariant() # 設置variant
function tapas() # 功能同choosecombo
function choosecombo() # 設置編譯參數
function add_lunch_combo() # 添加lunch項目
function print_lunch_menu() # 列印lunch列表
function lunch()# 配置lunch
function m()# make from top
function findmakefile() # 查找makefile
function mm() # make from current directory
function mmm() # make the supplied directories
function croot()# 回到根目錄
function cproj()
function pid()
function systemstack()
function gdbclient()
function jgrep()# 查找java文件
function cgrep() # 查找c/cpp文件
function resgrep()
function tracedmmp()
function runhat()
function getbugreports()
function startviewserver()
function stopviewserver()
function isviewserverstarted()
function smoketest()
function runtest()
function godir () # 跳到指定目錄 405
# add_lunch_combo函數被多次調用,就是它來添加Android編譯選項
# Clear this variable. It will be built up again when the vendorsetup.sh
406 # files are included at the end of this file.
# 清空LUNCH_MENU_CHOICES變數,用來存在編譯選項
407 unset LUNCH_MENU_CHOICES
408 function add_lunch_combo()
409 {
410 local new_combo=$1 # 獲得add_lunch_combo被調用時的參數
411 local c # 依次遍歷LUNCH_MENU_CHOICES里的值,其實該函數第一次調用時,該值為空
412 for c in ${LUNCH_MENU_CHOICES[@]} ; do
413 if [ "$new_combo" = "$c" ] ; then # 如果參數里的值已經存在於LUNCH_MENU_CHOICES變數里,則返回
414 return
415 fi
416 done # 如果參數的值不存在,則添加到LUNCH_MENU_CHOICES變數里
417 LUNCH_MENU_CHOICES=(${LUNCH_MENU_CHOICES[@]} $new_combo)
418 }
# 這是系統自動增加了一個默認的編譯項 generic-eng
420 # add the default one here
421 add_lunch_combo generic-eng # 調用上面的add_lunch_combo函數,將generic-eng作為參數傳遞過去
422
423 # if we're on linux, add the simulator. There is a special case
424 # in lunch to deal with the simulator
425 if [ "$(uname)" = "Linux" ] ; then
426 add_lunch_combo simulator
427 fi
# 下面的代碼很重要,它要從vendor目錄下查找vendorsetup.sh文件,如果查到了,就載入它
1037 # Execute the contents of any vendorsetup.sh files we can find.
1038 for f in `/bin/ls vendorbuild/vendorsetup.sh 2> /dev/null`
1039 do
1040 echo "including $f"
1041 . $f # 執行找到的腳本,其實裡面就是廠商自己定義的編譯選項
1042 done
1043 unset f
envsetup.sh其主要作用如下:
1. 載入了編譯時使用到的函數命令,如:help,lunch,m,mm,mmm等
2. 添加了兩個編譯選項:generic-eng和simulator,這兩個選項是系統默認選項
3. 查找vendor/<-廠商目錄>/和vendor/<廠商目錄>/build/目錄下的vendorsetup.sh,如果存在的話,載入執行它,添加廠商自己定義產品的編譯選項
其實,上述第3條是向編譯系統添加了廠商自己定義產品的編譯選項,裡面的代碼就是:add_lunch_combo xxx-xxx。
根據上面的內容,可以推測出,如果要想定義自己的產品編譯項,簡單的辦法是直接在envsetup.sh最後,
添加上add_lunch_combo myProct-eng,當然這么做,不太符合上面代碼最後的本意,
我們還是老實的在vendor目錄下創建自己公司名字,然後在公司目錄下創建一個新的vendorsetup.sh,在裡面添加上自己的產品編譯項
#mkdir vendor/farsight/
#touch vendor/farsight/vendorsetup.sh
#echo "add_lunch_combo fs100-eng" > vendor/farsight/vendorsetup.sh
這樣,當我們在執行source build/envsetup.sh命令的時候,可以在shell上看到下面的信息:
including vendor/farsight/vendorsetup.sh
2. 按照android官網的步驟,開始執行lunch full-eng
當然如果你按上述命令執行,它編譯的還是通用的eng版本系統,不是我們個性系統,我們可以執行lunch命令,它會列印出一個選擇菜單,列出可用的編譯選項
如果你按照第一步中添加了vendorsetup.sh那麼,你的選項中會出現:
You're building on Linux
generic-eng simulator fs100-eng
Lunch menu... pick a combo:
1. generic-eng
2. simulator
3. fs100-eng
其中第3項是我們自己添加的編譯項。
lunch命令是envsetup.sh里定義的一個命令,用來讓用戶選擇編譯項,來定義Proct和編譯過程中用到的全局變數。
我們一直沒有說明前面的fs100-eng是什麼意思,現在來說明下,fs100是我定義的產品的名字,eng是產品的編譯類型,除了eng外,還有user, userdebug,分別表示:
eng: 工程機,
user:最終用戶機
userdebug:調試測試機
tests:測試機
由此可見,除了eng和user外,另外兩個一般不能交給最終用戶的,記得m8出來的時候,先放出了一部分eng工程機,然後出來了user機之後,可以用工程機換。
那麼這四個類型是干什麼用的呢?其實,在main.mk里有說明,在Android的源碼里,每一個目標(也可以看成工程)目錄都有一個Android.mk的makefile,每個目標的Android.mk中有一個類型聲明:
LOCAL_MODULE_TAGS,這個TAGS就是用來指定,當前的目標編譯完了屬於哪個分類里。
PS:Android.mk和Linux里的makefile不太一樣,它是Android編譯系統自己定義的一個makefile來方便編譯成:c,c++的動態、靜態庫或可執行程序,或java庫或android的程序,好了,我們來分析下lunch命令幹了什麼?
function lunch()
{
local answer
if [ "$1" ] ; then
# lunch後面直接帶參數
answer=$1
else
# lunch後面不帶參數,則列印處所有的target proct和variant菜單提供用戶選擇
print_lunch_menu
echo -n "Which would you like? [generic-eng] "
read answer
fi
local selection=
if [ -z "$answer" ]
then
# 如果用戶在菜單中沒有選擇,直接回車,則為系統預設的generic-eng
selection=generic-eng
elif [ "$answer" = "simulator" ]
then
# 如果是模擬器
selection=simulator
elif (echo -n $answer | grep -q -e "^[0-9][0-9]*$")
then
# 如果answer是選擇菜單的數字,則獲取該數字對應的字元串
if [ $answer -le ${#LUNCH_MENU_CHOICES[@]} ]
then
selection=${LUNCH_MENU_CHOICES[$(($answer-$_arrayoffset))]}
fi
# 如果 answer字元串匹配 *-*模式(*的開頭不能為-)
elif (echo -n $answer | grep -q -e "^[^\-][^\-]*-[^\-][^\-]*$")
then
selection=$answer
fi
if [ -z "$selection" ]
then
echo
echo "Invalid lunch combo: $answer"
return 1
fi
# special case the simulator
if [ "$selection" = "simulator" ]
then
# 模擬器模式
export TARGET_PRODUCT=sim
export TARGET_BUILD_VARIANT=eng
export TARGET_SIMULATOR=true
export TARGET_BUILD_TYPE=debug
else
# 將 proct-variant模式中的proct分離出來
local proct=$(echo -n $selection | sed -e "s/-.*$//")
# 檢查之,調用關系 check_proct()->get_build_var()->build/core/config.mk比較羅嗦,不展開了
check_proct $proct
if [ $? -ne 0 ]
then
echo
echo "** Don't have a proct spec for: '$proct'"
echo "** Do you have the right repo manifest?"
proct=
fi
# 將 proct-variant模式中的variant分離出來
local variant=$(echo -n $selection | sed -e "s/^[^\-]*-//")
# 檢查之,看看是否在 (user userdebug eng) 范圍內
check_variant $variant
if [ $? -ne 0 ]
then
echo
echo "** Invalid variant: '$variant'"
echo "** Must be one of ${VARIANT_CHOICES[@]}"
variant=
fi
if [ -z "$proct" -o -z "$variant" ]
then
echo
return 1
fi
# 導出環境變數,這里很重要,因為後面的編譯系統都是依賴於這里定義的幾個變數的
export TARGET_PRODUCT=$proct
export TARGET_BUILD_VARIANT=$variant
export TARGET_SIMULATOR=false
export TARGET_BUILD_TYPE=release
fi # !simulator
echo
# 設置到環境變數,比較多,不再一一列出,最簡單的方法 set >env.txt 可獲得
set_stuff_for_environment
# 列印一些主要的變數, 調用關系 printconfig()->get_build_var()->build/core/config.mk-
>build/core/envsetup.mk 比較羅嗦,不展開了
printconfig
}
由上面分析可知,lunch命令可以帶參數和不帶參數,最終導出一些重要的環境變數,從而影響編譯系統的編譯結果。導出的變數如下(以實際運行情況為例)
TARGET_PRODUCT=fs100
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
執行完上述兩個步驟,就該執行:make命令了
9. 靈動a20啟動器怎麼啟動
,boot1,u-boot,boot0與boot1源碼在lichee/boot/目錄下, 機器上電執行boot0,boot0
A20啟動代碼流程分析:
1:全志的啟動包括boot0,boot1,u-boot,boot0與boot1源碼在lichee/boot/目錄下,
機器上電執行boot0,boot0就會引導boot1,boot1再引導u-boot。
2:在lichee/boot/目錄下的Makefile文件指定了boot1的編譯目錄,例如
make -f make_sdmmc -C boot1/core -j8命令就是調用lichee/boot/boot1/core目錄下make_sdmmc腳本編譯,
make_sdmmc最終又調用make.cfg腳本編譯,所以lichee/boot/目錄下的Makefile文件指定的編譯路徑最終都會
調用各自目錄下的make.cfg來編譯。
3:使用make_nand與make_sdmmc腳本是core目錄生成的boot1_nand.bin與boot1_sdcard.bin,同時在
lichee/boot/workspace/egon/與lichee/tools/pack/chips/sun7i/eGon/目錄生成,他們分別調用
lichee/boot/boot1/driver/drv_nand/與lichee/boot/boot1/driver/drv_sd/目錄下的文件;
boot1_nand.bin與boot1_sdcard.bin分別對應啟動模式:nandflash與inand啟動,配置文件是在
lichee/boot/pack/chips/sun7i/configs/android/目錄下相應的文件指定,其中storage_type欄位指定,
2為inand啟動,—1為nandflash啟動;Boot_Android是正常啟動模式,Boot_Burn是調試模式,Card_Android
是升級模式,他們分別生成boot.axf,prvt.axf與sprite.axf鏡像,同時在
lichee/boot/workspace/wboot/bootfs/與lichee/tools/pack/chips/sun7i/wboot/bootfs/目錄生成;
lichee/boot/boot1/driver/drv_de/目錄是多媒體庫源碼,是Lcd與HDMI等顯示源碼,同時在
lichee/boot/workspace/wboot/bootfs/與lichee/tools/pack/chips/sun7i/wboot/bootfs/目錄生成
drv_de.drv鏡像。
4:arm_start.S(boot1/core/arm_board)->eGon2_swi_handler->eGon2_swi_handler_entry->eGon2_init->
eGon2_start->eGon2_storage_type_set(判斷啟動模式,載入boot.axf或者sprite.axf),eGon2_run_app->
FS_fread(載入.axf文件),elf_loader[*entry = (__u32)priv->main;],func(argc, argv)[該函數就是
BootMain()的指針]->BootMain。
(1)正常啟動模式:
BootMain->BoardInit_Display[載入drv_de.drv,判斷顯示模式,LCD,TV,HDMI等],check_power_status[
檢測電壓與電池狀態,判斷是否開機],BootOS_detect_os_type[載入u-boot.bin,PreBootOS->
boot_dsipatch_kernal[設置u-boot的物理地址是*kernal_addr = 0x4a000000]->wBoot_fopen("c:\\linux\\u-boot.bin", "rb")],
BootOS[wBoot_jump_to_linux->EGON2_SWI_JUMP_TO_LINUX->eGon2_jump_to_android_linux直接進入u-boot
介面]。
(2)升級模式:
BootMain->boot_ui_init[載入drv_de.drv,判斷顯示模式,LCD,TV,HDMI等],card_sprite->
update_flash_hardware_scan[掃描當前存儲設備是nand還是inand,update_boot0,update_boot1,
根據sprite_type判斷升級nand還是inand]。
5:(1)lichee/tools/pack/pack腳本打包鏡像文件。
(2)編譯kernel的時候首調用./build.sh -p sun7i_android->buildroot/scripts/common.sh->
lichee/linux-3.3/build.sh->lichee/buildroot/scripts/build_sun7i_android.sh編譯。
在編譯kernel的時候也編譯也u-boot,調用./build.sh -p sun7i_android->buildroot/scripts/common.sh->
lichee/u-boot/build.sh編譯。
6:lichee/boot/pack/chips/sun7i/wboot/bootfs.ini或lichee/tools/pack/chips/sun7i/wboot/bootfs.ini
把文件系統盤符映射成C盤,就是代碼中使用的c:\\boot.ini","c:\\sprite.axf"等。
lichee/tools/pack/chips/sun7i/configs/android/default/下有env.cfg與image.cfg配置文件,
env.cfg是u-boot使用的配置文件,包括nand_root,mmc_root,loglevel,bootcmd等參數;
image.cfg是boot使用的文件列表與ITEM_ROOTFSFAT32等重要符號。
7:sys_partition.fex文件中各個分區與下載對應的文件如下:
bootloader分區保存bootloader.fex,bootloader.fex就是由boot.axf u-boot.bin等組成。
env分區保存env.fex,env.fex就是lichee/tools/pack/chips/sun4i/configs/crane/default/env.cfg文件,它是u-boot的基本配置。
boot分區保存boot.fex,boot.fex是boot.img的鏈接,它由kernel與ramdisk組成,使用fastboot下載的時候就是下載boot.img。
system分區保存system.fex,system.fex是system.img的鏈接,它是android系統,使用fastboot下載的時候就是下載system.img。
recovery分區保存recovery.fex,recovery.fex是recovery.img的鏈接,它也是由kernel與ramdisk組成,用於系統恢復,使用fastboot下載的時候就是下載recovery.img。
misc分區用於恢復系統設置的時候在uboot中保存一些變數與命令的值。
*.fex文件在lichee/tools/pack/out/目錄,*.img在anroid/out/...下。
8:A20的分區如下:
--------fastboot partitions--------
-total partitions:11-
-name- -start- -size-
bootloader : 8000 8000
env : 10000 8000
boot : 18000 8000
system : 20000 100000
data : 120000 100000
misc : 220000 8000
recovery : 228000 10000
cache : 238000 80000
private : 2b8000 8000
databk : 2c0000 80000
UDISK : 340000 3e0000
-----------------------------------
其中UDISK就是作為SDCARD分區,bootloader是從16MB開始,在bootloader的前面是
16KB的MBR_SIZE與16KB的DL_SIZE。
9:各個鏡像的對應的內存地址:
在read_boot_img()或者do_boota()都可以列印這些信息。
u-boot的地址為0x4a000000,在boot_dsipatch_kernal函數里強制賦值,也在該函數里
使用wBoot_fopen("c:\\linux\\u-boot.bin", "rb")與wBoot_fread((void *)(*kernal_addr), 1, file_length, hd_file)
把u-boot.bin從存儲設備載入到0x4a000000內存地址,之後boot1從BootOS(para_addr, kernal_addr)
跳轉到u-boot。
*kernal_addr = 0x4a000000。
kernel地址為0x40008000,ramdisk地址為0x41000000,在CONFIG_EXTRA_ENV_SETTINGS
中的boota 40007800其實是把boot.img下載到內存中的地址,由於boot.img中包含了
kernel與ramdisk,也包含了這兩個鏡像在內存中的地址,還有檢查boot.img的magic
是不是ANDROID,從存儲設備載入這個兩個鏡像到內存的操作是在read_boot_img函數里,
在u-boot是do_boota函數里再次檢查boot.img的合法性。