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),强烈鄙视这些无良开发板厂家,埋了这么多坑,在文档中只字不提,你问他他还不愿意说清楚。