uclinux下编译busybox制作根文件系统

busybox下编译uclinux的根文件系统配置

我在使用busybox创建uClinux系统的根文件系统过程中,发现只有从网上的git下来的文件系统源文件可以起来,但是我想自己使用busybox编译一个跟文件系统,特此记录下我制作跟文件系统的整个过程。

最开始,我就直接编译busybox,使用arm-uclinuxeabi-gcc这个编译工具链,编译之后根本起不来。我查看到busybox的网站上,有一个基本的提示,

Busybox init isn't working!

Init is the first program that runs, so it might be that no programs are working on your new system because of a problem with your cross-compiler, kernel, console settings, shared libraries, root filesystem... To rule all that out, first build a statically linked version of the following "hello world" program with your cross compiler toolchain:

#include <stdio.h>

int main(int argc, char *argv)
{
  printf("Hello world!\n");
  sleep(999999999);
}
Now try to boot your device with an "init=" argument pointing to your hello world program. Did you see the hello world message? Until you do, don't bother messing with Busybox init.

Once you've got it working statically linked, try getting it to work dynamically linked. Then read the FAQ entry How do I build a Busybox-based system?, and the documentation for Busybox init (FIXME: dead link)

根据上面的思路,我编译了一个init文件,然后替换了可以启动的根文件系统的init文件,发现也是没有打印输出。于是我就猜测是编译器生成的文件存在问题,使用正常的可以启动的init,进入文件系统之后,启动如上程序,发现打印SEGV错误,然后我就谷歌这种问题,发现了如下内容:

Understanding What Causes SEGV in an Application

If a user-space application terminates with SEGV, this means, as it is always the case in Linux, that the application did something that triggered an exception to the Cortex-M processor core. The most likely causes are:
You built your application for a processor architecture other than Cortex-M, which causes an "Unsupported instruction" exception.
Your application makes an attempt to access an address outside of the Cortex-M address space.
Your application makes an attempt to access unaligned data.
To understand what is causing an exception, do the following:
Enable CONFIG_DEBUG_USER in the kernel configuration. From your project directory, bring up the kernel configuration interface by running make kmenuconfig. Go to Kernel hacking and enable Verbose user fault messages.
In U-boot, add user_debug=8 to bootargs.
Having done the above, rebuild your Linux project, bring it up on the target and re-run your application. When the application fails with SEGV, there should be some informational messages on the system console indicating the cause of the fault.

根据上面的操作过程:

  1. 开启 CONFIG_DEBUG_USER
  2. 在uboot下,bootargs 中user_debug=8

然后,我重新执行上述简单的打印程序,果然,出现了更加详细的提示:

asd: fault at 0xc1208044 [pc=0xc1208044, sp=0xc120ef30]
Invalid ISA state

无效的ISA状态,Attempt to execute an instruction when in an invalid ISA state. For example, not Thumb。然后我猜想可能是编译出来的是arm指令集而不是thumb指令集,然后我就翻看gcc的文档,添加了-march=armv7m选项,重新编译,然后,发现提示我error: target CPU does not support ARM mode。看到了这里,我猜想是印证了我之前的假设,于是我查看如何声明gcc,编译生成thumb指令集的文件,然后,我就发现了-mthumb选项。再我添加了这个选项之后,可以编译通过了,在可以启动的根文件系统下运行这个程序,发现可以打印出来,然后就是修改busybox的编译选项。

因为我使用的是stm32f767igt这款MCU,cortex-m7架构,重点在于只支持thumb指令集,不支持arm指令集。然而,在我编译busybox的时候,没有声明编译生成thumb指令集的可执行文件,但是gcc默认生成的是arm指令集的busybox。所以总是无法启动。这也是在我分析无法启动的过程中发现的。当我尝试修改busybox的配置选项:CONFIG_EXTRA_CFLAGS=”-march=armv7-m -mthumb”

然后,我又重新编译,现在是可以启动起来了,但是,启动不正常,总是在不断回显串口终端的提示符。我又添加了一个etc/initab文件,添加了如下两句话:

::shutdown:bin/umount -a -r                                                                                                 
::askfirst:-/bin/sh 

然后,就不再回显了,所以我怀疑是::askfirst:-/bin/sh,起作用了。

总结一下,编译针对某种特定MCU的busybox时,要注意该MCU是否支持arm指令集,如果不支持,那么需要在编译busybox的时候,添加额外的CFLAGS选项,主要声明MCU的结构,同时声明编译生成thumb指令集的可执行文件。

附录,我写了一个脚本,用于编译busybox,在busybox源码根目录下创建rootfs目录,并编译安装程序到对应目录中

#/bin/sh

CROSS_COMPILE=arm-uclinuxeabi-
TARGET=yyfish_defconfig
usage(){
    echo "Usage
        sh build.sh [menu/config/build/install/clean/distclean/deldirs/adddirs]
        menu:make menuconfig
        config:make $TARGET
        build:make withour install
        adddir:prepare to create some dirs and files in rootfs[default rootfs]for rootfs install
        deldirs:delete rootfs dir[default name is roofs]
        install:make install to dir rootfs[default]
        clean:make clean
        distclean:make disrclean
    "
}

ROOT_DIR=rootfs
DIRS="etc dev home lib sbin bin usr proc sys tmp"
init_files(){
    if [  ! -e etc/inittab ];then
    touch etc/inittab && \
    exec 3> etc/inittab && \
    echo """\
::shutdown:bin/umount -a -r
::askfirst:-/bin/sh\
""" >& 3 && \
    exec 3<&-  
    fi
    if [ ! -e etc/fstab ];then
    touch etc/fstab;
    exec 4> etc/fstab;
    echo """\
proc    /proc   proc    defaults    0   0
sysfs   /sys    sysfs   defaults    0   0\
""" >& 4
    exec 4<&-
    fi
}

do_dirs(){
    if [ $1 == "adddirs" ];then
    mkdir -p $ROOT_DIR; cd $ROOT_DIR;\
    for dir in $DIRS;do 
        mkdir $dir
    done;\
    init_files;\
    elif [ $1 == "deldirs" ];then
    sudo rm -fr $ROOT_DIR
fi;
}

do_install_last(){
    if [ -e $ROOT_DIR/dev ];then
    cd $ROOT_DIR && sudo chown root:root -R ./* && \
    cd dev && sudo mknod -m 666 console c 5 1 && \
    sudo mknod -m 666 null c 1 3;
    else
    echo $ROOT_DIR" no exist !!!"
    fi
}

if [ $# -gt 0 ] ; then
    case $1 in
    config)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE $TARGET;;
    menu)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE menuconfig;;
    build)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE SKIP_STRIP=y;;
    install)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE install; do_install_last;;
    dtb)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE dtb;;
    *clean)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE $1;;
    *dirs)do_dirs $1;;
    *Image)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE $1;;
    print_*)make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE $1;;
    *)usage;;
    esac
else
    make ARCH=arm CROSS_COMPILE=$CROSS_COMPILE SKIP_STRIP=y
fi

这个脚本的使用一般操作是:sh build.sh menu(记得配置install的目录为./rootfs,这个是adddirs操作的默认路径)–>sh build.sh build(编译busybox)–>sh build.sh adddirs(创建一些基本目录和节点等文件)–>sh build.sh install(安装)

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值