下载
加入VIP
  • 专属下载券
  • 上传内容扩展
  • 资料优先审核
  • 免费资料无限下载

上传资料

关闭

关闭

关闭

封号提示

内容

首页 Uboot中start.S源码的指令级的详尽解析

Uboot中start.S源码的指令级的详尽解析.pdf

Uboot中start.S源码的指令级的详尽解析

159*****195@sina.cn
2011-11-14 0人阅读 举报 0 0 0 暂无简介

简介:本文档为《Uboot中start.S源码的指令级的详尽解析pdf》,可适用于IT/计算机领域

Uboot中startS源码的指令级的详尽解析Version:Author:greenwaste(at)com目录正文之前本文内容本文目标代码来源关于本文内容的组织形式阅读此文所要具有的前提知识声明startS详解设置CPU模式关闭看门狗关闭中断设置堆栈sp指针清除bss段异常中断处理相关知识点详解uboot初始化中为何要设置CPU为SVC模式而不是设置为其他模式什么是watchdog为何在要系统初始化的时候关闭watchdog什么是watchdog为何在要系统初始化的时候关闭watchdog为何ARM中PC=PC为何ARM和ARM一样也是PC=PCAMR寄存器的别名APCSARM中的寄存器的别名什么是APCS为何C语言(的函数调用)需要堆栈而汇编语言却不需要堆栈保存现场上下文什么叫做上下文context传递参数举例分析C语言函数调用是如何使用堆栈的关于为何不直接用mov指令而非要用adr伪指令mov指令的操作数的取值范围到底是多少引用图表图表global的语法图表LDR指令的语法图表word的语法图表balignl的语法图表CPSRSPSR的位域结构图表pWTCON图表INTMOD图表INTMSK图表INTSUBMSK图表CLKDIVN图表WTCON寄存器的位域图表INTMSK寄存器的位域图表INTSUBMSK寄存器的位域图表CLKDIVN的位域图表控制寄存器的位域含义图表时钟模式图表关于访问控制位在域访问控制寄存器中的含义图表关于访问允许(AP)位的含义图表macro的语法图表LDMSTM的语法图表条件码的含义图表ARM中CPU的模式图表AMR三级流水线图表ARM三级流水线状态图表ARM三级流水线示例图表ARM三级流水线vsARM五级流水线图表ARM三级流水线到ARM五级流水线的映射图表ARM的五级流水线示例图表ARM五级流水线的执行机构的细节图表ARM寄存器的别名图表数据处理指令的指令格式图表mov指令xea的位域含义解析版本历史:版本时间内容详细解释了uboot的starts中的每行代码添加了相关知识点的详细解释正文之前本文内容此文主要内容就是分析startS这个汇编文件的内容即ARM上电后的最开始那一段的启动过程。本文目标本文的目标是希望看完此文的读者可以达到:微观上对此startS的每一行都有了基本的了解。宏观上对基于ARM核的SCX的CPU的启动过程有更加清楚的概念。这样的目的是为了读者看完本文后再去看其他类似的启动相关的源码能明白需要做什么事情然后再看别的系统是如何实现相关的内容的达到一定程度的触类旁通。总体说就是要做哪些为何要这么做如何实现的即英语中常说的:dowhatwhydohowdo此三方面都清楚理解了那么也才能算真正懂了。代码来源所用代码来自TQ官网天嵌的bbs上下载下来的uboot中的源码:ubootoptEmbedSkyubootcpuarmtstartS下载地址为:年月最新TQ光盘下载(Linux内核WinCE的ebootuboot均有更新)http:bbsembedskynetviewthreadphptid=关于本文内容的组织形式类似于这样的代码框:StartS的代码。。。中的内容是源文件startS的汇编代码紧接着代码框的内容是代码的解释。在┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳和┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻之间的代码是转自别的地方非startS的代码。阅读此文所要具有的前提知识阅读此文之前你至少要对TQ的板子有个基本的了解以及要了解开发板初始化的大概要做的事情比如设置输入频率设置堆栈等等。另外至少要有一定的C语言的基础这样更利于理解汇编代码。声明由于水平有限难免有误欢迎指正:greenwaste(at)com欢迎转载但请注明作者。startS详解下面将详细解释uboot中的startS中的每一行代码。详细到每个指令的语法和含义都进行详细讲解使得此文读者可以真正搞懂具体的含义即what。以及对于一些相关的问题深入探究为何要这么做即why。对于uboot的startS主要做的事情就是系统的各个方面的初始化。从大的方面分可以分成这几个部分:()设置CPU模式()关闭看门狗()关闭中断()设置堆栈sp指针()清除bss段()异常中断处理下面来对startS进行详细分析看看每一个部分是如何实现的。设置CPU模式**armbootStartupCodeforARMCPUcore**Copyright(c)MariusGr鰃er<magsysgode>*Copyright(c)AlexZ黳ke<azusysgode>*Copyright(c)GaryJennejohn<gjdenxde>**SeefileCREDITSforlistofpeoplewhocontributedtothis*project**Thisprogramisfreesoftwareyoucanredistributeitandor*modifyitunderthetermsoftheGNUGeneralPublicLicenseas*publishedbytheFreeSoftwareFoundationeitherversionof*theLicense,or(atyouroption)anylaterversion**Thisprogramisdistributedinthehopethatitwillbeuseful,*butWITHOUTANYWARRANTYwithouteventheimpliedwarrantyof*MERCHANTABILITYorFITNESSFORAPARTICULARPURPOSESeethe*GNUGeneralPublicLicenseformoredetails**YoushouldhavereceivedacopyoftheGNUGeneralPublicLicense*alongwiththisprogramifnot,writetotheFreeSoftware*Foundation,Inc,TemplePlace,Suite,Boston,*MAUSA*#include<configh>#include<versionh>****************************************************************************Jumpvectortableasintablein***************************************************************************globlstartglobl是个关键字对应含义为:http:reejectgbadevorgfilesGasARMRefpdf―图表global的语法DirectiveDescriptionSyntaxExampleglobalMakessymbolvisibletothelinkerglobalsymbolglobalMyAsmFuncgloblSameasglobalgloblsymbolgloblMyOtherAsmFunc―所以意思很简单就是相当于C语言中的Extern声明此变量并且告诉链接器此变量是全局的外部可以访问所以你可以看到:ubootoptEmbedSkyubootboardEmbedSkyubootlds中有用到此变量:ENTRY(start)即指定入口为start,而由下面的start的含义可以得知start就是整个startS的最开始即整个uboot的代码的开始。start:bresetstart后面加上一个冒号‘:‘表示其是一个标号Label类似于C语言goto后面的标号。而同时start的值也就是这个代码的位置了此处即为代码的最开始相对的的位置。而此处最开始的相对的位置在程序开始运行的时候如果是从NorFlash启动那么其地址是stat=如果是重新relocate代码之后就是我们定义的值了即在ubootoptEmbedSkyubootboardEmbedSkyconfigmk中的:TEXTBASE=xD表示是代码段的基地址即start=TEXTBASE=xD关于标号的语法解释:http:sourcewareorgbinutilsdocsasLabelshtml#Labels―Alabeliswrittenasasymbolimmediatelyfollowedbyacolon`:'Thesymbolthenrepresentsthecurrentvalueoftheactivelocationcounter,andis,forexample,asuitableinstructionoperandYouarewarnedifyouusethesamesymboltorepresenttwodifferentlocations:thefirstdefinitionoverridesanyotherdefinitions‖而start标号后面的:breset就是跳转到对应的标号为reset的位置。ldrpc,undefinedinstructionldrpc,softwareinterruptldrpc,prefetchabortldrpc,dataabortldrpc,notusedldrpc,irqldrpc,fiqldr命令的语法为:http:infocenterarmcomhelptopiccomarmdocduihcDUIHCrvctlinkerandutilitiesguidepdf图表LDR指令的语法http:wenkubaiducomviewfccbeebeahtml“LDR指令的格式为:LDR{条件}目的寄存器<存储器地址>LDR指令用于从存储器中将一个位的字数据传送到目的寄存器中。该指令通常用于从存储器中读取位的字数据到通用寄存器然后对数据进行处理。当程序计数器PC作为目的寄存器时指令从存储器中读取的字数据被当作目的地址从而可以实现程序流程的跳转。该指令在程序设计中比较常用且寻址方式灵活多样请读者认真掌握。指令示例:LDRRR将存储器地址为R的字数据读入寄存器R。LDRRRR将存储器地址为RR的字数据读入寄存器R。LDRRR#将存储器地址为R的字数据读入寄存器R。LDRRRR!将存储器地址为RR的字数据读入寄存器R,并将新地址R+R写入R。LDRRR#!将存储器地址为R的字数据读入寄存器R并将新地址R+写入R。LDRRRR将存储器地址为R的字数据读入寄存器R并将新地址R+R写入R。LDRRRRLSL#!将存储器地址为R+R×的字数据读入寄存器R并将新地址R+R×写入R。LDRRRRLSL#将存储器地址为R的字数据读入寄存器R并将新地址R+R×写入R。”http:wwwpczpgcomahtml“ARM是RISC结构数据从内存到CPU之间的移动只能通过LS指令来完成也就是ldrstr指令。比如想把数据从内存中某处读取到寄存器中只能使用ldr比如:ldrr,x就是把x这个地址中的值存放到r中。”上面那些ldr的作用以第一个undefinedinstruction为例就是将地址为undefinedinstruction中的一个word的值赋值给pc。undefinedinstruction:wordundefinedinstructionsoftwareinterrupt:wordsoftwareinterruptprefetchabort:wordprefetchabortdataabort:worddataabortnotused:wordnotusedirq:wordirqfiq:wordfiqhttp:blogoldchinaunixnetushowarthtml―wordwordexpr{,expr}…分配一段字内存单元并用expr初始化字内存单元(bit)‖http:reejectgbadevorgfilesGasARMRefpdf图表word的语法DirectiveDescriptionSyntaxExamplewordDefinewordexpr(bitnumbers)wordexpr{,…}word,x所以上面的含义以undefinedinstruction为例就是此处分配了一个word=bit=字节的地址空间里面存放的值是undefinedinstruction。而此处undefinedinstruction也就是该地址空间的地址了。用C语言来表达就是:undefinedinstruction=undefinedinstruction或*undefinedinstruction=undefinedinstruction在后面的代码我们可以看到undefinedinstruction也是一个标号即一个地址值对应着就是在发生“未定义指令”的时候系统所要去执行的代码。(其他几个对应的“软件中断”“预取指错误”“数据错误”“未定义”“(普通)中断”“快速中断”也是同样的做法跳转到对应的位置执行对应的代码。)所以:ldrpc,标号。。。标号:word标号标号:。。。(具体要执行的代码)的意思就是将地址为标号中内容载入到pc而地址为标号中的内容正好装的是标号。用C语言表达其实很简单:PC=*(标号)=标号对PC赋值即是实现代码跳转所以整个这段汇编代码的意思就是:跳转到标号的位置执行对应的代码。balignl,xdeadbeefbalignl这个标号的语法及含义:http:reejectgbadevorgfilesGasARMRefpdf“图表balignl的语法DirectiveDescriptionSyntaxExamplebalignlWordalignthefollowingcodetoalignmentbyteboundary(default=)Fillskippedwordswithfill(default=orNOP)Ifthenumberofbytesskippedisgreaterthanmax,thendon'talign(default=alignment)balignl{alignment}{,fill}{,max}balignl”所以意思就是接下来的代码都要字节对齐不足之处用xdeadbeef填充。其中xdeadbeef其实没啥特别意思就是要填充的内容你把其换成其他的也行当然最好也和xdeadbeef一样是个字节。****************************************************************************StartupCode(resetvector)**doimportantinitonlyifwedon'tstartfrommemory!*relocatearmboottoram*setupstack*jumptosecondstage***************************************************************************TEXTBASE:wordTEXTBASE此处和上面的类似TEXTBASE是一个标号地址此地址中是一个word类型的变量变量名是TEXTBASE,此值见名知意是text的base即代码的基地址可以在ubootoptEmbedSkyubootboardEmbedSkyconfigmk中找到其定义:TEXTBASE=xDgloblarmbootstartarmbootstart:wordstart同理此含义可用C语言表示为:*(armbootstart)=start**Thesearedefinedintheboardspecificlinkerscript*globlbssstartbssstart:wordbssstartgloblbssendbssend:wordend关于bssstart和bssend都只是两个标号对应着此处的地址。而两个地址里面分别存放的值是bssstart和end,这两个的值根据注释所说是定义在开发板相关的链接脚本里面的我们此处的开发板相关的链接脚本是:ubootoptEmbedSkyubootboardEmbedSkyubootlds其中可以找到bssstart和end的定义:bssstart=bss:{*(bss)}end=而关于bssstart和bssend定义为glogl即全局变量是因为uboot的其他源码中要用到这两个变量详情请自己去搜索源码。globlFREERAMENDFREERAMEND:wordxbadcdegloblFREERAMSIZEFREERAMSIZE:wordxbadcde关于FREERAMEND和FREERAMSIZE这里只是两个标号之所以也是声明为全局变量是因为uboot的源码中会用到这两个变量。但是这里有点特别的是这两个变量将在本源码startS中的后面要用到而在后面用到这两个变量之前uboot的C源码中会先去修改这两个值具体的逻辑是:本文件startS中后面有这两句:ldrpc,startarmbootstartarmboot:wordstartarmboot意思很明显就是去调用startarmboot函数。而startarmboot函数是在:ubootoptEmbedSkyubootlibarmboardc中:┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳initfnct*initsequence={cpuinit,*basiccpudependentsetup*。。。,}voidstartarmboot(void){initfnct**initfncptr。。。for(initfncptr=initsequence*initfncptrinitfncptr){if((*initfncptr)()!=){hang()}}。。。}┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻即在startarmboot去调用了cpuinit。cpuinit函数是在:ubootoptEmbedSkyubootcpuarmtcpuc中:cpuinit源码┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳┳intcpuinit(void){**setupupstacksifnecessary*#ifdefCONFIGUSEIRQIRQSTACKSTART=armbootstartCFGMALLOCLENCFGGBLDATASIZEFIQSTACKSTART=IRQSTACKSTARTCONFIGSTACKSIZEIRQFREERAMEND=FIQSTACKSTARTCONFIGSTACKSIZEFIQCONFIGSTACKSIZEFREERAMSIZE=FREERAMENDPHYSSDRAM#elseFREERAMEND=armbootstartCFGMALLOCLENCFGGBLDATASIZECONFIGSTACKSIZEFREERAMSIZE=FREERAMENDPHYSSDRAM#endifreturn}┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻┻在cpuinit中根据我们的一些定义比如堆栈大小等等去修改了IRQSTACKSTARTFIQSTACKSTARTFREERAMEND和FREERAMSIZE的值。至于为何这么修改后面遇到的时候会具体再解释。#ifdefCONFIGUSEIRQ*IRQstackmemory(calculatedatruntime)*globlIRQSTACKSTARTIRQSTACKSTART:wordxbadcde*IRQstackmemory(calculatedatruntime)*globlFIQSTACKSTARTFIQSTACKSTART:wordxbadcde#endif同上IRQSTACKSTART和FIQSTACKSTART也是在cpuinit中用到了。不过此处是只有当定义了宏CONFIGUSEIRQ的时候才用到这两个变量其含义也很明显只有用到了中断IRQ才会用到中断的堆栈才有中端堆栈的起始地址。快速中断FIQ同理。**theactualresetcode*reset:**setthecputoSVCmode*mrsr,cpsrCPSR:CPSR是当前的程序状态寄存器(CurrentProgramStatusRegister)而SPSR是保存的程序状态寄存器(SavedProgramStatusRegister)。具体细节为:ARM体系结构http:wwwdocincomphtml或http:wwwcsienctuedutw~wjtsaiEmbeddedSystemDesignChbootloaderpdf图表CPSRSPSR的位域结构或:NZCVIFMMMMMUser模式FIQ模式IRQ模式SVC模式User模式FIQ模式IRQ模式SVC模式ABT模式UND模式MRS:MRSMoveFromStatusRegisterMRS指令的语法为:“四、程序状态寄存器访问指令、MRS指令MRS指令的格式为:MRS{条件}通用寄存器程序状态寄存器(CPSR或SPSR)MRS指令用于将程序状态寄存器的内容传送到通用寄存器中。该指令一般用在以下两种情况:Ⅰ当需要改变程序状态寄存器的内容时可用MRS将程序状态寄存器的内容读入通用寄存器修改后再写回程序状态寄存器。Ⅱ当在异常处理或进程切换时需要保存程序状态寄存器的值可先用该指令读出程序状态寄存器的值然后保存。指令示例:MRSRCPSR传送CPSR的内容到RMRSRSPSR传送SPSR的内容到R”所以上述汇编代码含义为将CPSR的值赋给R寄存器。bicr,r,#xfbic指令的语法是:“、BIC指令BIC指令的格式为:BIC{条件}{S}目的寄存器操作数操作数BIC指令用于清除操作数的某些位并把结果放置到目的寄存器中。操作数应是一个寄存器操作数可以是一个寄存器被移位的寄存器或一个立即数。操作数为位的掩码如果在掩码中设置了某一位则清除这一位。未设置的掩码位保持不变。”

用户评价(0)

关闭

新课改视野下建构高中语文教学实验成果报告(32KB)

抱歉,积分不足下载失败,请稍后再试!

提示

试读已结束,如需要继续阅读或者下载,敬请购买!

评分:

/15

VIP

在线
客服

免费
邮箱

爱问共享资料服务号

扫描关注领取更多福利