随笔-118  评论-133  文章-4  trackbacks-0
 
注:
    原文出自taoyuetao大侠的博客上:
http://www.eetop.cn/blog/html/45/11145_itemid_1746.html
    小弟参考之研究s3c2410相关代码,然后做了稍微的修改,作为一个学习笔记,方便以后的学习,也希望对后人有所帮助^_^

函数__create_page_tables介绍:

假设内核起始物理地址是0x30008000,虚拟地址是0xC0008000,下面的代码是建立内核起始处4MB空间的映射,
采用了一级映射方式,即段式(section)映射方式,每段映射范围为1MB空间。于是需要建立4个表项,实现:
虚拟地址0xC0000000~0xC0300000,映射到物理地址0x30000000~0x30300000


     .macro  pgtbl, reg, rambase
     adr \reg, stext
     sub \reg, \reg, #0x4000    
     .endm
    
     .macro  krnladr, rd, pgtable, rambase
     bic \rd, \pgtable, #0x000ff000
     .endm
    
/*

 * Setup the initial page tables.  We only setup the barest

 * amount which are required to get the kernel running, which

 * generally means mapping in the kernel code.

 *

 * r8  = machinfo

 * r9  = cpuid

 * r10 = procinfo

 *

 * Returns:

 *  r0, r3, r5, r6, r7 corrupted

 *  r4 = physical page table address

 */

    .type   __create_page_tables, %function

