微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > arm linux 启动过程

arm linux 启动过程

时间:11-09 来源:互联网 点击:

  1. ype__arm920_proc_info,#object
  2. __arm920_proc_info:
  3. .long0x41009200
  4. .long0xff00fff0
  5. .longPMD_TYPE_SECT|\
  6. PMD_SECT_BUFFERABLE|\
  7. PMD_SECT_CACHEABLE|\
  8. PMD_BIT4|\
  9. PMD_SECT_AP_WRITE|\
  10. PMD_SECT_AP_READ
  11. .longPMD_TYPE_SECT|\
  12. PMD_BIT4|\
  13. PMD_SECT_AP_WRITE|\
  14. PMD_SECT_AP_READ
  15. /*__arm920_setup函数在stext的未尾被调用,请往回看。*/
  16. b__arm920_setup
  17. .longcpu_arch_name
  18. .longcpu_elf_name
  19. .longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB
  20. .longcpu_arm920_name
  21. .longarm920_processor_functions
  22. .longv4wbi_tlb_fns
  23. .longv4wb_user_fns
  24. #ifndefCONFIG_CPU_DCACHE_WRITETHROUGH
  25. .longarm920_cache_fns
  26. #else
  27. .longv4wt_cache_fns
  28. #endif
  29. .size__arm920_proc_info,.-__arm920_proc_info

[cpp]view plaincopyprint?

  1. /*
  2. *ReadprocessorIDregister(CP#15,CR0),andlookupinthelinker-built
  3. *supportedprocessorlist.Notethatwecantusetheabsoluteaddresses
  4. *forthe__proc_infolistssincewearentrunningwiththeMMUon
  5. *(andtherefore,wearenotinthecorrectaddressspace).Wehaveto
  6. *calculatetheoffset.
  7. *
  8. *r9=cpuid
  9. *Returns:
  10. *r3,r4,r6corrupted
  11. *r5=proc_infopointerinphysicaladdressspace
  12. *r9=cpuid(preserved)
  13. */
  14. __lookup_processor_type:
  15. /*adr是相对寻址,它的寻计算结果是将当前PC值加上3f符号与PC的偏移量,
  16. *而PC是物理地址,因此r3的结果也是3f符号的物理地址*/
  17. adrr3,3f
  18. /*r5值为__proc_info_bein,r6值为__proc_ino_end,而r7值为.,
  19. *也即3f符号的链接地址。请注意,在链接期间,__proc_info_begin和
  20. *__proc_info_end以及.均是链接地址,也即虚执地址。
  21. */
  22. ldmdar3,{r5-r7}
  23. /*r3为3f的物理地址,而r7为3f的虚拟地址。结果是r3为虚拟地址与物理地址的差值,即PHYS_OFFSET-PAGE_OFFSET。*/
  24. subr3,r3,r7@getoffsetbetweenvirt&phys
  25. /*r5为__proc_info_begin的物理地址,即r5指针__proc_info数组的首地址*/
  26. addr5,r5,r3@convertvirtaddressesto
  27. /*r6为__proc_info_end的物理地址*/
  28. addr6,r6,r3@physicaladdressspace
  29. /*读取r5指向的__proc_info数组元素的CPUID和mask值*/
  30. 1:ldmiar5,{r3,r4}@value,mask
  31. /*将当前CPUID和mask相与,并与数组元素中的CPUID比较是否相同
  32. *若相同,则找到当前CPU的__proc_info定义,r5指向访元素并返回。
  33. */
  34. andr4,r4,r9@maskwantedbits
  35. teqr3,r4
  36. beq2f
  37. /*r5指向下一个__proc_info元素*/
  38. addr5,r5,#PROC_INFO_SZ@sizeof(proc_info_list)
  39. /*是否遍历完所有__proc_info元素*/
  40. cmpr5,r6
  41. blo1b
  42. /*找不到则返回NULL*/
  43. movr5,#0@unknownprocessor
  44. 2:movpc,lr
  45. ENDPROC(__lookup_processor_type)
  46. .long__proc_info_begin
  47. .long__proc_info_end
  48. 3:.long.
  49. .long__arch_info_begin
  50. .long__arch_info_end

4 __lookup_machine_type 函数

__lookup_machine_type 和__lookup_processor_type像对孪生兄弟,它们的行为都是很类似的:__lookup_machine_type根据r1寄存器的机器编号到.arch.info.init段的数组中依次查找机器编号与r1相同的记录。它使了与它孪生兄弟同样的手法进行虚拟地址到物理地址的转换计算。

在介绍函数,我们先分析tqs3c2440开发板的机器信息的定义:

[cpp]view plaincopyprint?

  1. Arch/arm/include/asm/mach/arch.h
  2. #defineMACHINE_START(_type,_name)\
  3. staticconststructmachine_desc__mach_desc_##_type\
  4. __used\
  5. __attribute__((__section__(".arch.info.init")))={\
  6. .nr=MACH_TYPE_##_type,\
  7. .name=_name,
  8. #defineMACHINE_END\
  9. };

MACHINE_START宏用于定义一个.arch.info.init段的数组元素。.nr元素就是函数要比较的变量。Tqs3c2440开发板相应的定义如下:

[cpp]view plaincopyprint?

  1. MACHINE_START(S3C2440,"TQ2440")
  2. .phys_io=S3C2410_PA_UART,
  3. .io_pg_offst=(((u32)S3C24XX_VA_UART)>>18)&0xfffc,
  4. .boot_params=S3C2410_SDRAM_PA+0x100,
  5. .init_irq=s3c24xx_init_irq,
  6. .map_io=tq2440_map_io,
  7. .init_machine=tq2440_machine_init,
  8. .timer=&s3c24xx_timer,
  9. MACHINE_END

这是一个struct machine_desc结构,在后面的C代码(start_kernel开始执行的代码)会使用该变量对象。在tqs3c2440开发中的__lookup_machine_type函数就是返回该对象指针。

这里涉及很多函数指针,它们都是在start_kernel函数里在各种阶段进行初始化的回函数。如map_io指向的tq2440_map_io就是在建立好内核页表后,再调用它来针对开发板的各种IO端口来建立相关的映射和页表。

至于__loopup_machine_type的代码就不作详细分析,请对比__lookup_processor_type来自行分析。代码如下:

Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top