Linux移植遇到的一些問題及解決方法(arm開發板)

1. 前言
   自上次研究嵌入式系統以後,已經過了12年了,這期間,linux內核和硬件都發生了非常大的變化,加這方面的開發人員相對較少,碰到一些問題,需要耗費比較多的時間和精力來搜索資料和自己研究,對於沒於耐心和基礎的人來說,確實不容易堅持下去。這方面的網上資料,有很多是培訓機構或者愛好者發的,其正確性也需要驗證才能知道,也有很多是以詐傳詐,或者語焉不詳,要處之處一筆跳過,或者語焉不詳,要處之處一筆跳過,或乾脆不寫。另外,linux開發的問題,就是搭建環境比較麻煩,
庫版本的兼容性有差別,經常遇到庫不兼容,缺這個庫少那個庫的問題。 泛此種種,就需要靠自己,不斷的嘗試工,不斷的測試和探索,反反覆覆做測試,其辛苦只有做過的人才知道,但是走過一遍之後,對底層技術和相關開發知識就有了更深入的認識了,付出也是值得的,同志們共勉吧。

2. 編譯linux內核遇到的一些問題及對策

2.1 錯誤信息:
include/linux/if_pppox.h:24: included file 'linux/if_pppolac.h' is not exported
include/linux/if_pppox.h:25: included file 'linux/if_pppopns.h' is not exported
linux/kernel.h:65: userspace cannot reference function or variable defined in the kernel
include/linux/kernel.h:97: userspace cannot reference function or variable defined in the kernel
include/linux/quota.h:175: userspace cannot reference function or variable defined in the kernel
include/linux/soundcard.h:1054: userspace cannot reference function or variable defined in the kernel

解決方法:
編輯:include/linux/Kbuild
找到這一行:header-y += if_pppox.h 
在其下面加入如下兩行:
header-y += if_pppolac.h
header-y += if_pppopns.h

2.2 錯誤信息:
Can't use 'defined(@array)' (Maybe you should just omit the defined()?) at kernel/timeconst.pl
解決方法:
打開 kernel/timeconst.pl

