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