S3C2440 從cross-tools到 linux2.6.24.4

admin @ 2014-03-25 , reply:0

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  (host:linux   targe:arm-linux)
      binutils-2.18                        ftp://ftp.ntu.edu.tw/pub/gnu/gnu/binutils/binutils-2.18.tar.bz2
      gcc-core-4.1.2                   ftp://ftp.ntu.edu.tw/pub/gnu/gnu/gcc/gcc-4.1.2/gcc-core-4.1.2.tar.bz2
      gcc-g++4.1.2                     ftp://ftp.ntu.edu.tw/pub/gnu/gnu/gcc/gcc-4.1.2/gcc-g++-4.1.2.tar.bz2
      glibc-2.6.1                             ftp://ftp.ntu.edu.tw/pub/gnu//gnu/glibc/glibc-2.6.1.tar.gz
      linux-2.6.24.4                       http://www.cn.kernel.org/pub/linux/kernel/v2.6/linux-2.6.24.4.tar.bz2    

--------------------------------------------------------------------------------
  2)  定義環境變數 (然後解壓縮...)

           export PREFIX=/cross/cross-arm           cross gcc的bin會放到這個目錄
           export TARGET=arm-linux                          arm 上的linux

          cd /cross/src        假設你下載的gcc 和binutil在這個目錄(你當然要解壓縮了)
          mkdir build-binutils build-gcc build-glibc 

--------------------------------------------------------------------------------
   3) binutils (要分清host和target啊...)
         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 cpu和target cpu一樣的話,基本不用cross toolchain系統通過編譯選項也能實現這個功能).
--with-newlib 這只是個bug的work 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  :兩個邊界檢查使用的庫,有問題,禁止

http://www.mail-archive.com/gcc@gcc.gnu.org/msg31021.html    無libc的時候這幾個庫是不能編譯通過的 :ssp,mudflap,gomp
http://projects.linuxtogo.org/pipermail/openembedded-commits/2007-November/010465.html  這個線索是這個問題的補丁
還有官方的 bug :http://gcc.gnu.org/bugzilla/show_bug.cgi?id=25035

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

     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://ftp.osuosl.org/pub/clfs/conglomeration/glibc/
           推薦文章:  http://blog.chinaunix.net/u/26710/showart_394113.html          
           RTLD_SINGLE_THREAD_P 的fix(上面的patch已經包含了,參考下): 
                             http://sources.redhat.com/ml/libc-ports/2006-10/msg00070.html
          
            用 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的載入方式如下:

    將zImage從nand flash copy到 0x3040 0000 然後就jump過去. 內核參數放在0x3000 0100.
    goto_start = 0x3040 0000;
    (*goto_start)(0, 193);   
   不過對為啥不能啟動還是沒有線索啊...

   有幾個比較可疑的內核配置選項可能引起問題比如
         boot option->
            compressed rom boot loader base address      #<a>
            default kernel command string                      #<b>
   所以俺又試了幾個選項, 把 #<a> 的地址改成0x3040 0000...... 不幸還是不可以, 因為沒有信息出現也不知道運行到了哪裡,不過根據調試的結果,應該是過了解壓縮階段的....
   事後俺查上面兩個選項的含義( 就是按 ? 了), #<a> 是說ROM able 的zImage, 就是zImage直接在rom中運行時, 才有效所以犯了錯誤啊. <b> 也不行, 因為如果沒有辦法傳遞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 .

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



[admin via 研發互助社區 ] S3C2440 從cross-tools到 linux2.6.24.4已經有1338次圍觀

http://cocdig.com/docs/show-post-42155.html