Chinaunix首页 | 论坛 | 博客
  • 博客访问: 1162927
  • 博文数量: 93
  • 博客积分: 7185
  • 博客等级: 准将
  • 技术积分: 3560
  • 用 户 组: 普通用户
  • 注册时间: 2007-04-02 13:54
文章分类
文章存档

2011年(43)

2010年(11)

2009年(27)

2008年(12)

分类: 嵌入式

2009-09-07 23:22:39

1. vmware 添加新的硬盘
      fdisk                              
用法就算了
      mkfs -t ext3 -c /dev/sdb1  (
我看就不用 c 参数了吧, check bad block 就不用了, 俺的E4500真快阿,郁闷为啥叫sdx了呢)
      df                                
看看   
    vim /etc/fstab 
添加到系统fstab  
        /dev/sdb1        /cross                    ext3    default                                        1                       2
                                                                      (man fstab
mount                   不备份           fsck检查顺序

2. cross  build  principle      

--------------------------------------------------------------------------------

    1)  准备source code  hostlinux   targearmlinux
      binutils-2.18                       
      gcc-core-4.1.2                  
      gcc-g++4.1.2                    
      glibc-2.6.1                            
      linux-2.6.24.4                           

--------------------------------------------------------------------------------
  2) 
定义环境变量 (然后解压缩...)

           export PREFIX=/cross/cross-arm           cross gccbin会放到这个目录
           export TARGET=arm-linux                          arm
上的linux

          cd /cross/src        假设你下载的gcc binutil在这个目录(你当然要解压缩了)
          mkdir build-binutils build-gcc build-glibc 

--------------------------------------------------------------------------------
   3)
binutils (要分清hosttarget...)
         cd /cross/src/build-binutils
         ../binutils-x.xx/configure --target=$TARGET --prefix=$PREFIX --disable-nls
         make all
         make install
      
          --disable-nls :
不要使用汉语吧, 用英语就行了. 这个选项让gcc不输出汉语的提示...  

--------------------------------------------------------------------------------
  4)
bootstrap gcc   
          cd /cross/src/build-gcc
          export PATH=$PATH:$PREFIX/bin
          ../gcc-x.x.x/configure --target=$TARGET --prefix=$PREFIX --disable-nls
           --enable-languages=c  --without-headers   --disable-shared  --disable-threads --disable-libmudflap --disable-libssp
           make all-gcc
           make install-gcc 

-without-headers :这个选项使你编译出的GCC不能使用标准库.(host cputarget cpu一样的话,基本不用cross toolchain系统通过编译选项也能实现这个功能).
--
with-newlib 这只是个bugwork around,newlib没有关系的.
This is only necessary if you are compiling GCC <= 3.3.x. That version has a known bug that keeps --without-headers from working correctly. Additionally setting --with-newlib is a workaround for that bug.  
--
enable-languages :tell gcc需要哪些语言支持:font end,   bootstrap gcc only surppot C
tells GCC not to compile all the other language frontends it supports, but only C

--
disable-shared  : 没有这个选项,会有 crti.o: No such file: No such file or directory collect2: ld returned 1 exit status
--
disable-thread : 没有这个选项的话会有,  posix_thread.h  can't not found  的问题 .
--
disable-libmudflap --disable-libssp  :两个边界检查使用的库,有问题,禁止

    libc的时候这几个库是不能编译通过的 ssp,mudflap,gomp
 
这个线索是这个问题的补丁
还有官方的 bug

--------------------------------------------------------------------------------

     5)  prepare linux kernel heads
           
       
make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig             配置内核,记着选arm
        make ARCH=arm CROSS_COMPILE=arm-linux-                            
随意运行下,就能产生version.h autoconf.h

       cd    linux-2.4.21
       cp   -dR include/asm-arm     $PREFIX/$TARGET/include/asm
       cp   -dR include/linux              $PREFIX/$TARGET/include/linux

       $TARGET/PREFIX/目录中建立下面的符号连接:

           cd $PREFIX/$TARGET
           ln -s
include   sys-linux     相当于configure gcc  --with-heads=

      $TARGET_PREFIX/目录中建立下面的符号连接:
          
cd  $PREFIX/$TARGET/include/asm
           ln    -s  arch-s3c2410  arch     
其实arch 已经建立了 make了下,建立好了)
          
ln  -s  proc-armv proc         这个版本没proc这个连接了

--------------------------------------------------------------------------------

    6)  build   glibc
           