定位到以下內容:
@val = @{$canned_values{$hz}}; 
if (defined(@val)) { 
@val = compute_values($hz); 

output($hz, @val); 
將if (defined(@val)) 改爲if (@val),再次編譯就可以通過了。

2.3 錯誤信息:
openssl/opensslv.h: No such file or directory錯誤的解決辦法
解決方法:
缺少openssl庫,找到相應庫安裝,比如,centos-7中,
yum install openssl-devel 

2.4 錯誤信息:
"mkimage" command not found - U-Boot images will not be built

解決方法:
這是生成uImage時,要用於u-boot下的一個工具,這是安裝u-boot時的會
生成的工具,對u-boot編譯後,uboot的tools目錄下有這個工具。

2.5 錯誤信息:
---[ end Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(0,0)

原因分析及對策:這是一個讓新手或者沒見識過的人非常頭痛的問題,很長時間沒辦法下手,根本不知道原因是什麼。但是看信息,好像又是和文件系統相關,掛不上root 文件系統,unknown-block(0,0)又似乎和flash塊相關,經過反覆對比和測試,發現有2個原因:
(1) 對於支持設備樹的linux內核而言,沒有將emmmc的相關配置加進設備樹,內核啓動的時候都看不到emmc相關信息,或者是設備樹配置不正確,這個需要尋求硬件廠家支持,給到相應的資料和電路原理路;
(2) linux內核啓動參數問題,這也是一個很容易忽略的地方,這個坑也是隱藏的比較深,一不小心就錯過了,比如以下配置
就會出現這個問題:
Kernel command line: 
root=/dev/mmcblk1p2 rw console=ttySAC2,115200 init=/linuxrc earlyprintk
而正確的配置是:
root=/dev/mmcblk1p2 rw console=ttySAC2,115200 init=/linuxrc rootwait
即加上這個rootwait,至於爲什麼,可以參看內核代碼。這也太坑了,這個問題足
以讓你折騰3天3夜。

2.6 關於燒寫程序fastboot的問題
在有些燒寫程序啓動時,如果不在串口輸入fastboot命令,pc是識別不到otg區動的,而扯蛋的是有些版本的燒寫程序輸入fastboot回車即可,而有的版本輸入fastboot會提示:
fastboot <USB_controller>
    - run as a fastboot usb device
要輸入:fastboot 0 回車,纔會影響命令。

2.7 錯誤信息:
drivers/scsi/osd/osd_initiator.c: In function ‘build_test’:
drivers/scsi/osd/osd_initiator.c:67:2: error: size of unnamed array is negative
  BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
  ^
drivers/scsi/osd/osd_initiator.c:68:2: error: size of unnamed array is negative
  BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
  ^
make[3]: *** [drivers/scsi/osd/osd_initiator.o] Error 1
make[2]: *** [drivers/scsi/osd] Error 2
make[1]: *** [drivers/scsi] Error 2
make: *** [drivers] Error 2

解決方法:具體原因先沒時間分析,打開文件:drivers/scsi/osd/osd_initiator.c

//註釋掉67,68兩行
     63 static inline void build_test(void)
     64 {
     65         /* structures were not packed */
     66         BUILD_BUG_ON(sizeof(struct osd_capability) != OSD_CAP_LEN);
     67         //BUILD_BUG_ON(sizeof(struct osdv2_cdb) != OSD_TOTAL_CDB_LEN);
     68         //BUILD_BUG_ON(sizeof(struct osdv1_cdb) != OSDv1_TOTAL_CDB_LEN);
     69 }

2.8 錯誤信息:
missing bus glue for ehci-hcd
解決方法:
如果你的硬件不支持這個特性,就在內核配置中去掉這一項:
make menuconfig
Device Drivers -> USB support -> EHCI HCD(usb 2.0 support) 去掉,硬件不支持

2.9 錯誤信息:
arch/arm/plat-samsung/dev-i2c0.c:69: undefined reference to `s3c_i2c0_cfg_gpio'
解決方法:
對於s5pv210的核片,在內核中沒有選中smdkv210,編譯就會出現這個莫名奇妙的錯誤。

2.10 錯誤信息:
hival/rpm.c: In function ‘fileaction_setowngrp’:
archival/rpm.c:385:2: warning: ignoring return value of ‘chown’, declared with attribute warn_unused_result [-Wunused-result]
  chown(filename, uid, gid);
  ^
In file included from /usr/include/bits/byteswap.h:35:0,
                 from /usr/include/byteswap.h:24,
                 from include/platform.h:107,
                 from include/libbb.h:13,
                 from archival/rpm.c:10:
archival/rpm.c: In function ‘rpm_getint’:
archival/rpm.c:351:10: error: invalid 'asm': invalid operand for code 'w'
   return ntohs(*(int16_t*)tmpint);
          ^
make[1]: *** [archival/rpm.o] Error 1
make: *** [archival] Error 2

錯誤信息分析:以上看起來是因爲ntohs的問題,特別是這一句:
invalid 'asm': invalid operand for code 'w'
其根本原因,是交叉編譯工具跑到主機的頭文件搜索中去了,而交叉編譯工具應在交叉編譯工具的配置頭文件中去搜索。看看這路徑:In file included from /usr/include/bits/byteswap.h:35:0,應將/etc/profile中的C_INCLUDE_PATH先去掉,不要讓交叉工具跑去主機目錄下去搜。修改後,再將查看搜索路徑:查看頭文件搜索路徑
arm-linux-gnueabihf-gcc -E -v -

/usr/local/arm-linux/lib/gcc/arm-linux-gnueabihf/4.9.1/include
這樣顯示就對了。

2.11 錯誤信息:
In file included from /usr/local/arm-linux/arm-linux-gnueabihf/include/stdlib.h:959:0,
                 from include/libbb.h:24,
                 from libbb/login.c:14:
/usr/local/arm-linux/arm-linux-gnueabihf/include/bits/stdlib.h: In function ‘wctomb’:
/usr/local/arm-linux/arm-linux-gnueabihf/include/bits/stdlib.h:90:3: error: #error "Assumed value of MB_LEN_MAX wrong"
 # error "Assumed value of MB_LEN_MAX wrong"
 
原因分析及對策:在網上查到以下幾句:

By default the limits.h file is not properly configured, so you need to patch it.To fix the problem you have to go inside GCC's source directory and type the command:

cd $GCC_VERSION
cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
`dirname $(${TARGET}-gcc -print-libgcc-file-name)`/include-fixed/limits.h

cat gcc/limitx.h gcc/glimits.h gcc/limity.h > \
`dirname $(${TARGET}-gcc -print-libgcc-file-name)`/include-fixed/limits.h


This adds a #include_next <limits.h> to the bottom which eventually picks up the right header
   ^
   
    88 #define __STDLIB_MB_LEN_MAX     16
     89 #if defined MB_LEN_MAX && MB_LEN_MAX != __STDLIB_MB_LEN_MAX
     90 # error "Assumed value of MB_LEN_MAX wrong"
     91 #endif

glimits.h 中有這麼一句
/* Maximum length of a multibyte character.  */
#ifndef MB_LEN_MAX
#define MB_LEN_MAX 1
#endif
這裏怎麼定義爲1呢,改爲16試試?也就是兩個地方定義不一致

多字節字符最大長度,改大是最好的。

2.12 錯誤信息:
Error: unrecognized/unsupported machine ID (r1 = 0x00000d8a).

Available machine support:

ID (hex)        NAME
ffffffff        Generic DT based system
ffffffff        Samsung S5PC110/S5PV210-based board

Please check your kernel config and/or bootloader.

原因分析:對於s5pv210的板子,這是硬件廠家的u-boot中將machine ID設置爲0x00000d8a,而內核編譯配置時,沒有選中SMDKV210這個固件編譯,還有是應將arch/arm/tools/mach-types 這個文件中定義的smdkv210 的值改爲3466(0x00000d8a),強烈鄙視這些無良開發板廠家,埋了這麼多坑,在文檔中隻字不提,你問他他還不願意說清楚。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章