uclinux初始化--------(1)

第零个文件 arch/armnommu/Makefile
在这个文件中定义了你编译好的内核的入口的地址和MACHINE类型,一般是通过条件编译
TEXTADDR     = 0x10008000   这个值完全是根据你的cpu和内存状况确定的
MACHINE      = your_processor

指定连接文件
LINKFLAGS :=-p -X -T arch/armnommu/vmlinux.lds

替换vmlinux-$(PROCESSOR).lds.in中的TEXTADDR,生成实际需要的连接脚本
arch/armnommu/vmlinux.lds: arch/armnommu/vmlinux-$(PROCESSOR).lds.in dummy
ifeq ($(CONFIG_ARCH_DSC21),y)
 @sed 's/TEXTADDR/$(TEXTADDR)/' <$< >tmp.ld
 @sed 's/DATAADDR/$(DATAADDR)/' <tmp.ld >$@
 $(RM) tmp.ld
else
 @sed 's/TEXTADDR/$(TEXTADDR)/' <$< >$@ 
endif

一般连接脚本的前面几句是这样的
ENTRY(stext)---------指定入口
SECTIONS
{
 . = $(TEXTADDR);-----设定入口的绝对地址


第一个文件linux/arch/armnommu/kernel/head-armv.S

#define K(a,b,c) ((a) << 24 | (b) << 12 | (c))


#ifndef CONFIG_UCLINUX
设置符号swapper_pg_dir的地址
  .globl SYMBOL_NAME(swapper_pg_dir)
  .equ SYMBOL_NAME(swapper_pg_dir), TEXTADDR - 0x4000 
定义了一个宏,该宏可以获得swapper_pg_dir的地址
  .macro pgtbl, reg, rambase
  adr /reg, stext
  sub /reg, /reg, #0x4000
  .endm

/*
 * Since the page table is closely related to the kernel start address, we
 * can convert the page table base address to the base address of the section
 * containing both.
 */
  .macro krnladr, rd, pgtable, rambase
  bic /rd, /pgtable, #0x000ff000
  .endm
#endif

/*
 *  Kernel startup entry point.
 *
 * The rules are:
 *  r0      - should be 0
 *  r1      - unique architecture number
 *  MMU     - off
 *  I-cache - on or off
 *  D-cache - off
 *
 * See linux/arch/arm/tools/mach-types for the complete list of numbers
 * for r1.
 */
.section ".text.init",#alloc,#execinstr
  .type stext, #function 
  
  请注意,这里是入口点,而且此时r1中应该保存唯一的一个architecture number
ENTRY(stext)

保存r0寄存器的值?????
  mov r12, r0
 
 靠~~Rebel.COM  NetWinder是什么东东,这个条件编译可以不予理会
 #if defined(CONFIG_ARCH_NETWINDER)
。。。。。
#endif


#if defined(CONFIG_ARCH_L7200)
  mov r1, #MACH_TYPE_L7200
#elif defined(CONFIG_ARCH_INTEGRATOR)
  mov r1, #MACH_TYPE_INTEGRATOR
#elif defined(CONFIG_ARCH_P52)
  mov r1, #MACH_TYPE_P52
#elif defined(CONFIG_ARCH_SWARM)
  mov r1, #MACH_TYPE_SWARM
#elif defined(CONFIG_ARCH_SAMSUNG)
  mov r1, #MACH_TYPE_SAMSUNG
#endif
前面预定义了部分的ARCH,如果匹配的上,R1中包含了architecture number

其实系统复位之后,ARM就处于SVC 模式,而且禁止了FIQ IRQ, 的确如注视所说--make sure
  mov r0, #F_BIT | I_BIT | MODE_SVC @ make sure svc mode
  msr cpsr_c, r0   @ and all irqs disabled

使用的是atmel的arm处理器吗???跳过去吧
#if defined(CONFIG_ARCH_ATMEL)
。。。。。
#endif
又来,使用的是samsumg的arm处理器吗???跳过去吧
#if defined(CONFIG_ARCH_SAMSUNG)
。。。。。
#endif

重点还是分析通用的arm处理器的内容吧
  bl __lookup_processor_type ----寻找处理器类型,R10中保存指向表示处理器类型结构的指针
  teq r10, #0    @ invalid processor?  ----R10 == 0????靠,发生错误
  moveq r0, #'p'   @ yes, error 'p'
  beq __error
  
  bl __lookup_architecture_type----寻找体系结构类型, R7中保存指向表示体系结构类型结构的指针
  teq r7, #0    @ invalid architecture?----好像不用说什么了吧
  moveq r0, #'a'   @ yes, error 'a'
  beq __error
  
跳过,我们一般是会定义CONFIG_UCLINUX这个宏的
__create_page_tables函数建立一个初始化阶段的页表,映射4M内存,当然足够了
#ifndef CONFIG_UCLINUX
  bl __create_page_tables
#endif
  adr lr, __ret   @ return address
看看你的proc_info_list结构,第三个成员变量是一个跳转指令,进行一些CPU初始化的操作
返回则跳到__ret
  add pc, r10, #12   @ initialise processor
       @ (return control reg)

__switch_data: .long __mmap_switched
  .long SYMBOL_NAME(compat)
  .long SYMBOL_NAME(__bss_start)
  .long SYMBOL_NAME(_end)
  .long SYMBOL_NAME(processor_id)
  .long SYMBOL_NAME(__machine_arch_type)
  .long SYMBOL_NAME(cr_alignment)
  .long SYMBOL_NAME(init_task_union)+8192

__ret:  ldr lr, __switch_data
执行__switch_data
  mov pc, lr

  /*
   * This code follows on after the page
   * table switch and jump above.
   *
   * r0  = processor control register
   * r1  = machine ID
   * r9  = processor ID
   */
  .align 5
在这个函数中,主要作用是清bss,设置sp到(init_task_union)+8192,
给compat  processor_id  __machine_arch_type  __machine_arch_type  cr_alignment  赋值,
后来,在setup_processor和setup_architecture中需要用到这些变量。
__mmap_switched:
  adr r3, __switch_data + 4
  ldmia r3, {r2, r4, r5, r6, r7, r8, sp}@ r2 = compat
                             @ sp = stack pointer
  str r12, [r2]

  mov fp, #0    @ Clear BSS (and zero fp)
1:  cmp r4, r5
  strcc fp, [r4],#4
  bcc 1b

  str r9, [r6]   @ Save processor ID
  str r1, [r7]   @ Save machine type
#ifdef CONFIG_ALIGNMENT_TRAP
  orr r0, r0, #2   @ ...........A.
#endif
  bic r2, r0, #2   @ Clear 'A' bit
  stmia r8, {r0, r2}   @ Save control register values
  b SYMBOL_NAME(start_kernel)   进入start_kernel



/*
 * Exception handling.  Something went wrong and we can't
 * proceed.  We ought to tell the user, but since we
 * don't have any guarantee that we're even running on
 * the right architecture, we do virtually nothing.
 * r0 = ascii error character:
 * a = invalid architecture
 * p = invalid processor
 * i = invalid calling convention
 *
 * Generally, only serious errors cause this.
 */
 对出错的处理,打印消息,进入死循环
__error:
#ifdef CONFIG_DEBUG_LL
  mov r8, r0    @ preserve r0
  adr r0, err_str
  bl printascii
  mov r0, r8
  bl printch
#endif

1:  mov r0, r0
  b 1b

#ifdef CONFIG_DEBUG_LL
err_str: .asciz "/nError: "
  .align
#endif

/*
 * 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:
 * r5, r6, r7 corrupted
 * r8  = page table flags
 * r9  = processor ID
 * r10 = pointer to processor structure
 */
在编译生成的内核影像的.proc.info段中保存了处理器类型的信息
下面的代码是在..proc.info段中寻找proc_info_list结构
__lookup_processor_type:
  adr r5, 2f
  ldmia r5, {r7, r9, r10}
  sub r5, r5, r10   @ convert addresses 调整地址
  add r7, r7, r5   @ to our address space
  add r10, r9, r5

r10-----proc_info_list first addr
r7------proc_info_list end addr
找到合适的proc_info_list,则R10指向了该结构

1:  ldmia r10, {r5, r6, r8}  @ value, mask, mmuflags
  and r6, r6, r9           @ mask wanted bits
  teq r5, r6
  moveq pc, lr-------------找到了适当的proc_info_list返回
  add r10, r10, #36   @ sizeof(proc_info_list) 下一个proc_info_list
  cmp r10, r7                      是否到达结尾
  blt 1b
  mov r10, #0    @ unknown processor
  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.
 */
2:  .long __proc_info_end           .proc.info段的END
  .long __proc_info_begin       .proc.info段的BEGIN
  .long 2b
  .long __arch_info_begin
  .long __arch_info_end

/*
 * 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:
 *  r2, r3, r4 corrupted
 *  r5 = physical start address of RAM
 *  r6 = physical address of IO
 *  r7 = byte offset into page tables for IO
 */
 寻找体系结构的类型
 
__lookup_architecture_type:
  adr r4, 2b
  ldmia r4, {r2, r3, r5, r6, r7} @ throw away r2, r3
  sub r5, r4, r5   @ convert addresses
  add r4, r6, r5   @ to our address space
  add r7, r7, r5
至此我们得到了.arch.info段的起始地址
r4-----__arch_info_begin
r7-----__arch_info_end
1:  ldr r5, [r4]   @ get machine type
  teq r5, r1       -----------architecture number是否匹配
  beq 2f
  add r4, r4, #SIZEOF_MACHINE_DESC
  cmp r4, r7
  blt 1b
  mov r7, #0    @ unknown architecture
  mov pc, lr-------------error 返回

找到了architecture number返回
2:  ldmib r4, {r5, r6, r7}  @ found, get results
  mov r7, r7, lsr #18   @ pagetable byte offset
  mov pc, lr

L_AT91_SF_CIDR: .long 0xfff00000

具体实现寻找体系结构其实和寻找cpu info 是一样的,不过是信息是保存在了.arch.info段
 在文件linux/include/asm-arm/mach/arch.h中定义了如下结构
 struct machine_desc {
 /*
  * Note! The first four 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  virt_io; /* start of virtual io */

 const char  *name;  /* architecture name */
 unsigned int  param_offset; /* parameter page */

 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  */
 const struct tagtable * tagtable; /* tag table  */
 int   tagsize; /* tag table size */
 void   (*fixup)(struct machine_desc *,
      struct param_struct *, char **,
      struct meminfo *);
 void   (*map_io)(void);/* IO mapping function */
 void   (*init_irq)(void);
};

/*
 * Set of macros to define architecture features.  This is built into
 * a table by the linker.
 */
#define MACHINE_START(_type,_name)  /
const struct machine_desc __mach_desc_##_type /
 __attribute__((__section__(".arch.info"))) = { /---------放入.arch.info段
 nr:  MACH_TYPE_##_type, /
 name:  _name,

#define MAINTAINER(n)

#define INITIRQ(_func)    /
 init_irq: _func,

而在linux/arch/arm/mach-***/arch.c文件中定义了你的machine_desc结构
当然我们这里只是定义了machine_desc中的init_irq结构
MACHINE_START(ATMEL, "EB01")
       MAINTAINER("Erwin Authried")
       INITIRQ(genarch_init_irq)
MACHINE_END



第二个文件linux/include/asm-armnommu/procinfo.h

#ifndef __ASM_PROCINFO_H
#define __ASM_PROCINFO_H

#ifndef __ASSEMBLY__

#include <asm/proc-fns.h>

struct proc_info_item {
 const char  *manufacturer;
 const char  *cpu_name;
};


基本上,这是一个定义处理器类型的数据结构,你可以在arch/arm/mm目录下建立关于自己processor的信息,
具体方法是,创建一个proc-myproc.S,当然这个文件修改自proc-arm*.S
struct proc_info_list {
 unsigned int  cpu_val;
 unsigned int  cpu_mask;
 unsigned long  __cpu_mmu_flags; /* used by head-armv.S */
 unsigned long  __cpu_flush;  /* used by head-armv.S */
 const char  *arch_name;
 const char  *elf_name;
 unsigned int  elf_hwcap;
 struct proc_info_item *info;
#ifdef MULTI_CPU
 struct processor *proc;
#else
 void   *unused;
#endif
};

#endif /* __ASSEMBLY__ */

#define HWCAP_SWP  1
#define HWCAP_HALF  2
#define HWCAP_THUMB  4
#define HWCAP_26BIT  8 /* Play it safe */
#define HWCAP_FAST_MULT  16
#define HWCAP_FPA        32
#define HWCAP_VFP        64
#define HWCAP_EDSP  128

#endif


第三个文件 linux/arch/armnommu/mm/proc-***.S
这个文件具体是和你的cpu相关的
在这个文件中定义了你的proc_info_list,
你可以定义若干,让程序根据ID扫描,如果专门应用在特定的CPU上,也可以直接指定proc_info_list
  .align
  .section ".proc.info", #alloc, #execinstr

  .type __arm6_proc_info, #object
__arm6_proc_info:
  .long 0x41560600
  .long 0xfffffff0
  .long 0x00000c1e
  b __arm6_setup
  .long cpu_arch_name
  .long cpu_elf_name
  .long HWCAP_SWP | HWCAP_26BIT
  .long cpu_arm6_info
  .long arm6_processor_functions
  .size __arm6_proc_info, . - __arm6_proc_info
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值