搞了半天,原来glibc 2.6.1     是不支持arm的, 需要打上一系列的补丁
           glibc-2.6.1-alpha_ioperm_fix-1.patch
            glibc-2.6.1-cross_hacks-1.patch
            glibc-2.6.1-hppa_nptl-1.patch
            glibc-2.6.1-libgcc_eh-1.patch
            glibc-2.6.1-localedef_segfault-1.patch
            glibc-2.6.1-mawk_fix-1.patch
            glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch
            glibc-2.6.1-sysdep_cancel-1.patch

           推荐补丁下载地址
          
推荐文章:  http://blog.chinaunix.net/u/26710/showart_394113.html          
           RTLD_SINGLE_THREAD_P
fix(上面的patch已经包含了,参考下): 
                            
          
           
patch -Np1 -i  猛打把,少了那个都编译不过去 ,详细步骤如下
tar xvf glibc-2.6.1.tar.bz2
 cd glibc-2.6.1/

 tar xvf ../glibc-ports-2.6.1.tar.bz2
 mv -v glibc-ports-2.6.1 ports

 patch -Np1 -i ../glibc-2.6.1-libgcc_eh-1.patch
 patch -Np1 -i ../glibc-2.6.1-localedef_segfault-1.patch
 patch -Np1 -i ../glibc-2.6.1-cross_hacks-1.patch
 patch -Np1 -i ../glibc-2.6.1-RTLD_SINGLE_THREAD_P-1.patch

             NPTL problem fix:
             patch for glibc2.4: http://www.devfiles.jlime.com/parted/glibc/nptl-crosscompile.patch
             The following lines need to be added to config.cache for Glibc to support NPTL:
                   
echo "libc_cv_forced_unwind=yes" > config.cache                    
        echo "libc_cv_c_cleanup=yes" >> config.cache
        
            
最后使用参数--cache-file=config.cache
            
还不行,需要把asm-generic copy $PREFIX/$TARGET/include ....   (为啥经验这么重要呢。。)             

         $ tar -xvzf glibc-2.2.3.tar.gz
         $ tar -xzvf glibc-linuxthreads-2.2.3.tar.gz --directory=glibc-2.2.3

         $ cd build-glibc
         $
CC=arm-linux-gcc ../glibc-2.2.3/configure --host=$TARGET  --prefix=/usr
                 --with-headers=$PREFIX/$TARGET/include --cache-file=config.cache

             CC=arm-linux-gcc CC 变量设成你刚编译完的boostrap gcc, 用它来编译你的glibc.
             --host=$TARGET
告诉该链接库在目标系统上执行, 而非在本地主机.
             --prefix="/usr"
告诉配置脚本在目标板的根文件系统中glibc的位置.
             --with-headers
告诉glibc 我们的linux 内核头文件的目录位置.
            
--enable-add-ons 告诉配置脚本使用我们下载的附加包. 已经将glibc-linuxthreads-2.2.3放入了glibc 源码目录中.
                
由于我们只添加了一个附加包, 这里--enable-add-ons等价于  --enable-add-ons=linuxthreads.
                 (
如果使用glibc-2.1.x, 需要使用glibc-crypt附加包, 就得使用: --enable-add-ons= linuxthreads, crypt选项). (NPTL )

         $ make
         $
make install_root=$PREFIX/$TARGET  prefix="" install
        install_root 指定了安装链接库组件的目录, glibc安装到与我们项目相关的目录, 而非/usr目录.如果不指定prefix="", 那么glibc会被安装到$/PREFIX/$TARGET/usr/lib目录中. 指定prefix使glibc被安装到 $TARGET_PREFIX/lib目录.

--------------------------------------------------------------------------------
7.)
修改$PREFIX$TARGET/lib目录中的libc.so
    $ cd $PREFIX/$TARGET/lib
    $
cat libc.so

libc.so的内容:

/* GNU ld script

   Use the shared library, but some functions are only in

   the static library, so try that secondarily.  */

GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a )


/lib/绝对目录去掉, 既将"GROUP ( /lib/libc.so.6 /lib/libc_nonshared.a )"改为: GROUP ( libc.so.6 libc_nonshared.a )

--------------------------------------------------------------------------------
8) 
completed  GCC

  cd build-4.1.2 
  ../gcc-4.1.2/configure --target=arm-linux  --prefix=/cross/cross-arm  --enable-languages=c
  make
  make install

(出鬼的顺利,不支持c++,gcc 相关补丁也没有打, 凑合先用吧)

