stm32uclinuxstartkernel之前的汇编代码分析.docx
- 文档编号:12811639
- 上传时间:2023-04-22
- 格式:DOCX
- 页数:15
- 大小:23.80KB
stm32uclinuxstartkernel之前的汇编代码分析.docx
《stm32uclinuxstartkernel之前的汇编代码分析.docx》由会员分享,可在线阅读,更多相关《stm32uclinuxstartkernel之前的汇编代码分析.docx(15页珍藏版)》请在冰豆网上搜索。
stm32uclinuxstartkernel之前的汇编代码分析
Boot中执行下面两句话之后,进入uclinux内核。
theKernel=(void(*)(int,int,unsignedint))((uint32_t)0x08003001);
theKernel(0,2189,((uint32_t)0x20000100));
1start_kernel之前的汇编代码分析
首先来到0x08003000处,此时携带有三个参数,R0、R1、R2,分别是0,2189,0x20000100.
0x08003000对应着下面stext的汇编代码。
代码阅读说明:
@后面的内容标示是注释语句
ARM或者THUMB指令的选取,在\include\asm-arm\unified.h中,定义了使用ARM,THUMB为空
偏移量#PROC_INFO_SZ等,在\include\asm\asm-offset.h中宏定义
1.1head-mommu.S
文件在arch\arm\kernel\head-nommu.S,text.head段,有stext、__after_proc_init两段组成,内核从这里开始启动,然后通过各种调用,最终进入C语言的start_kernel函数,这段代码执行流程如下:
(1)调用__lookup_processor_type,传入R9(CPU基址寄存器的值),成功后获得当前的proc_info结构体信息,地址放入R10;
(2)调用__lookup_machine_type,BootLoader传给内核的R1值,成功后获得当前的machine_desc结构体信息,地址放入R8;
(3)执行__v7m_setup,进行必要的初始化;
(4)执行__switch_data,并最终跳转到C语言的start_kernel函数。
.section".text.head","ax"
ENTRY(stext)
cpsidi@disableinterrupts//cortex-M3特殊指令,关闭所有中断
ldrr9,=0xe000ed00@CPUIDregisteraddress
ldrr9,[r9]//CPUID基址寄存器,参考手册(周立功)-P80
bl__lookup_processor_type@r5=procinfor9=cupid//head-common.S
movsr10,r5@invalidprocessor(r5=0)?
beq__error_p@yes,error'p'
bl__lookup_machine_type@r5=machinfo
movsr8,r5@invalidmachine(r5=0)?
beq__error_a@yes,error'a'
badrlr,__after_proc_init@return(PIC)address//提前暂存lr的值
ARM(addpc,r10,#PROCINFO_INITFUNC)//R10处偏移16个字节,然后赋给PC
//相当于跳转到下面的__v7m_setup
ENDPROC(stext)
__after_proc_init:
ldrpc,__switch_data//将PC指针赋值到__switch_data标号地址处,实际执行的
ENDPROC(__after_proc_init)//是在__mmap_switched这个标号处
.ltorg
#include"head-common.S"//末尾包含下面的文件
1.2head-common.S
文件在arch\arm\kernel\head-common.S,有__switch_data、__mmap_switched、__error_p、__error_a、__error、__lookup_processor_type、C语言的lookup_processor_type、__lookup_machine_type、C语言的lookup_machine_type、__vet_atags等组成,这里只列出上面调用要使用的查找处理器类型和查找机器类型。
_lookup_processor_type:
//r9是刚从CPU基址寄存器中取出的值
ARM(adrr3,3f)//执行此句后,r3的地址是后面标号3处的地址
ARM(ldmdar3,{r5-r7})//r5,r6,r7依次变为,__proc_info_begin,end,以及
//标号3处的末尾链接地址
subr3,r3,r7@getoffsetbetweenvirt&phys//这三行执行虚实地址转换
addr5,r5,r3@convertvirtaddressesto//r5是proc_info_list结构体地址
addr6,r6,r3@physicaladdressspace//__proc_info_end的自己
1:
ldmiar5,{r3,r4}@value,mask//r3是结构体的val变量
andr4,r4,r9@maskwantedbits//r4是结构体的mask变量
teqr3,r4
beq2f//相等转到后面的2标号处
addr5,r5,#PROC_INFO_SZ@sizeof(proc_info_list)//宏定义在asm-offset.h
cmpr5,r6//结构体可能是个数组,需要全部查找,若r5的地址没有超出end
blo1b//的地址,则继续转到1处理,若最后没找到,r5变为空
movr5,#0@unknownprocessor
2:
movpc,lr
ENDPROC(__lookup_processor_type)
ENTRY(lookup_processor_type)
stmfdsp!
{r4-r7,r9,lr}
movr9,r0//提供C语言的API结构,r0是传入的参数
bl__lookup_processor_type
movr0,r5//此处的R0是函数的返回值,即传出的参数
ldmfdsp!
{r4-r7,r9,pc}
ENDPROC(lookup_processor_type)
.long__proc_info_begin//arch/arm/kernel/vmlinux.lds.s中定义
.long__proc_info_end
3:
.long.
.long__arch_info_begin
.long__arch_info_end
/*
*Lookupmachinearchitectureinthelinker-buildlistofarchitectures.
*Notethatwecan'tusetheabsoluteaddressesforthe__arch_info
*listssincewearen'trunningwiththeMMUon(andtherefore,weare
*notinthecorrectaddressspace).Wehavetocalculatetheoffset.
*
*r1=machinearchitecturenumber
*Returns:
*r3,r4,r6corrupted
*r5=mach_infopointerinphysicaladdressspace
*/
__lookup_machine_type:
adrr3,3b
ldmiar3,{r4,r5,r6}//r5是__arch_info_begin,r6是end
subr3,r3,r4@getoffsetbetweenvirt&phys//虚实地址转换
addr5,r5,r3@convertvirtaddressesto
addr6,r6,r3@physicaladdressspace
1:
ldrr3,[r5,#MACHINFO_TYPE]@getmachinetype//结构体偏移字节数,见上面的注释
teqr3,r1@matchesloadernumber?
//与传递给内核的r1相同
beq2f@found//r3就是结构体中第一个变量nr
addr5,r5,#SIZEOF_MACHINE_DESC@nextmachine_desc
cmpr5,r6
blo1b
movr5,#0@unknownmachine
2:
movpc,lr
ENDPROC(__lookup_machine_type)
/*
*ThisprovidesaC-APIversionoftheabovefunction.
*/
ENTRY(lookup_machine_type)
stmfdsp!
{r4-r6,lr}
movr1,r0//提供C语言的API结构,r0是传入的参数
bl__lookup_machine_type
movr0,r5//此处的R0是函数的返回值,即传出的参数
ldmfdsp!
{r4-r6,pc}
ENDPROC(lookup_machine_type)
1.2.1lookup_processor_type
(1)vmlinux.lds.s
文件在arch\arm\kernel\vmlinux.lds.s
__proc_info_begin=.;//include/asm-arm/procinfo.h中定义
*(.proc.info.init)
__proc_info_end=.;
__arch_info_begin=.;//include/asm-arm/mach/arch.h 中定义
*(.arch.info.init)
__arch_info_end=.;
(2)procinfo.h
文件在include/asm-arm/procinfo.h
structproc_info_list{//pro-v7m.S对其实例化
unsignedintcpu_val;
unsignedintcpu_mask;
unsignedlong__cpu_mm_mmu_flags;/*usedbyhead.S*/
unsignedlong__cpu_io_mmu_flags;/*usedbyhead.S*/
unsignedlong__cpu_flush;/*usedbyhead.S*/
constchar*arch_name;
constchar*elf_name;
unsignedintelf_hwcap;
constchar*cpu_name;
structprocessor*proc;
structcpu_tlb_fns*tlb;
structcpu_user_fns*user;
structcpu_cache_fns*cache;
};
(3)pro-v7m.S
文件在arch\arm\mm\pro-v7m.S,内容很多,核心就是.section".proc.info.init",其它的都是它这个结构体中得成员,如__v7m_setup、cpu_arch_name、cpu_elf_name、cpu_v7m_name、v7m_processor_functions等。
cpu_v7m_name:
.ascii"ARMv7-MProcessor"
.align
.section".text.init",#alloc,#execinstr
.typev7m_processor_functions,#object
ENTRY(v7m_processor_functions)
.wordv7m_early_abort
.wordcpu_v7m_proc_init
.wordcpu_v7m_proc_fin
.wordcpu_v7m_reset
.wordcpu_v7m_do_idle
.wordcpu_v7m_dcache_clean_area
.wordcpu_v7m_switch_mm
.wordcpu_v7m_set_pte_ext
.wordpabort_noifar
.sizev7m_processor_functions,.-v7m_processor_functions
.typecpu_arch_name,#object
cpu_arch_name:
.asciz"armv7m"
.sizecpu_arch_name,.-cpu_arch_name
.typecpu_elf_name,#object
cpu_elf_name:
.asciz"v7m"
.sizecpu_elf_name,.-cpu_elf_name
.align
.section".proc.info.init",#alloc,#execinstr
/*
*MatchanyARMv7-Mprocessorcore.
*/
.type__v7m_proc_info,#object
__v7m_proc_info:
//E000ED00是CPUID基址寄存器,其中[19:
16]读作常量F
.long0x000f0000@RequiredIDvalue
.long0x000f0000@MaskforID
.long0@proc_info_list.__cpu_mm_mmu_flags
.long0@proc_info_list.__cpu_io_mmu_flags
b__v7m_setup@proc_info_list.__cpu_flush
.longcpu_arch_name
.longcpu_elf_name
.longHWCAP_SWP|HWCAP_HALF|HWCAP_THUMB|HWCAP_FAST_MULT|HWCAP_EDSP
.longcpu_v7m_name
.longv7m_processor_functions@proc_info_list.proc
.long0@proc_info_list.tlb
.long0@proc_info_list.user
.long0@proc_info_list.cache
.size__v7m_proc_info,.-__v7m_proc_info
1.2.2lookup_machine_type
(1)arch.h
文件在include/asm-arm/mach/arch.h
structmachine_desc{//在stm3210e_eval.c中实例化
/*
*Note!
Thefirstfourelementsareused
*byassemblercodeinhead.S,head-common.S
*/
unsignedintnr;/*architecturenumber*/
unsignedintphys_io;/*startofphysicalio*/
unsignedintio_pg_offst;/*byteoffsetforio
*pagetabeentry*/
constchar*name;/*architecturename*/
unsignedlongboot_params;/*taggedlist*/
unsignedintvideo_start;/*startofvideoRAM*/
unsignedintvideo_end;/*endofvideoRAM*/
unsignedintreserve_lp0:
1;/*neverhaslp0*/
unsignedintreserve_lp1:
1;/*neverhaslp1*/
unsignedintreserve_lp2:
1;/*neverhaslp2*/
unsignedintsoft_reboot:
1;/*softreboot*/
void(*fixup)(structmachine_desc*,
structtag*,char**,
structmeminfo*);
void(*map_io)(void);/*IOmappingfunction*/
void(*init_irq)(void);
structsys_timer*timer;/*systemticktimer*/
void(*init_machine)(void);
};
/*
*Setofmacrostodefinearchitecturefeatures.Thisisbuiltinto
*atablebythelinker.
*/
#defineMACHINE_START(_type,_name)\
staticconststructmachine_desc__mach_desc_##_type\
__used\
__attribute__((__section__(".arch.info.init")))={\
.nr=MACH_TYPE_##_type,\
.name=_name,
#defineMACHINE_END\
};
(2)stm3210e_eval.c
文件在arch\arm\mach-stm3210e_eval\stm3210e_eval.c
MACHINE_START(STM3210E_EVAL,"STM3210E-EVAL")
/*Maintainer:
MCDApplicationTEAM*//*Status*/
.fixup=stm3210e_eval_fixup,//OK
.boot_params=CONFIG_EXTERNAL_RAM_BASE+0x100,//OK
.init_irq=nvic_init_irq,//OK
.timer=&stm3210e_eval_timer,//OK
.init_machine=stm3210e_eval_init,//OK
MACHINE_END
(3)match-type.h
文件在include/asm-arm/mach-type.h
#defineMACH_TYPE_STM3210E_EVAL2189
1.3__v7m_setup
文件在arch\arm\mm\pro-v7m.S
/*
*__v7m_setup
*
*InitialiseTLB,Caches,andMMUstatereadytoswitchtheMMU
*on.Returninr0thenewCP15C1controlregistersetting.
*
*WeautomaticallydetectifwehaveaHarvardcache,andusethe
*Harvardcachecontrolinstructionsinseadoftheunifiedcache
*controlinstructions.
*
*ThisshouldbeabletocoverallARMv7-Mcores.
*
*Itisassumedthat:
*-cachetyperegisterisimplemented
*/
__v7m_setup:
@Configurethevectortablebaseaddress//配置中断向量偏移
ldrr0,=0xe000ed08@vectortablebaseaddress
ldrr12,=vector_table
strr12,[r0]
@LowerthepriorityoftheSVCandPendSVexceptions
ldrr0,=0xe000ed1c//设置SVC、PendSV的中断优先级都为128
movr5,#0x80000000
strr5,[r0]@setSVCpriority
ldrr0,=0xe000ed20
movr5,#0x00800000
strr5,[r0]@setPendSVpriority
@SVCtorunthekernelinthismode
badrr0,1f
ldrr5,[r12,#11*4]@readtheSVCvectorentry
strr0,[r12,#11*4]@writethetemporarySVCvectorentry
movr6,lr@saveLR
movr7,sp@saveSP
#if!
defined(CONFIG_XIP_KERNEL)
ldrsp,=__v7m_setup_stack_top
#endif
cpsiei
svc#0//呼叫系统服务,权威指南-P182,暂时没找到?
1:
cpsidi
strr5,[r12,#11*4]@restoretheoriginalSVCvectorentry
movlr,r6@restoreLR
m
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- stm32uclinuxstartkernel 之前 汇编 代码 分析
![提示](https://static.bdocx.com/images/bang_tan.gif)