• Ubuntu12.04下建立交叉编译环境、使用QEMU模拟CortexA9、QEMU运行uboot


    一. 基础环境

    0. 安装virtualbox

     下载最新virtualbox (4.2),安装

    1. 安装ubuntu12.04

     下载ubuntu-12.04的dvd安装iso,搜索下载

    2. virtualbox安装ubuntu时候,分配100G,的动态盘

    3. 装好ubuntu后, 安装virtualbox增强功能,重启

    4. 设置共享文件夹,自动挂载+固定分配,重启

    5. sudo adduser xxx vboxsf,设置了用户加到vboxsf组,获取权限,重启

    6.  修改ubuntu源,网易很给力:

    deb http://mirrors.163.com/ubuntu/ precise main restricted
    deb http://mirrors.163.com/ubuntu/ precise-updates main restricted
    deb http://mirrors.163.com/ubuntu/ precise universe
    deb http://mirrors.163.com/ubuntu/ precise-updates universe
    deb http://mirrors.163.com/ubuntu/ precise multiverse
    deb http://mirrors.163.com/ubuntu/ precise-updates multiverse
    deb http://mirrors.163.com/ubuntu/ precise-backports main restricted universe multiverse
    deb http://mirrors.163.com/ubuntu/ precise-security main restricted
    deb http://mirrors.163.com/ubuntu/ precise-security universe
    deb http://mirrors.163.com/ubuntu/ precise-security multiverse
    sudo apt-get update

    二. 安装交叉工具链

    1. sudo apt-get insatll gcc-arm-linux-gnueabi
    2. sudo apt-get insatll g++-arm-linux-gnueabi

    注意:此处arm-linux-gnueabi-gdb没有被安装,可以自己编译一个:

    (1) 搜索下载 gdb-7.4.1.tar.bz2

    (2) 安装 

    sudo apt-get install libncurses5-dev
    termcap库在这里

    (3) 解压配置

    ./configure --target=arm-linux-gnueabi
    (4) 安装

    默认地址 /usr/local

    sudo make install

    (5) sudo ldconfig系统配置生效

    (6) 可以使用了


    三. 安装Qemu

    sudo apt-get install qemu qemu-system qemu-utils

    四.  下载u-boot

    www.denx.de是uboot的官网,denx软件和硬件都有,工具链eldk也很好用,可以用eldk的工具链编译,ftp下载时候,使用http方式的,不要使用ftp方式,可能看不见东西.

    http://ftp.denx.de/pub/eldk/ - 工具链地址
    http://ftp.denx.de/pub/u-boot/ - uboot地址
    http://ftp.denx.de/pub/u-boot/u-boot-2012.04.tar.bz2 下载这个

    五. 编译uboot

    编译uboot需要确定板子,板子和cpu、soc等是密切相关的,看uboot源码根目录下的boards.cfg,可以知道所有支持的板子名字,对应的架构,cpu,厂商等,

    因为我们要使用Qemu来模拟这个板子,所以要找到一个Qemu和uboot同时支持的板子,同时还是cortex-a9架构核心的.

    boards.cfg中有一行:

     ca9x4_ct_vxp                 arm         armv7       vexpress            armltd
    vexpress 是板子名,arm是架构arch,armv7是cpu,实际也是架构,armltd是厂商vendar
    ca9x4_ct_vxp 是配置名。

    同时,使用qemu-system-arm -M ?命令,能看到支持的板子列表,其中包括:

    vexpress-a9          ARM Versatile Express for Cortex-A9 

    就是说vexpress 这个板子,在uboot和qemu中,同时支持,且是cortex-a9的.

    (1) export ARCH=arm

    (2) export CROSS_COMPILE=arm-linux-gnueabi-

    (3) make ca9x4_ct_vxp_config

    (4) make

    编译成功后,源码根目录下出现 u-boot u-boot.bin等文件.

    六. 运行

    1. qemu-system-arm -M vexpress-a9 -m 256M -nographic -kernel u-boot  此命令没有图形只有命令行输出
    2. 或者
      1. qemu-system-arm -M vexpress-a9 -m 256M -serial stdio -kernel u-boot 此命令包括图形和命令行输出

      可以gdb调试:

      注意

      (1)  gdb调试

      qemu-system-arm -M vexpress-a9 -m 256M -kernel u-boot -S -s
      qemu-system-arm -m 256 -kernel u-boot -gdb tcp::1234 -S同一个意思

      -s 表示 -gdb tcp::1234

      -S 表示停下来,另一个终端可用arm-linux-gnueabi-gdb,启动后用参数target remote tcp::1234连接

      当然,连接之前,需要用file 制定一个有符号的目标,比如u-boot .

      同时gdb的 directory命令可以制定源文件的搜索路径.

       (2)  kernel 文件类型

       支持ld链接出来的elf文件,gdb调试端,需要用file加载相应的有调试信息符号的elf文件.

      七. 编译运行linux内核

      1. 获取内核

      ftp://ftp.kernel.org/pub/linux/kernel/v3.x/linux-3.8.tar.bz2
      2. 编译

      export ARCH=arm

      export CROSS_COMPILE=arm-linux-gnueabi-

      make clean distclean

      make vexpress_defconfig

      make -j4

      3. 启动

      qemu-system-arm -M vexpress-a9 -m 256M -kernel linux/linux-3.8/arch/arm/boot/zImage -append "console=tty0"

      八. 根文件系统

      1. busybox编译

      (1) 下载源码

      http://www.busybox.net/downloads/busybox-1.21.0.tar.bz2
      (2) 编译

      export ARCH=arm

      export CROSS_COMPILE=arm-linux-gnueabi-

      make -j4

      make install

      (3) _install目录就是所有的busybox编译的结果

      2. 制作根文件系统目录

      (0) 根目录

      mkdir rootfs

      cd rootfs

      (1) 目录结构

      mkdir bin etc dev lib proc tmp root home sys usr sbin var mnt

      (2) 运行库-来自工具链

      cp -a /usr/arm-linux-gnueabi/lib/* lib

      (3) 配置文件-来自busybox

      cp -a <busybox_dir>/examples/bootfloppy/etc/* etc

      (4) busybox工具集

      cp -a <busybox_dir>/_install/* .

      (5) 设备文件

      sudo cp -a /dev/console /dev/loop0  /dev/loop1  /dev/null  /dev/ram0  /dev/tty  /dev/tty0  /dev/tty1  /dev/zero /dev

      (6) 修改mdev配置,mdev负责自动生成设备节点,mdev.conf是配置文件

      vi etc/mdev.conf

      1. controlC[0-9] 0:0 0660 =snd/
      2. pcm.* 0:0 0660 =snd/
      3. seq.* 0:0 0660 =snd/
      4. mix.* 0:0 0660 =snd/
      5. timer 0:0 0660 =snd/
      其他特殊要求的设备文件,同样道理即可.

      (7) 修改启动配置

      vi etc/init.d/rcS

      增加

      mount -n -t proc none /proc 
    3. mount -n -t sysfs none /sys 
    4. mdev -s 这句很重要,生成所有的设备节点

      如果用nfs的话,有了以上目录就可以了

      3. 根文件系统镜像

      dd if=/dev/zero of=rootfs.img bs=1M count=32 # 32M的镜像

      mkfs.ext3 rootfs.img

      mkdir tmpfs

      sudo mount -o loop rootfs.img tmpfs

      sudo cp -a rootfs/* tmpfs/

      sudo umount tmpfs

      rootfs.img中就有了文件系统镜像了,ext3格式.

      4. 文件系统镜像启动qemu - 此时不需要u-boot了,直接启动内核指定参数即可

      qemu-system-arm -M vexpress-a9 -m 256M -kernel linux/linux-3.8/arch/arm/boot/zImage -append "root=/dev/mmcblk0 console=tty0 init=/linuxrc" -sd rootfs.img

      九. qemu网络配置

      0. qemu支持tap网络

      1. ubuntu-12.04本身内核支持了tun设备,所以不用再编译模块了.

      2. 安装nfs

      (1) sudo apt-get install nfs-kernel-server

      (2) sudo vi /etc/exports

       /home/xxxx/work/rootfs/fs *(rw,sync,no_subtree_check,all_squash,insecure,anonuid=1000,anongid=1000)
      (3) service portmap restart

      (4) service nfs restart

      3. 修改qemu网络启动脚本

      sudo vi /etc/qemu-ifup

      #!/bin/sh  
      /sbin/ifconfig $1 172.20.0.1
      意思就是说host机器的ip是172.20.0.1

      4. nfs启动内核

      sudo qemu-system-arm -M vexpress-a9 -m 256M -kernel linux/linux-3.8/arch/arm/boot/zImage -append "root=/dev/nfs nfsroot=172.20.0.1:/home/rda/work/rootfs/fs rw ip=172.20.0.2:172.20.0.1:172.20.0.1:255.255.255.0 init=/linuxrc console=tty0"   -net nic -net tap 

      ip=本机IP:对方IP:网关IP:掩码

      nfsroot=nfs的地址 对方IP:路径 - 和/etc/exports中导出的路径一样

      十. GDB和GDBServer的交叉编译和使用

      1. gdbserver

      gdbserver很好用,作为设备端的应用为pc端gdb提供需要的信息,编译也简单

      (1) 下载源码

      gdb-7.5.tar.bz2

      地址: ftp://prep.ai.mit.edu/pub/gnu/  

      (2) 编译

      cd gdb-7.5/gdb/gdbserver

      ./configure --host=arm-linux-gnueabi --target=arm-linux-gnueabi

      make -j4

      即生成了gdbserver,file查看文件类型,copy到板子上

      (3) 使用

      板子上:

      ./gdbserver localhost:1234 helloworld # helloworld是程序,执行后等待连接

      PC上:

      arm-linux-gnueabi-gdb helloworld

      target remote 172.20.0.2:1234 

      以上连接上,就可以直接调试了

      2. gdb

      (1)  源码 - gdb依赖termcap库

      termcap-1.3.1.tar.gz

      地址: ftp://prep.ai.mit.edu/pub/gnu/ 

      (2) 交叉编译termcap

      cd termcap-1.3.1

      ./configure

      后,修改Makefile如下

      vi Makefile

      CC = arm-linux-gnueabi-gcc

      AR = arm-linux-gnueabi-ar

      RANLIB = arm-linux-gnueabi-ranlib

      make

      (3) 交叉编译GDB

      把刚编译出的libtermcap.a复制到gdb-7.5/gdb

      cp -a libtermcap.a gdb-7.5/gdb

      cd gdb-7.5

      修改gdb/configure

      case $host_os in

          cygwin*)

             if test -d $srcdir/libtermcap; then

      ........

      esac

      ------->

      ac_cv_search_rgetent="libtermcap.a"

      配置

      ./configure --target=arm-linux-gnueabi --host=arm-linux-gnueabi 

      make -j4

      (4) 运行GDB

      GDB复制到板子上,就和调试PC程序一样了.

    十一. 问题

     1. 参考链接

    http://www.linuxidc.com/Linux/2012-07/65478.htm
    http://www.cnblogs.com/huqingyu/archive/2005/04/03/131102.html QEMU网络
    2. uboot出现问题
    DRAM:  256 MiB
    WARNING: Caches not enabled
    Flash: ## Unknown flash on Bank 1 - Size = 0x00000000 = 0 MB
    ## Unknown flash on Bank 2 - Size = 0x00000000 = 0 MB
    *** failed ***
    ### ERROR ### Please RESET the board ###
    如果在检测Flash failed后停止运行,是因为在 arch/arm/lib/board.c里面 board_init_r()函数里检测Flash失败后调用了hang(), 暂时先把hang()去掉就可以运行下去了。


    3. gdb运行出现

    "Remote ‘g’ packet reply is too long"
      在gdb/remote.c中
      注释掉:
           
    if (buf_len > 2 * rsa->sizeof_g_packet)            error (_(“Remote ‘g’ packet reply is too long: %s”), rs->buf); 

      并在后面添加:
     
    if (buf_len > 2 * rsa->sizeof_g_packet) {       rsa->sizeof_g_packet = buf_len ;       for (i = 0; i < gdbarch_num_regs (gdbarch); i++)       {          if (rsa->regs[i].pnum == -1)          continue;           if (rsa->regs[i].offset >= rsa->sizeof_g_packet)          rsa->regs[i].in_g_packet = 0;          else          rsa->regs[i].in_g_packet = 1;       }    }
    原因是gdbserver给的register个数过多,具体看代码即可.

    4. 高版本gdb可能会遇到调试错误,段错误等,可以换用低版本gdb,如gdb-7.0,gdb-6.8

    gdb-7.0a这个版本是好用的.

    5. 如果出现编译错误

    Werror相关的,那么配置的时候:

    ./configure --enable-werror=no ......

    6. 注意gdbserver和gdb要用同一版本的 

    7. gdb和gdbserver通信过程中,共享库符号问题

    因为板子上的库路径和pc库路径不同,所以pc上gdb可能出现加载不了动态库的问题,方法是:

    set solib-absolute-prefix /usr/arm-linux-gnueabi/

    set solib-search-path /uar/arm-linux-gnueabi/lib/

  • 相关阅读:
    UVA 11991 Easy Problem from Rujia Liu(map,vector的使用)
    UVA 11995 I Can Guess the Data Structure! (STL应用)
    HDU 2795 Billboard(线段树,单点更新)
    HDU 1394 Minimum Inversion Number (线段树,单点更新)
    UVA 11827 Maximum GCD(读入技巧,stringstream的使用)
    contest 2 总结
    Const 1 总结
    开始进行大量题目练习
    函数式线段树的个人理解
    poj 2318 TOYS
  • 原文地址:https://www.cnblogs.com/linucos/p/2938517.html
Copyright © 2020-2023  润新知