--------------------------------------------------------------------------------

9)  simple check
arm-linux-gcc --print-libgcc-file-name
arm-linux-gcc -print-search-dirs
arm-linux-gcc -o test test.c
arm-linux-objdump -D test

--------------------------------------------------------------------------------
10
build kernel for arm
   
为了配置方便,copy 一个default config linux2.6.24.4 的根目录. 然后就剪辑吧能去的都去掉.嘿嘿.
    
    cp arch/arm/configs/s3c2410_defconfig  .
    mv s3c2410_defconfig .config
   
    menuconfig:
    make ARCH=arm CROSS_COMPILE=arm-linux- menuconfig 

    zImage 出来了, download S3C2440 看看吧任意键进入boot menu. 2 downfrom uart,DNW下载代码,完成 4,写入nand flash. (不同系统不一样,monitor 咋写了)   boot os............. 操蛋,啥都没看到,
  
只是在串口上看到monitor输出如下:
Set boot params = root=/dev/ram init=/linuxrc initrd=0x00000000,0x00000000 console=ttyS1,115200 mem=65536K devfs=mount
Load Kernel...
Load Ramdisk...

   遇到的问题请继续看下一节...

--------------------------------------------------------------------------------
11
调整解压缩参数
   
   
到底啥是最重要的啊, 如果连个printf都不能用,运气未免太差. 参数中的ttyS1 (10节的输出),俺没有注意到(么经验啊). 于是上ADS AXD调试:
   
先连接上目标板,然后选run, 这样就可以reboot 系统,5, boot os, 然后用ADX stop,就会看到一段汇编了. 仔细查看发现arm 确实在运行一段程序,经过查询system.map,发现是panic( 我猜想是root fs没有...,但是没有显示内容到我的串口啊,串口接在uart1).
  
    
随意看看那个2440 mon程序, linux的加载方式如下:

    zImagenand flash copy 0x3040 0000 然后就jump过去. 内核参数放在0x3000 0100.
    goto_start = 0x3040 0000;
    (*
goto_start)(0, 193);   
  
不过对为啥不能启动还是没有线索啊...

   有几个比较可疑的内核配置选项可能引起问题比如
         boot option->
            compressed
rom boot loader base address      #
            default kernel command string                      #
  
所以俺又试了几个选项, # 的地址改成0x3040 0000...... 不幸还是不可以, 因为没有信息出现也不知道运行到了哪里,不过根据调试的结果,应该是过了解压缩阶段的....
  
事后俺查上面两个选项的含义( 就是按 ? ), #
是说ROM able zImage, 就是zImage直接在rom中运行时, 才有效所以犯了错误啊. 也不行, 因为如果没有办法传递kernel command line时才有效, s32440下无效. 帮助里列举有几个平台需要这个选项.

  先把参数地址为啥在0x3000 0100 runaddr为啥在0x3040 0000跳过不谈,为啥没有任何信息? 连解压内核的信息都没有? 看了几遍config, 找到了如下的选项:
    system type->
        
[0] S3C UART to use for low-level messages    
   
嘿嘿,进去把0改成1, 看看arm的相关启动代码,印证了通过这个选项选择内核解压缩信息的输出端口. 选成1, 再试,果然有内核解压缩信息打印出来,呵呵. 相关代码在内核的位置:
decompress_kernel  ->
    putstr("Uncompressing Linux...");
    gunzip();
    putstr(" done, booting the kernel. ");