__create_page_tables:

    ldr r5, [r8, #MACHINFO_PHYSRAM] @ physram   r5=0x30000000

    pgtbl   r4, r5              @ page table address    r4=0x30004000

 

    /*

     * Clear the 16K level 1 swapper page table

     */

    mov r0, r4

    mov r3, #0

    add r6, r0, #0x4000

1:  str r3, [r0], #4

    str r3, [r0], #4

    str r3, [r0], #4

    str r3, [r0], #4

    teq r0, r6

    bne 1b

 

    ldr r7, [r10, #PROCINFO_MMUFLAGS]   @ mmuflags         //r7=0x00000c1e

    /*

*  r7用于设置第一级表描述符之用:

     *      AP          :11(读/写权限)

     *                :0000

     *      C           : 1(高速缓存)

     *      B           : 1 (缓冲)

     *      bit[1 0]    :10(标识此为节描述符)

    */

    /*

     * Create identity mapping for first MB of kernel to

     * cater for the MMU enable.  This identity mapping

     * will be removed by paging_init().  We use our current program

     * counter to determine corresponding section base address.

     *

* 为以后MMU的开启准备好内存头1M空间的转换表,

* 采用平板地址映射模式(表索引==节基址)

*/

    mov r6, pc, lsr #20         @ start of kernel section      //r6=0x00000300

    orr r3, r7, r6, lsl #20     @ flags + kernel base          //r3=0x30000c1e

    str r3, [r4, r6, lsl #2]    @ identity mapping  //[0x30004c00]=0x30000c1e

/*  结果:

*  虚拟地址        物理地址

*  0x300000000     0x30000000

    /*

     * Now setup the pagetables for our kernel direct

     * mapped region.  We round TEXTADDR down to the

     * nearest megabyte boundary.  It is assumed that

     * the kernel fits within 4 contigous 1MB sections.

     *

*为内核占用的头4M地址准备好转换表(在这采用的就不是平板地址映射模式了)

/

    add r0, r4,  #(TEXTADDR & 0xff000000) >> 18                 //ro=0x30007000

    str r3, [r0, #(TEXTADDR & 0x00f00000) >> 18]!       @ KERNEL + 0MB

    add r3, r3, #1 << 20                                        //r3=0x30100c1e

    str r3, [r0, #4]!                                   @ KERNEL + 1MB

    add r3, r3, #1 << 20                                        //r3=0x30200c1e

    str r3, [r0, #4]!                                   @ KERNEL + 2MB

    add r3, r3, #1 << 20                                        //0x30300c1e

    str r3, [r0, #4]                                    @ KERNEL + 3MB

    /*

     *  结果:

     *  虚拟地址        物理地址

              0xc0000000           0x30000000

              0xc0100000           0x30100000

              0xc0200000           0x30200000

              0xc0300000           0x30300000

       */

   

    /*

     * Then map first 1MB of ram in case it contains our boot params.

     *

*  映射sdram的头1M以防boot params需要(不是已经映射过了吗?)

*/

    add r0, r4, #VIRT_OFFSET >> 18                              //r0=0x30007000

    orr r6, r5, r7                                              //r6=0x30000c1e

    str r6, [r0]                                       //[0x30007000]=0x3000c1e

 

#ifdef CONFIG_XIP_KERNEL

    /*

     * Map some ram to cover our .data and .bss areas.

     * Mapping 3MB should be plenty.

     */

    sub r3, r4, r5

    mov r3, r3, lsr #20

    add r0, r0, r3, lsl #2

    add r6, r6, r3, lsl #20

    str r6, [r0], #4

    add r6, r6, #(1 << 20)

    str r6, [r0], #4

    add r6, r6, #(1 << 20)

    str r6, [r0]

#endif

 

#ifdef CONFIG_DEBUG_LL

    bic r7, r7, #0x0c           @ turn off cacheable

                        @ and bufferable bits

    /*

     * Map in IO space for serial debugging.

     * This allows debug messages to be output

     * via a serial console before paging_init.

     */

    ldr r3, [r8, #MACHINFO_PGOFFIO]

    add r0, r4, r3

    rsb r3, r3, #0x4000         @ PTRS_PER_PGD*sizeof(long)

    cmp r3, #0x0800         @ limit to 512MB

    movhi   r3, #0x0800

    add r6, r0, r3

    ldr r3, [r8, #MACHINFO_PHYSIO]

    orr r3, r3, r7

1:  str r3, [r0], #4

    add r3, r3, #1 << 20

    teq r0, r6

    bne 1b

#if defined(CONFIG_ARCH_NETWINDER) || defined(CONFIG_ARCH_CATS)

    /*

     * If we're using the NetWinder, we need to map in

     * the 16550-type serial port for the debug messages

     */

    teq r1, #MACH_TYPE_NETWINDER

    teqne   r1, #MACH_TYPE_CATS

    bne 1f

    add r0, r4, #0xff000000 >> 18

    orr r3, r7, #0x7c000000

    str r3, [r0]

1:

#endif

#ifdef CONFIG_ARCH_RPC

    /*

     * Map in screen at 0x02000000 & SCREEN2_BASE

     * Similar reasons here - for debug.  This is

     * only for Acorn RiscPC architectures.

     */

    add r0, r4, #0x02000000 >> 18

    orr r3, r7, #0x02000000

    str r3, [r0]

    add r0, r4, #0xd8000000 >> 18

    str r3, [r0]

#endif

#endif

    mov pc, lr


posted @ 2007-08-02 12:09 lfc 阅读(1770) | 评论 (0)编辑 收藏
注:
    原文出自taoyuetao大侠的博客上:
http://www.eetop.cn/blog/html/45/11145_itemid_1512.html
    小弟参考之研究s3c2410相关代码,然后做了稍微的修改,作为一个学习笔记,方便以后的学习,也希望对后人有所帮助^_^

前一篇介绍了汇编函数__lookup_processor_type

这一篇介绍__lookup_architecture_type函数

函数__lookup_architecture_type介绍:
每个机器(一般指的是某一个电路板)都有自己的特殊结构,如物理内存地址,物理I/O地址,显存起始地址等等,
这个结构为struct machine_desc,定义在asm-arm/mach/arch.h:
struct machine_desc {

    /*

     * Note! The first five elements are used

     * by assembler code in head-armv.S

     */

    unsigned int        nr;     /* architecture number  */

    unsigned int        phys_ram;   /* start of physical ram */

    unsigned int        phys_io;    /* start of physical io */

    unsigned int        io_pg_offst;    /* byte offset for io

                         * page tabe entry  */

 

    const char      *name;      /* architecture name    */

    unsigned long       boot_params;    /* tagged list      */

 

    unsigned int        video_start;    /* start of video RAM   */

    unsigned int        video_end;  /* end of video RAM */

 

    unsigned int        reserve_lp0 :1; /* never has lp0    */

    unsigned int        reserve_lp1 :1; /* never has lp1    */

    unsigned int        reserve_lp2 :1; /* never has lp2    */

    unsigned int        soft_reboot :1; /* soft reboot      */

    void            (*fixup)(struct machine_desc *,

                     struct tag *, char **,

                     struct meminfo *);

    void            (*map_io)(void);/* IO mapping function  */

    void            (*init_irq)(void);

    struct sys_timer    *timer;     /* system tick timer    */

    void            (*init_machine)(void);

};

这个结构一般都定义在(arm平台为例)kernel\arch\arm\mach-xxx\xxx.c中,是用宏来定义的,以s3c2410的开发板为例:
定义在kernel\arch\arm\mach-s3c2410\mach-smdk2410.c文件中,如下所示:
MACHINE_START(SMDK2410, "SMDK2410") /* @TODO: request a new identifier and switch to SMDK2410 */

    /* Maintainer: Jonas Dietsche */

    .phys_ram   = S3C2410_SDRAM_PA,

    .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   = smdk2410_init_irq,

    .timer      = &s3c24xx_timer,

MACHINE_END

这些宏也定义在kernel/include/asm-arm/mach/arch.h中,以MACHINE_START为例:
#define MACHINE_START(_type,_name)      \

const struct machine_desc __mach_desc_##_type   \

 __attribute__((__section__(".arch.info.init"))) = {    \

    .nr     = MACH_TYPE_##_type,    \

    .name       = _name,

 

#define MACHINE_END             \

};

展开之后结构的是:
__mach_desc_SMDK2410= {
 .nr = MACH_TYPE_SMDK2410,
 .name = "SMDK2410",

中间的1__attribute__((__section__(".arch.info"))) = {说明将这个结构放到指定的段.arch.info中,这和前面的
.proc.info
是一个意思,__attribute__((__section__的含义参考GNU手册。后面的宏都是类似的含义,这里就不再一一介绍。

 

下面开始说明源码:

1行实现r3指向3b的地址,3b__lookup_processor_type介绍的第19行,

3行将r3所指向的数据区的数据读出到r4r5r6,执行结果是

R5= __arch_info_beginr6= __arch_info_endr4=19行的地址

用仿真器查看:

R5= 0xc0018694

R6= 0xc00186cc

R4= 0xc0008324 (为何是0xc0008324而不是0x30008324???)

4行算出虚、实地址的偏移,

5-6行的结果应该是r5指向__arch_info_begin的实地址,r6指向__arch_info_end的实地址。

7行读取__mach_desc_ SMDK2410结构中的nr参数到r3中,

8行比较r3r1中的机器编号是否相同,
r3
中的nrMACH_TYPE_SMDK2410定义在kernel\include\asm-arm\mach-types.h中:
#define MACH_TYPE_SMDK2410             193

r1中的值是由bootloader传递过来的,这在<<linux启动流程分析(1)---bootloader启动内核过程>>中有说明,如果机器编号相同,跳到14行返回。如果不同则将地址指针增加,在跳到7行继续查找,见10--12行的代码,如果检索完所有的machine_desc仍然没有找到则将r5清零并返回。

/*

 * Lookup machine architecture in the linker-build list of architectures.

 * Note that we can't use the absolute addresses for the __arch_info

 * lists since we aren't running with the MMU on (and therefore, we are

 * not in the correct address space).  We have to calculate the offset.

 *

 *  r1 = machine architecture number

 * Returns:

 *  r3, r4, r6 corrupted

 *  r5 = mach_info pointer in physical address space

 */

    .type   __lookup_machine_type, %function

1:  __lookup_machine_type:

2:      adr r3, 3b

3:      ldmia   r3, {r4, r5, r6}

4:      sub r3, r3, r4          @ get offset between virt&phys

5:      add r5, r5, r3          @ convert virt addresses to

6:      add r6, r6, r3          @ physical address space

7:  1:  ldr r3, [r5, #MACHINFO_TYPE]    @ get machine type

8:      teq r3, r1              @ matches loader number?

9:      beq 2f              @ found

10:     add r5, r5, #SIZEOF_MACHINE_DESC    @ next machine_desc

11:     cmp r5, r6

12:     blo 1b

13:     mov r5, #0              @ unknown machine

14  2:  mov pc, lr


posted @ 2007-07-25 17:05 lfc 阅读(1288) | 评论 (0)编辑 收藏
注:
    原文出自taoyuetao大侠的博客上:
http://www.eetop.cn/blog/html/45/11145_itemid_1396.html
    小弟参考之研究s3c2410相关代码,然后做了稍微的修改,作为一个学习笔记,方便以后的学习,也希望对后人有所帮助^_^

前面一篇文章,简单介绍了内核启动的汇编主流程,这篇介绍其中调用的汇编子函数__lookup_processor_type

函数__lookup_processor_type介绍:

内核中使用了一个结构struct proc_info_list,用来记录处理器相关的信息,该结构定义在
kernel/include/asm-arm/procinfo.h
头文件中。

/*

 * Note!  struct processor is always defined if we're

 * using MULTI_CPU, otherwise this entry is unused,

 * but still exists.

 *

 * NOTE! The following structure is defined by assembly

 * language, NOT C code.  For more information, check:

 *  arch/arm/mm/proc-*.S and arch/arm/kernel/head.S

 */

struct proc_info_list {

    unsigned int        cpu_val;

    unsigned int        cpu_mask;

    unsigned long       __cpu_mmu_flags;    /* used by head.S */

    unsigned long       __cpu_flush;        /* used by head.S */

    const char      *arch_name;

    const char      *elf_name;

    unsigned int        elf_hwcap;

    const char      *cpu_name;

    struct processor    *proc;

    struct cpu_tlb_fns  *tlb;

    struct cpu_user_fns *user;

    struct cpu_cache_fns    *cache;

};

arch/arm/mm/proc-arm920.S文件中定义了所有和arm920有关的proc_info_list,我们使用的arm920定义如下:

    .section ".proc.info.init", #alloc, #execinstr

 

    .type   __arm920_proc_info,#object

__arm920_proc_info:

    .long   0x41009200

    .long   0xff00fff0

.

.

 

由于.section指示符,上面定义的__arm920_proc_info信息在编译的时候被放到了.proc.info段中,这是由linux的链接脚本文件arch/arm/kernel/vmlinux.lds指定的,参考如下:

SECTIONS

{

    . = TEXTADDR;

    .init : {           /* Init code and data       */

        _stext = .;

            _sinittext = .;

            *(.init.text)

            _einittext = .;

        __proc_info_begin = .;

            *(.proc.info.init)

        __proc_info_end = .;

                .

                .

 

这里的符号__proc_info_begin指向.proc.info的起始地址,而符号__proc_info_end指向.proc.info的结束地址。后面就会引用这两个符号,来指向.proc.info这个段。
    

下面来来看看函数的源代码,为了分析方便将函数按行进行编号,其中17-18行就是前面提到的对.proc.info的引用,
2行将19行的地址放到寄存器r3中,adr是小范围的地址读取伪指令。

3行将r3所指向的数据区的数据读出到r5r6r9,执行结果是

R5=__proc_info_beginr6=__proc_info_endr9=19行的地址

用仿真器查看:

r5=0xc0018664

r6=0xc0018694

r9=0xc0008324(为何是0xc0008324而不是0x30008324???)

4行算出虚、实地址的偏移,

5-6行的结果应该是r5指向__proc_info_begin的实地址,r6指向__proc_info_end的实地址。

7行读取cpuid,这是一个协处理器指令,将processor ID存储在r9中。

8行将r5指向的__arm920_proc_info开始的数据读出放到寄存器r3r4,结果r3=0x41009200 (cpu_val)r4=0xff00fff0 (cpu_mask)

9-10行将读出的id和结构中的id进行比较,如果id相同则返回,返回时r9存储
processor ID
,如果id不匹配,则将指针r10增加PROC_INFO_SZ (proc_info_list结构的长度,在这等于48),如果r5小于r6指定的地址,也就是
__proc_info_end
,则继续循环比较下一个proc_info_list中的id,如第11-14行的代码,如果查找到__proc_info_end,仍未找到一个匹配的id,则将r5清零并返回,如15-16行,也就是说如果函数执行成功则r5指向匹配的proc_info_list结构地址,如果函数返回错误则r50

 

/*

 * Read processor ID register (CP#15, CR0), and look up in the linker-built

 * supported processor list.  Note that we can't use the absolute addresses

 * for the __proc_info lists since we aren't running with the MMU on

 * (and therefore, we are not in the correct address space).  We have to

 * calculate the offset.

 *

 * Returns:

 *  r3, r4, r6 corrupted

 *  r5 = proc_info pointer in physical address space

 *  r9 = cpuid

 */

    .type   __lookup_processor_type, %function

1   __lookup_processor_type:

2       adr r3, 3f

3       ldmda   r3, {r5, r6, r9}

4       sub r3, r3, r9          @ get offset between virt&phys

5       add r5, r5, r3          @ convert virt addresses to

6       add r6, r6, r3          @ physical address space

7       mrc p15, 0, r9, c0, c0      @ get processor id

8   1:  ldmia   r5, {r3, r4}            @ value, mask

9       and r4, r4, r9          @ mask wanted bits

10     teq r3, r4

11      beq 2f

12      add r5, r5, #PROC_INFO_SZ       @ sizeof(proc_info_list)

13      cmp r5, r6

14      blo 1b

15      mov r5, #0              @ unknown processor

16  2:  mov pc, lr
   
/*

 * Look in include/asm-arm/procinfo.h and arch/arm/kernel/arch.[ch] for

 * more information about the __proc_info and __arch_info structures.

 */

17      .long   __proc_info_begin

18      .long   __proc_info_end

19  3:  .long   .

20      .long   __arch_info_begin

21      .long   __arch_info_end

 



posted @ 2007-07-24 20:50 lfc 阅读(1556) | 评论 (0)编辑 收藏

USB 驱动移植心得
一、代码修改
主要是按照这个贴来做:
http://www.hfrk.net/S3C2410/kaifa/063152202483252_37.htm
我也看过其它不同版本的内核关于usb驱动的移植,移植方法几乎一样,只是修改的文件不同而已。上面的贴子有不少头文件没有例出来,以下是我按照以上贴子添加的代码(好像在很多论坛上包括头文件部分都显示不出来,在这里把include前面的#给删了,希望有帮助):

/*add by lfc*/
include <asm/arch/regs-clock.h>
include <asm/arch/usb-control.h>
include <linux/device.h>
include <linux/delay.h>
/*end add*/

/**********************add by lfc*************************************/
static struct s3c2410_hcd_info usb_sbc2410_info = {
       .port[0]        = {
               .flags  = S3C_HCDFLG_USED
       }
};

int usb_sbc2410_init(void)
{
unsigned long upllvalue = (0x78<<12)|(0x02<<4)|(0x03);
printk("USB Control, (c) 2006 sbc2410\n");
s3c_device_usb.dev.platform_data = &usb_sbc2410_info;
while(upllvalue!=__raw_readl(S3C2410_UPLLCON))
{
__raw_writel(upllvalue,S3C2410_UPLLCON);
mdelay(1);
}
return 0;
}

/***************************end add**********************/

static void __init smdk2410_map_io(void)
{
s3c24xx_init_io(smdk2410_iodesc, ARRAY_SIZE(smdk2410_iodesc));
s3c24xx_init_clocks(0);
s3c24xx_init_uarts(smdk2410_uartcfgs, ARRAY_SIZE(smdk2410_uartcfgs));
s3c24xx_set_board(&smdk2410_board);
/*************************add by lfc****************************/
       usb_sbc2410_init();
/*************************end add*******************************/
}

上面的修改其实也参考了这个牛贴一下,里面有大虾们对USB驱动移植的讨论,还不错:
http://www.linuxforum.net/forum/showflat.php?Cat=&Board=embedded&Number=556915&page=0&view=collapsed&sb=5&o=0&fpart=

其实到了这里,要修改的代码已经修改完了,比添加Nand flash的支持修改的地方还要少^_^,不过我一直以为还没修改好,最后发现原来是没配置好~_~

二、内核配置
下面说一下郁闷了我好一阵子的内核配置(支持USB)问题,这个就比Nand flash的配置要复杂多了。
1、让内核支持热插拔
               General setup  --->  
 
│ │[*] Support for hot-pluggable devices

2、USB驱动设置,可能有些不选也行,不过没时间去试,至于为什么要选这些选项的话可以看一下这个贴(Linux下的硬件驱动——USB设备):
http://www-128.ibm.com/developerworks/cn/linux/l-usb/index1.html

  │ │                Device Drivers  --->
│ │              Generic Driver Options  --->          
<*> Hotplug firmware loading support    
 
│ │              Block devices  --->  
 
│ │              <*> Low Performance USB Block driver  
 
│ │              SCSI device support  --->  
 
│ │  <*>   SCSI generic support  
│ │  [*]   Probe all LUNs on each SCSI device    
 
│ │              USB support  --->        
 
│ │<*> Support for Host-side USB    
│ │[*]   USB device filesystem
 
│ │<*>   OHCI HCD support  
│ │<*>   USB Mass Storage support
 
│ │[*]   USB Monitor

3、加入了MSDOS fsVFAT fs的支持。

  │ │                File systems  --->      
 
│ │        DOS/FAT/NT Filesystems  --->  
 
│ ┌─────────────────────────────────────────────────────────────────────┐ │
 
│ │                 <*> MSDOS fs support                                │ │
 
│ │                 <*> VFAT (Windows-95) fs support                    │ │
 
│ │                 (936) Default codepage for FAT                      │ │
 
│ │                 (cp936) Default iocharset for FAT                   │ │
 
│ │                 < > NTFS file system support

做完这些后,插入u盘后,内核应该可以识别到u盘,出现:
usb 1-1: new full speed USB device using s3c2410-ohci and address 3
ub(1.3): GetMaxLUN returned 0, using 1 LUNs

但是,还有下面一句出错提示:
/dev/ub/a: unknown partition table

再次查看了贴子上大虾们的讨论,提到:“使能CONFIG_MSDOS_PARTITION选项”,再仔细查找,发现配置选项如下:
│ │                File systems  --->
│ │                Partition Types  --->  
 
│ │     [*]   PC BIOS (MSDOS partition tables) support
加上这个后应该就可以挂载usb上的MSDOS分区了

以下是我的内核插入u盘后的提示信息:
usb 1-1: new full speed USB device using s3c2410-ohci and 2
ub(1.2): GetMaxLUN returned 0, using 1 LUNs
/dev/ub/a: p1
表示usb设备已经挂载到/dev/ub/a/part1目录下

4. 加入中文字体库(可惜在我的板上还是没能正常显示中文~_~,知道的朋友麻烦告诉我一声,大家一起探讨)
 
│ │        Native Language Support  --->    
 
│ │<*>   Simplified Chinese charset (CP936, GB2312)  
 
│ │<*>   NLS UTF8

以下是挂载usb设备后的显示:
[root@luofuchong /]# mount -t vfat -o iocharset=cp936 /dev/ub/a/part1 /mnt
[root@luofuchong /]# ls /mnt
cramfs-1.1.tar.gz        netkit-base-0.17.tar.gz  thttpd-2.25b.tar.gz
lfc                      settings.dat             . . I. ..  . .txt

三、一点心得。

1、如果想知道内核有没有识别出u盘的话可以执行命令:cat /proc/partitions ,看看插入USB前后分区信息有什么不同就知道了。


2、另外,如果想让内核把它当成SCSI设备来处理的话,只要把上面:
 │ │                Device Drivers  --->    
 
│ │              Block devices  --->  
 
│ │              <*> Low Performance USB Block driver
的 Low Performance USB Block driver这个选项去掉,然后把:
 │ │                Device Drivers  --->
 │ │              SCSI device support  --->  
 │ │              <*>SCSI disk support
的SCSI disk support这个选项选上,重新编译内核就行。
注:
    个人觉得使用usb设备的话Low Performance USB Block driver比SCSI disk要好,自己看着办吧^_^

3、最后,一般都会新建一个/dev/sda1的链接指向usb设备的挂载点的,可以在启动文件中使用命令ln -s xxx xxx来建立这个链接。
 

四、
   呵呵,说了一大堆的废话,希望不要见怪。毕竟我对usb设备了解不多,如果有什么说错的地方请各位大虾见谅。其实关于usb驱动的移植在网上有不少的贴,我在这里只对针对我的经历作一点总结而已,希望能对大家有一点的帮助^_^

 

posted @ 2007-01-24 13:21 lfc 阅读(7802) | 评论 (9)编辑 收藏

注:
  u-boot
使用的是打上:
http://www.hhcn.com/cgi-bin/topic.cgi?forum=3&topic=651&show=0
keety大侠提供的补丁生成的u-boot-1.1.3


这段时间不断有人问我u-boot启动内核的问题,记得在上次提供的u-boot源码中提到了go的方案,不过其实u-boot本来有一种更好的方案:
bootm
花了不少时间,查看了论坛上不少的帖子,认真阅读了bootm的源码,终于使用bootm把内核给跑起来了,
现把解决方法介绍如下:



一、在开始之前先说明一下bootm相关的东西。

1、首先说明一下,S3C2410架构下的bootm只对sdram中的内核镜像文件进行操作(好像AT91架构提供了一段从flash复制内核镜像的代码,不过针对s3c2410架构就没有这段代码,虽然可以在u-boot下添加这段代码,不过好像这个用处不大),所以请确保你的内核镜像下载到sdram中,或者在bootcmd下把flash中的内核镜像复制到sdram中。

2、-a参数后是内核的运行地址,-e参数后是入口地址。

3、
1)如果我们没用mkimage对内核进行处理的话,那直接把内核下载到0x30008000再运行就行,内核会自解压运行(不过内核运行需要一个tag来传递参数,而这个tag建议是由bootloader提供的,在u-boot下默认是由bootm命令建立的)。
 
2)如果使用mkimage生成内核镜像文件的话,会在内核的前头加上了64byte的信息,供建立tag之用。bootm命令会首先判断bootm xxxx 这个指定的地址xxxx是否与-a指定的加载地址相同。
(1)如果不同的话会从这个地址开始提取出这个64byte的头部,对其进行分析,然后把去掉头部的内核复制到-a指定的load地址中去运行之
(2)如果相同的话那就让其原封不同的放在那,但-e指定的入口地址会推后64byte,以跳过这64byte的头部。


二、好,接着介绍使用mkimage生成镜像文件并下载运行的方法。

方法一、
1、首先,用u-boot/tools/mkimage这个工具为你的内核加上u-boot引导所需要的文件头,具体做法如下:
[root@localhost tftpboot]#mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008000 -d zImage zImage.img
Image Name:   linux-2.6.14
Created:      Fri Jan 12 17:14:50 2007
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    1262504 Bytes = 1232.91 kB = 1.20 MB
Load Address: 0x30008000
Entry Point:  0x30008000

这里解释一下参数的意义:
        -A ==> set architecture to 'arch'
        -O ==> set operating system to 'os'
        -T ==> set image type to 'type'
        -C ==> set compression type 'comp'
        -a ==> set load address to 'addr' (hex)
        -e ==> set entry point to 'ep' (hex)
        -n ==> set image name to 'name'
        -d ==> use image data from 'datafile'
        -x ==> set XIP (execute in place)
 

2 、下载内核
U-Boot 1.1.3 (Jan 12 2007 - 16:16:36)

U-Boot code: 33F80000 -> 33F9BAC0  BSS: -> 33F9FBAC
RAM Configuration:
Bank #0: 30000000 64 MB
Nor Flash: 512 kB
Nand Flash:  64 MB
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0
sbc2410=>tftp 0x31000000 zImage.img        
TFTP from server 192.168.1.115; our IP address is 192.168.1.128
Filename 'zImage.img'.
Load address: 0x31000000
Loading: #################################################################
        #################################################################
        #################################################################
        ####################################################
done
Bytes transferred = 1263324 (1346dc hex)


3.运行 

sbc2410=>bootm 0x31000000
## Booting image at 31000000 ...
  Image Name:   linun-2.6.14 
  Image Type:   ARM Linux Kernel Image (uncompressed)
  Data Size:    1263260 Bytes =  1.2 MB
  Load Address: 30008000
  Entry Point:  30008000
  Verifying Checksum ... OK
OK

Starting kernel ...

Uncompressing Linux.............................................................Linux version 2.6.14 (root@luofuchong) (gcc version 3.4.1) #21 Fri Oct 20 17:206CPU: ARM920Tid(wb) [41129200] revision 0 (ARMv4T)
Machine: SMDK2410
Memory policy: ECC disabled, Data cache writeback
CPU S3C2410A (id 0x32410002)
S3C2410: core 202.800 MHz, memory 101.400 MHz, peripheral 50.700 MHz
S3C2410 Clocks, (c) 2004 Simtec Electronics
CLOCK: Slow mode (1.500 MHz), fast, MPLL on, UPLL on
USB Control, (c) 2006 sbc2410
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
Kernel command line: console=ttySAC0 root=/dev/nfs nfsroot=192.168.1.115:/frien"irq: clearing subpending status 00000002
PID hash table entries: 512 (order: 9, 8192 bytes)
timer tcon=00500000, tcnt a509, tcfg 00000200,00000000, usec 00001e4c
Console: colour dummy device 80x30
Dentry cache hash table entries: 16384 (order: 4, 65536 bytes)
Inode-cache hash table entries: 8192 (order: 3, 32768 bytes)
Memory: 64MB = 64MB total
Memory: 62208KB available (1924K code, 529K data, 108K init)
Mount-cache hash table entries: 512
CPU: Testing write buffer coherency: ok
softlockup thread 0 started up.
NET: Registered protocol family 16
S3C2410: Initialising architecture
SCSI subsystem initialized
usbcore: registered new driver usbfs
usbcore: registered new driver hub
S3C2410 DMA Driver, (c) 2003-2004 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
NetWinder Floating Point Emulator V0.97 (double precision)
devfs: 2004-01-31 Richard Gooch (rgooch@atnf.csiro.au)
devfs: devfs_debug: 0x0
devfs: boot_options: 0x1
yaffs Oct 18 2006 12:39:51 Installing.
Console: switching to colour frame buffer device 30x40
fb0: s3c2410fb frame buffer device
fb1: Virtual frame buffer device, using 1024K of video memory
led driver initialized
s3c2410 buttons successfully loaded
s3c2410_serial0 at MMIO 0x50000000 (irq = 70) is a S3C2410
s3c2410_serial1 at MMIO 0x50004000 (irq = 73) is a S3C2410
s3c2410_serial2 at MMIO 0x50008000 (irq = 76) is a S3C2410
io scheduler noop registered
io scheduler anticipatory registered
io scheduler deadline registered
io scheduler cfq registered
RAMDISK driver initialized: 16 RAM disks of 4096K size 1024 blocksize
usbcore: registered new driver ub
Cirrus Logic CS8900A driver for Linux (Modified for SMDK2410)
eth0: CS8900A rev E at 0xe0000300 irq=53, no eeprom , addr: 08: 0:3E:26:0A:5B
S3C24XX NAND Driver, (c) 2004 Simtec Electronics
s3c2410-nand: mapped registers at c4980000
s3c2410-nand: timing: Tacls 10ns, Twrph0 30ns, Twrph1 10ns
NAND device: Manufacturer ID: 0xec, Chip ID: 0x76 (Samsung NAND 64MiB 3,3V 8-bi)Scanning device for bad blocks
Bad eraseblock 1884 at 0x01d70000
Creating 4 MTD partitions on "NAND 64MiB 3,3V 8-bit":
0x00000000-0x00020000 : "vivi"
0x00020000-0x00030000 : "param"
0x00030000-0x00200000 : "kernel"
0x00200000-0x04000000 : "root"
usbmon: debugfs is not available
s3c2410-ohci s3c2410-ohci: S3C24XX OHCI
s3c2410-ohci s3c2410-ohci: new USB bus registered, assigned bus number 1
s3c2410-ohci s3c2410-ohci: irq 42, io mem 0x49000000
hub 1-0:1.0: USB hub found
hub 1-0:1.0: 2 ports detected
Initializing USB Mass Storage driver...
usbcore: registered new driver usb-storage
USB Mass Storage support registered.
usbcore: registered new driver usbmouse
drivers/usb/input/usbmouse.c: v1.6:USB HID Boot Protocol mouse driver
mice: PS/2 mouse device common for all mice
s3c2410 TouchScreen successfully loaded
UDA1341 audio driver initialized
NET: Registered protocol family 2
IP route cache hash table entries: 1024 (order: 0, 4096 bytes)
TCP established hash table entries: 4096 (order: 2, 16384 bytes)
TCP bind hash table entries: 4096 (order: 2, 16384 bytes)
TCP: Hash tables configured (established 4096 bind 4096)
TCP reno registered
TCP bic registered
NET: Registered protocol family 1
IP-Config: Complete:
     device=eth0, addr=192.168.1.128, mask=255.255.255.0, gw=192.168.1.1,
    host=luofuchong, domain=, nis-domain=(none),
    bootserver=192.168.1.1, rootserver=192.168.1.115, rootpath=
Looking up port of RPC 100003/2 on 192.168.1.115
Looking up port of RPC 100005/1 on 192.168.1.115
VFS: Mounted root (nfs filesystem).
Mounted devfs on /dev
Freeing init memory: 108K
init started:  BusyBox v1.1.3 (2006.09.20-14:52+0000) multi-call binary
Starting pid 696, console /dev/tts/0: '/etc/init.d/rcS'

Please press Enter to activate this console.



方法二、
1、首先,用u-boot/tools/mkimage这个工具为你的内核加上u-boot引导所需要的文件头,具体做法如下:
[root@localhost tftpboot]#mkimage -n 'linux-2.6.14' -A arm -O linux -T kernel -C none -a 0x30008000 -e 0x30008040 -d zImage zImage.img
Image Name:   linux-2.6.14
Created:      Fri Jan 12 17:14:50 2007
Image Type:   ARM Linux Kernel Image (uncompressed)
Data Size:    1262504 Bytes = 1232.91 kB = 1.20 MB
Load Address: 0x30008000
Entry Point:  0x30008040
 

2 、下载内核
U-Boot 1.1.3 (Jan 12 2007 - 16:16:36)

U-Boot code: 33F80000 -> 33F9BAC0  BSS: -> 33F9FBAC
RAM Configuration:
Bank #0: 30000000 64 MB
Nor Flash: 512 kB
Nand Flash:  64 MB
In:    serial
Out:   serial
Err:   serial
Hit any key to stop autoboot:  0
sbc2410=>tftp 0x30008000 zImage.img        
TFTP from server 192.168.1.115; our IP address is 192.168.1.128
Filename 'zImage.img'.
Load address: 0x30008000
Loading: #################################################################
        #################################################################
        #################################################################
        ####################################################
done
Bytes transferred = 1263324 (1346dc hex)


3.运行 

sbc2410=>bootm 0x30008000
## Booting image at 30008000 ...
   Image Name:   linux-2.6.14
   Image Type:   ARM Linux Kernel Image (uncompressed)
   Data Size:    1261056 Bytes =  1.2 MB
   Load Address: 30008000
   Entry Point:  30008040
   Verifying Checksum ... OK
   XIP Kernel Image ... OK


内核启动信息省。。。。


三、固化
       
如果你想把镜像文件写入flash,每次开机后让u-boot帮你复制到sdram中,再使用bootm命令引导的话,可以按照这样操作:
sbc2410=>tftp 0x30008000 zImage.img
TFTP from server 192.168.1.115; our IP address is 192.168.1.128
Filename 'zImage.img'.
Load address: 0x30008000
Loading: #################################################################
        #################################################################
        #################################################################
        ####################################################
done
Bytes transferred = 1263324 (1346dc hex)
sbc2410=>nand erase 0x30000 0x1d0000

NAND erase: device 0 offset 196608, size 1900544 ... OK
sbc2410=>nand write 0x30008000 0x30000 0x1d0000

NAND write: device 0 offset 196608, size 1900544 ...  1900544 bytes written: OK

设置u-boot启动命令:
1、针对方法一:
sbc2410=>setenv bootcmd nand read 0x31000000 0x30000 0x1d0000\;bootm 0x31000000
sbc2410=>saveenv
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done
2、针对方法二:
sbc2410=>setenv bootcmd nand read 0x30008000 0x30000 0x1d0000\;bootm 0x30008000
sbc2410=>saveenv
Saving Environment to NAND...
Erasing Nand...Writing to Nand... done

sbc2410=>reset
启动信息略。。。。

 

posted @ 2007-01-12 23:13 lfc 阅读(47695) | 评论 (10)编辑 收藏
     摘要: 几经艰辛,终于基本完成了 u-boot 在 s3c44b0 的移植工作,在些记录一下在移植过程中所碰到的困难和解决方法(一些心得),作为日后参考之用,也希望能够帮到其它有需要的人 ^_^ 。 1. ...  阅读全文
posted @ 2007-01-10 15:41 lfc 阅读(7961) | 评论 (15)编辑 收藏
     摘要: 2.6.14 内核移植说明文档 一、编译内核 1. make distclean 或者 make mrproper 如果你是新下载的内核,那这一步就不用了。但如果你用的是别人移植好的内核,那最好在编译内核之前先清除一下中间文件,因为你们用来编译内核的交叉编译工具可能不同。 2.修改 Makefile 主要是以下两项: 1 ) ARCH = arm 2) CROSS_CO...  阅读全文
posted @ 2007-01-10 15:35 lfc 阅读(19276) | 评论 (17)编辑 收藏

文件系统的制作

前言

  文件系统的制作其实并没有想像中那么难。一个基本的文件系统应该包括: busybox (提供 shell 命令集)、配置文件(用来初始化和布局你的文件系统)、设备文件(如果是用 devfs 的话这个就免了)、必要的库文件系统(如果 busybox 是静态编译的话,那根本不用为 busybox 用到的库文件而烦。在我制作的文件系统里,只是为了用户程序和 qt 的运行才放置了一些库文件)。

 

正文

一、 首先说一下 busybox 的配置和编译问题

其实搞好 busybox 后,可以说你的文件系统已经完成了一半了。 Busybox 之所以比较难编译,主要是 busybox 和交叉编译工具的版本搭配问题。在文坛上不乏因为 busybox 某些命令不能编译通过而烦的人,在这里我推荐一个搭配: busybox-1.1.3+arm-linux-gcc-3.3.2 (在文坛上看到过有人说 busybox-1.0.1+arm-linux-gcc-3.4.1 也可以正常编译通过,你自己看着办吧)。

Busybox 的配置很简单,详细过程可以参考《基于 S3C2410 Linux 全线移植文档》的文件系统部分,我刚开始的时候就是按照这个来做出一个很简单的文件系统的。

 

不过有一点要特别注意的 (shell 的配置问题 )

1、要这样配置:
 
│ │               Shells  --->    
      Choose your default shell (ash)  --->      

2、如果是这样配置的话,虽然可以生成ash,但不能生成sh
 
│ │       Choose your default shell (none)  --->                        │ │
 
│ │   [*] ash  

另外,按照他的这种方法做出来的文件系统,运行的时候 shell 并不好有,没有历史记录、自动补全、删除字符的功能,下面介绍如何为它添加这些功能:

               Shells  --->

---   Bourne Shell Options                                       

   [ ]   Hide message on interactive shell startup                  

   [ ]   Standalone shell                                           

   [*]   command line editing                                       

   [*]     vi-style line editing commands                           

        (15)    history size                                              

   [*]     history saving                                           

   [*]     tab completion                                           

   [*]       username completion                                    

   [ ]     Fancy shell prompts

 

这是我自己试验出来的,网上没有看到过这方面的介绍,在此奉献给大家。

 

二、 再来说一下配置文件的问题

 

在文件系统中,配置文件主要存放在 /etc 目录里面。《基于 S3C2410 Linux 全线移植文档》里面介绍的文件系统由于需要加载文件系统的时候把 /mnt/etc 目录拷贝到 /etc ,所以不得不使用 /linuxrc 脚本,不过如果是这样的话需要在内核传递参数里设置 init=/linuxrc ,因为默认是启动 /sbin/init 初始化脚本的( busybox 编译安装以后生成的 linuxrc 文件是指向 /bin/busybox 的符号文件,应该把它删掉,自己重写脚本)。在我做的文件系统里不采用这种方法,所以不用设置 init=/linuxrc

 

Busybox init 的流程在《构建嵌入式 linux 系统》这本书里面有介绍,我在这简单的说一下:如果不采用 linuxrc 的话就会执行 /sbin/init 脚本( busybox init ),它会去分析 /etc/inittab 脚本(如果没有的话就使用它默认的来代替,一般没必要自己为它编写这个脚本,用它默认的就行),然后会执行 /etc/init.d/rcS 命令(在我制作的文件系统里就把配置都写入了这个文件)。

 

至于 rcS 这个目录的编写主要是安排哪些目录挂载哪些次级文件系统,比如 /proc 要挂载 proc 文件系统、 /sys 要挂载 sysfs /dev/shm 要挂载 tmpfs /tmp 要挂载 ramfs 等等。此外,还可以让内核重新挂载根文件系统也行,具体可以参考 rcS 这个脚本里面的内容,我的是参考友善的那个来写的。另外,可以在这个脚本里执行一些命令,比如设置 ip 地址、建立符号链接(我为 usb 设备的挂载特意建立了 /dev/sda1 的符号链接)、设置主机名等等。 Busybox init 还会调用 /etc/profile 来设置 PATH ,具体请看文件。

 

在《构建嵌入式 linux 系统》提到了怎样建立和建立哪些设备文件,但因为 devfs 这个东西的存在,我们可以不再为这些设备文件而费心了。因为内核在申请设备的同时会向 devfs 申请相应的设备文件,然后 devfs 会帮我们在 /dev 目录建立相应的设备文件,做到内核使用多少设备就建立多少设备文件,不像以前那样要预先建立一大堆可以你不会用到的设备文件(不过从 2.6.12 内核开始,这个 devfs 选项从内核配置中删除,好像是用 udevfs 之类来代替了,不过很多人还是喜欢用回 devfs ,而且按现在看来起码它用得还挺不错的)。

 

好像没什么好讲了,至于 /lib 目录应该放哪些库文件,我也没有底。如果不运行应用程序,只是运行 busybox 的话根本不用放任何的库,因为我们的 busybox 是静态链接的还记得吧?我在自己的文件系统中存放了 helloworld 应用程序和模块,另外还有一个 led 模块,是用 ioctl 来控制 led 灯的亮和灭的,所以我才加载了一些库,而且是从原来友善的文件系统里面拷过来的。以后如果要运行 qt 的话,还要把 qt 用到的库文件也放进去,这样文件系统就变得挺大的了。

 

总结

好了,一个简单的文件系统就是如此简单的就可以做出来。不过要做出一个合理的文件系统的话相信还有很多东西要注意,比如根文件系统各目录应该使用什么次级文件系统、配置文件的设计、选用哪些库文件、如何增加用户管理和网络功能 (boa) 等等。网上关于文件系统制作的介绍很少,不过有个不错的方法就是参考人家文件系统的做法来做,我就是参考友善文件系统的做法来做的。在这里提供一个下载文件系统的好地方,里面有很多的文件系统可以给你参考:
http://husaberg.toby-churchill.com/balloon/releases/v0.7/roots/

好了,总结如此,希望对你有帮助。

 

posted @ 2007-01-10 11:09 lfc 阅读(16986) | 评论 (11)编辑 收藏
仅列出标题
共12页: First 4 5 6 7 8 9 10 11 12