->
include/asm-arm/plat-s3c
static void
putc(int ch)
{
    if (
uart_rd(S3C2410_UFCON) & S3C2410_UFCON_FIFOMODE) {
    .....
}
uart_rd(unsigned int reg)
{
    volatile unsigned int *ptr;

    ptr = (volatile unsigned int *)(reg + uart_base);
    return *ptr;
}
#define
uart_base S3C24XX_PA_UART + (0x4000*CONFIG_S3C_LOWLEVEL_UART_PORT)

--------------------------------------------------------------------------------
12.
内核控制台

   就是命令行里的console参数. 这里不打算讨论console到底是啥, 仅指出,俺没有看到内核正常的启动信息和这个选项大大的相关.我们分析下monitor给出的信息:

Set boot params = root=/dev/ram init=/linuxrc initrd=0x00000000,0x00000000 console=ttyS1,115200 mem=65536K devfs=mount
Load
Kernel...
Load Ramdisk...

 
  
这里console设置成了 ttyS1, linux2.6.24.4 要求(不知道具体从啥时候开始,2.6?) 名字是ttySAC1,指定串口1. monitor的代码就能知道了, monitor需要升级的.  ...走了冤枉路了,明白了monitor和内核这里的一点纠缠.
  
升级monitor之后... 嘿嘿,终于有东西了...呵呵

Uncompressing Linux...................................................... done
, booting the kernel.
Linux version 2.6.24.4 (root@localhost.localdomain) (gcc version 4.1.2) #7
Tue Apr 15 07:50:25 CST 2008
CPU: ARM920T [41129200] revision 0 (ARMv4T), cr=c0007177
Machine: SMDK2410
ATAG_INITRD is deprecated; please update your bootloader.

Memory policy: ECC disabled, Data cache writeback
CPU S3C2440A (id 0x32440001)
S3C244X: core 400.000 MHz, memory 100.000 MHz, peripheral 50.000 MHz
S3C24XX Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
CPU0: D VIVT write-back cache
CPU0: I cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
CPU0: D cache: 16384 bytes, associativity 64, 32 byte lines, 8 sets
Built 1 zonelists in Zone order, mobility grouping on.  Total pages: 16256
Kernel command line: root=/dev/ram init=/linuxrc initrd=0x00000000,0x00000000
console=
ttySAC1,115200 mem=65536K devfs=mount
irq: clearing pending ext status 000dff00
irq: clearing pending ext status 00001000
irq: clearing subpending status 000000ba
irq: clearing subpending status 00000092
PID hash table entries: 256 (order: 8, 1024 bytes)
timer tcon=00090000, tcnt a2c1, tcfg 00000200,00000000, usec 00001eb8
Console: colour dummy device 80x30
console [ttySAC1] enabled
Dentry cache hash table entries: 8192 (order: 3, 32768 bytes)
Inode-cache hash table entries: 4096 (order: 2, 16384 bytes)
Memory: 64MB = 64MB total
Memory: 63128KB available (1428K code, 223K data, 92K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
S3C2440: Initialising architecture
S3C2440: IRQ Support
S3C2440: Clock Support, DVS off
S3C24XX DMA Driver, (c) 2003-2004,2006 Simtec Electronics
DMA channel 0 at c4800000, irq 33
DMA channel 1 at c4800040, irq 34
DMA channel 2 at c4800080, irq 35
DMA channel 3 at c48000c0, irq 36
JFFS2 version 2.2. (NAND)
2001-2006 Red Hat, Inc.
io scheduler noop registered
io scheduler anticipatory registered (default)
io scheduler deadline registered
io scheduler cfq registered
Serial: 8250/16550 driver $Revision: 1.90 $ 4 ports, IRQ sharing enabled
s3c2440-uart.0: s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2440
s3c2440-uart.1: s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2440
s3c2440-uart.2: s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2440
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
loop: module loaded
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2440-nand s3c2440-nand: Tacls=3, 30ns Twrph0=7 70ns, Twrph1=3 30ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-
bit)
Scanning device for bad blocks
Creating 8 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00004000 : "Boot Agent"
0x00000000-0x00200000 : "S3C2410 flash partition 1"
0x00400000-0x00800000 : "S3C2410 flash partition 2"
0x00800000-0x00a00000 : "S3C2410 flash partition 3"
0x00a00000-0x00e00000 : "S3C2410 flash partition 4"
0x00e00000-0x01800000 : "S3C2410 flash partition 5"
0x01800000-0x03000000 : "S3C2410 flash partition 6"
0x03000000-0x04000000 : "S3C2410 flash partition 7"
mice: PS/2 mouse device common for all mice
S3C24XX RTC, (c) 2004,2006 Simtec Electronics
s3c2440-i2c s3c2440-i2c: slave address 0x10
s3c2440-i2c s3c2440-i2c: bus frequency set to 390 KHz
s3c2440-i2c s3c2440-i2c: i2c-0: S3C I2C adapter
S3C2410 Watchdog Timer, (c) 2004 Simtec Electronics
s3c2410-wdt s3c2410-wdt: watchdog inactive, reset disabled, irq enabled
drivers/rtc/hctosys.c: unable to open rtc device (rtc0)
List of all partitions:
1f00         16 mtdblock0 (driver?)
1f01       2048 mtdblock1 (driver?)
1f02       4096 mtdblock2 (driver?)
1f03       2048 mtdblock3 (driver?)
1f04       4096 mtdblock4 (driver?)
1f05      10240 mtdblock5 (driver?)
1f06      24576 mtdblock6 (driver?)
1f07      16384 mtdblock7 (driver?)
No filesystem could mount root, tried:  cramfs romfs
Kernel panic - not syncing: VFS: Unable to mount root fs on unknown-block(1,0)

--------------------------------------------------------------------------------
13.
内核参数的传递方式

    前边说过monitor吧内核参数放到了地址 0x3000 0100 这个地址. 这个道理何在呢. 先看内核打印内核命令行的地方: init/main.c
asmlinkage void __init
start_kernel(void)
     -->printk(KERN_NOTICE "Kernel command line: %s ",
boot_command_line);
    
是个全局变量,搜索下,arch/arm/kernel/setup.c:
void __init
setup_arch(char **cmdline_p)
{
    char *from =
default_command_line; /*.config 中指定的命令行*/
    ...
    mdesc = setup_machine(machine_arch_type);  /*
从上面串口输出知道是 "Machine: SMDK2410", .config决定*/
                /*
里边引用的lookup_machine_type arch/arm/kernel/head_common.S*/
......
    if (__atags_pointer)
        tags = phys_to_virt(__atags_pointer);
    else if (mdesc->boot_params)
        tags = phys_to_virt(
mdesc->boot_params);   
...
     /*
     * If we have the old style parameters, convert them to
     * a tag list.
     */
    if (tags->hdr.tag != ATAG_CORE)
       
convert_to_tag_list(tags); /*boot loader传递的参数, arch/arm/kernel/compat.c struct param_struct {
                                                  ..} 转换成tag list, 其中包括 ATAG_CMDLINE */
    if (tags->hdr.tag != ATAG_CORE)
        tags = (struct tag *)&init_tags;

    if (mdesc->fixup) /*s3c2410 NULL*/
        mdesc->fixup(mdesc, tags, &from, &meminfo);

    if (tags->hdr.tag == ATAG_CORE) {
        if (meminfo.nr_banks != 0)
            squash_mem_tags(tags);
        parse_tags(tags); /*
ATAG_CMDLINE parser 把相应命令行copy default_command_line, 也在这个文件内*/
    }

    ....
    memcpy(boot_command_line, from, COMMAND_LINE_SIZE);
    boot_command_line[COMMAND_LINE_SIZE-1] = '\0';
    parse_cmdline(
cmdline_p, from);
}

这里先忽略下mdesc是怎么被找到的,先直接搜索 mdesc的类型,可以找到 #define MACHINE_START(_type,_name) 这个宏,然后console"SMDK2410"这个宏定义, 可以在arch/arm/mach-s3c2410下找到:

MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch
                    * to SMDK2410 */
    /* Maintainer: Jonas Dietsche */
    .phys_io    = S3C2410_PA_UART,
    .io_pg_offst    = (((u32)S3C24XX_VA_UART) >> 18) & 0xfffc,
    .boot_params    =
S3C2410_SDRAM_PA + 0x100,
    .map_io        = smdk2410_map_io,
    .init_irq    = s3c24xx_init_irq,
    .init_machine    = smdk2410_init,
    .timer        = &s3c24xx_timer,
MACHINE_END

#define S3C2410_SDRAM_PA    (S3C2410_CS6)
#define
S3C2410_CS6 (0x30000000)

这下子就知道内核参数传递的方式了: (arm)
  
arch/arm/kernel/compat.c 中定义的struct param_struct { } 放到0x3000 0100 处即可....

至于去求证 monitor runAddr 和参数地址, 请看 :  (这个是monitor用到的参数,决定了runAddrs)

BootParams boot_params = {
    {"bootpara", 1},    //0=boot without parameters,1=boot with parameters
    {"cpuclk",   2},    //0=200M, 1=300M, 2=400M, 3=440M
    {"rundelay", 0},    //0 seconds
    {"serial",   1},    //0=serial port 0, 1=serial port 1
    {"baudrate", 115200},
    {"machine",  193},
    {"runAddr",  0x30400000},
    {"rootfs",   0},
    {"tty",      1},
    {"initrdA",  0},
    {"initrdL",  0},
    {"memsize",  0x04000000},
    {"devfs",    1},
    {"ostore",   0},    //0=nand, 1=nor
    {"userpara", sizeof(DEFAULT_USER_PARAMS)},
    DEFAULT_USER_PARAMS
};
从这个参数加载linux的代码在nand.c LoadRun .

 

阅读(1596) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~