时间:2024-09-14 12:38 / 来源:未知
瓦特wbf网址下载但是在系统复位时又被存储器控制器映射到0x0000地址处应用散开加载,能够将用户界说的构造体或代码定位到指定物理地点上的外设,这种外设能够是守时器、实不时钟、静态SRAM或者是两个收拾器间用于数据和指令通讯的双端口存储器等。正在步伐中不必直接拜访相应外设,只需拜访相应的内存变量即可竣工对指定外设的操作,由于相应的内存变量定位正在指定的外设上。如许,对外设的拜访看不到相应的指针操作,对构造体成员的拜访即可竣工对外设相应存储单位的拜访,让步伐员感思到似乎没有外设,惟有内存。
比如,一个带有两个32位寄存器的守时器外设,正在编造中的物理地点为Ox04000000,其C言语构造描绘如下:
要应用散开加载将上述构造体定位到Ox04000000的物理地点,能够将上述构造体放正在一个文献名为timer_regs.c中,并正在散开加载文献中指定即可,如下:
属性UNINIT是避免正在使用步伐启动时对该实行段的ZI数据段初始化为零。
正在步伐联贯后,通过Image map文献可查看该ZI数据段的存储器分拨处境:
散开加载机造正在供给将指定代码和数据定位正在指定物理地点的才气的同时,也供给了一种代码瓜分机造能够将指定的零初始化段(ZI段)从可实行代码中诀别出来。如许最终身成的烧入ROM或Flash中的镜像文献就不包含谁人人瓜分了的零初始化段,假使该零初始化段再大,也不影响最终身成的镜像文献的巨细。但不采用散开加载机造,零初始化段正在编译联贯后是直接天生到镜像文献中的。它的巨细直接影响最终要烧写的文献的巨细,且零初始化段的巨细还取决于内存的巨细,它不行大到横跨内存的巨细;而采用散开加载机造,能够将某个零初始化段定位到非内存地点的一个存储器外设上,如NVRAM(非易失性随机存储器)。
笔者曾正在一个本质工程中采用这种散开加载机造,将一个2MB的构造体数组定位到外部NVRAM中,用于纪录筑立正在任责经过中采撷到的数据;而正在本编造中,ARM收拾器的内存惟有256 KB,Flash存储器也惟有2 MB。借使不采用散开加载,步伐根基无法运转,也不行烧写到Flash中。
采用散开加载,把对繁杂外设的拜访形成对构造体数组的拜访,使步伐代码精简捷懂。对步伐员来说,对构造体数组的操作依旧和内存变量的操作相同的。
3. 某些特地使用,必要将代码段或者数据段的个人安顿正在指定身分,利便更新,或者其他加密等出处。
4. 某些特地使用,必要固定函数地点的时期,能够将谁人函数放于固定的区域,而不管其他步伐有误变动。
5. 看待步伐中的少许设备型的变量,或者必要荟萃安顿正在一个区域,利便下次直接更新那块存储空间。
下面着重描绘散开描绘符的写法,散开描绘文献的类型为 .scf 。写完后,能够通过ADS实行加载。
正在本质的嵌入式编造中,ADS供给的缺省存储器映照是不行餍足恳求的。用户的目的硬件日常有众个存储器筑立位于差别的身分,而且这些存储器筑立正在步伐装载和运转时或者再有差别的设备。
Scattertoading能够通过一个文本文献来指定一段代码或数据正在加载和运转时正在存储器中的差别身分。这个文本文献scatterfile正在号召行中由-scatter开合指定,比如:
正在scatterfile中能够为每一个代码或数据区正在装载和实行时指定差别的存储区域地点,Scatlertoading的存储区块能够分成二品种型:
实行区:编造启动后,使用步伐实行实行和数据拜访的存储器区域,编造正在及时运转时能够有一个或众个实行块。
映像中全部的代码和数据都有一个装载地点和运转地点(二者或者相通也或者差别,视的确处境而定)。正在编造启动时,C函数库中的__main初始化代码会实行须要的复造及清零操作,使使用步伐的相应代码和数据段从装载形态转入实行形态。
每个块由一个头题目动手界说,头中起码包括块的名字和肇端地点,此外再有最大长度和其他少许属性选项。块界说的实质包含正在紧接的一对花括号内,依赖于的确的编造处境。
一个实行块务必起码含有一个代码或数据段;这些日常来自源文献或库函数等的目的文献;通配符号*能够配合指定属性项中全部没有正在文献中界说的余下个人。
图8所示样例中,惟有一个加载块,包括了全部的代码和数据,肇端地点为0。这个加载块一共对应两个实行块。一个包括全部的RO代码和数据,实行地点与装载地点相通;同时另一个肇端地点为0x10000的实行块,包括全部的RW和ZI数据。如许当编造动手启动时,从第一个实行块动手运转(实行地点等于装载地点),正在实行经过中,有一段初始化代码会把装载块中的一个人代码搬动到此外的实行块中。
正在大大都使用中,并不是像前例那样,容易地把全部属性都放正在一道,用户必要职掌特定代码和数据段的安顿身分。这能够通过正在scatter文献中对单个目的文献实行界说竣工,而不是只容易地依托通配符。
为了笼盖规范的联贯器组织原则,咱们能够应用+FIRST和+LAST散开加载指令。规范的例子是正在实行块的动手处安顿断绝向量外格:
根区是一个实行块,它的加载地点与实行地点是相似的。每个scatter文献起码有一个根区。散开加载有一个限定:创筑实行块的代码和数据(即竣工复造和清零的代码和数据)无法自行复造到另一个身分。因而,正在根区中务必含有下面的个人:
因为上面两个个人的属性是只读的,因而他们被*〈+RO〉通配符语法配合。借使*〈+RO〉被用正在了非根区中,则正在根区中务必显式地指明另一个RO区域。
Scatterloading机造供给了一种指定代码和静态数据组织的措施。下面先容奈何安顿使用步伐的货仓和heap。
使用步伐的货仓和heap是正在C库函数初始化经过中成立起来的。能够通过重定向对应的子步伐来转化货仓和heap的身分,正在ADS的库函数中,即_user_initial_stackheap()函数。
当用户应用散开装载效力的时期,务必重挪用_user_initial_stackheap(),不然联贯器会报错:
ADS供给了两种及时存储器模子。缺省时为one-region,使用步伐的货仓和heap位于统一个存储器区块,应用的时期相向滋长,当正在heap区别配一块存储器空间时必要查验
货仓指针。另一种处境是货仓和heap应用两块独立的存储器区域。看待速率额外速的RAM,可采取只用来作货仓应用。为了应用这种two-region模子,用户必要导入符号use_two_region_memory,heap应用必要查验heap的长度限定值。对这两种模子来说,缺省处境下对货仓的滋长都不实行查验。用户能够正在步伐编译时应用 -apcs/swst 编译器选项来实行软件货仓查验。借使应用two-region模子,务必得正在实行_user_initial_stackheap时指定一个货仓限定值。
目前处境,平常假设步伐从C库函数的初始化入口_main动手实行。本质上,全部的
嵌入式步伐正在启动时都要实行少许编造级的初始化操作。正在此商量这方面的实质。初始化经过
图10中显示了一个基于ARM的嵌入式编造的基础初始化经过。能够看到,正在_main之前参加了一个复位收拾模块reset handler,它正在编造上电复位时立地启动。标识为$sub$$main的新代码块正在进入主步伐之前实行。
复位收拾模块reset handler日常是一小段汇编代码,正在编造复位时实行。它起码竣工使用步伐中应用到的全部收拾器形式的货仓初始化职责。看待含有当地存储器编造的内核(譬喻含cache的ARM内核),设备职责也务必正在这一段初始化经过中竣工。当竣工编造初始化之后,日常步伐会跳向_main,动手C库函数的初始化经过。
编造初始化经过平常还包含此外少许实质,断绝使能等,这些大众摆设正在C库函数的初始化竣工之后实行。$sub$$main()竣工这个人效力。
全部的ARM编造都有一张断绝向量外当显现特殊必要收拾时,务必挪用向量外。向量外平常要位于0地点处。
当编造启动的时期,为了担保0地点处有无误的启动代码生活,必要非易失性的存储器。
一种容易的措施,便是把编造0x0000动手的一块地点分拨给ROM。其差错是,因为ROM的拜访速率比RAM慢良众,当实行断绝反映必要从断绝向量外跳转时,会给编造功能带来失掉;同时,正在ROM中的向量外实质也不行被用户步伐动态编削。
此外一种可行的计划如图11所示。ROM位于地点0x1000动手的地方,然则正在编造复位时又被存储器职掌器映照到0x0000地点处。如许当编造启动之后,正在地点0x0000看到的是ROM,编造实行这块ROM中的启动代码,启动代码跳转到真正的ROM的地点,并让存储器职掌器移除对ROM的地点映照。这时0x0000地点处的存储器又收复回了RAM。__main中的代码把向量外copy到0x0000处的RAM中去,使得特殊时能被无误反映。
外1为ARM汇编中实行ROM/RAM重定向和映照的一个例子。它以ARM公司的Integrator平台为根基的,该措施实用于近似ROM/RAM重定向措施的全部平台。第一条指令竣工从ROM的映照地点(0x00000)到可靠地点的跳转。地点标号instruct_2是ROM的线)。然后通过筑设Integrator平台上的相应职掌寄存器,移除ROM的地点映照。代码正在系团结启动就被实行。所相合于地点重定向/映照的操作务必正在C库函数初始化之前竣工。
很众ARM收拾器都有片上存储器编造,如cache和精细耦合存储器(TCM)、存储器统造单位(MMU)或存储器袒护单位(MPU)。这些筑立都要正在编造初始化经过中无误设备,而且有少许特地的恳求必要切磋。
由前文可知,_main中的C库函数初始化代码掌握步伐运转时的存储器编造筑设。因而,全盘存储器编造自身务必得正在__main之前竣工初始化职责,如MMU或MPU务必正在reset handler内中竣工设备。
精细耦合存储器(TCM)的初始化同样须正在_main之前竣工(日常正在MMU/MPU之前),由于平常步伐都必要把代码和数据散开装入TCM。必要留意的是当TCM被使能后,不再拜访被TCM障蔽的存储器。
合于cache的相似性题目,借使cache正在_main之前使能的话,那么当_main内中实行从装载区到实行区的代码和数据拷贝时(由于正在拷贝经过中指令和数据正在素质上都是被算作数据收拾),指令会出目前数据缓冲区。避免此题目的措施是正在C库函数初始化竣工后再使能cache。
无论是通过ROM/RAM重定向依旧MMU设备的措施,借使编造正在启动和运转时存储器漫衍纷歧致,scatterloading文献中的界说就要遵从编造重定向后的存储器漫衍处境实行。
装载区LOAD_ROM被安顿正在0x10000处,代外了重定向之儿女码和数据的装载地点。
正在外2中,货仓位于stack_base标识的地点中。这个符号能够是存储器编造中的一个直接地点,也能够正在此外的汇编文献中界说,由scatter文献来界说分拨地点。外2代码为FIQ和IRQ形式各分拨了一个256字节的货仓,用户能够用同样的措施为其他形式也分拨货仓。最容易的措施便是进入相应的形式,然后为SP寄存器指定相应的值。借使思应用软件货仓查验,还务必指定一个货仓长度限定值。
平常来说,应当把全部的编造初始化代码与主使用步伐分脱离来,然则有几个不同,譬喻cache和断绝的使能,必要正在C库函数初始化之后实行。
很众正在启动经过中应用到的效力,如MMU/MPU的设备、断绝的使能等,只可正在特权级形式下实行。借使必要正在特权极形式下运转本身的使用步伐,只消正在退出初始化经过之前转化到相应的形式就行了,没有其他任何题目。
借使应用user形式,务必担保全部只可正在特权形式下实行的效力竣工之后,才智进入user形式。由于system形式和user形式应用相通的寄存器组,reset handler应当从system形式退出,_user_initial_stackheap正在system形式下竣工使用步伐货仓的初始化。如许正在收拾器进入user形式后,全部的货仓空间都曾经被无误筑设好了。
固然能够正在一个scatter文献中描绘代码和数据的分流传局,然则目的硬件中的外设寄存器,货仓和heap设备已经直接采用硬件地点正在步伐源代码中实行筑设。借使把全部存储器地点干系的音讯都正在scatter文献中实行界说,避免正在源文献中援用绝对硬件地点,对步伐的工程化统造是有大好处的。
日常外设寄存器的地点正在步伐文献或头文献中界说,也能够声明一个构造类型指向外设寄存器,构造的地点定位正在scatter文献中竣工。
举例来说,目的守时器上有2个32位的寄存器,能够用外4来映照这些寄存器。为了把构造安顿正在指定的存储器地点上面,创筑一个新的实行区(睹外5)。scatter文献便把timer_regs构造定位正在了地点0x40000000。
留意,正在启动经过当中这些寄存器的实质不必要清零,转化寄存器的实质或者影响编造形态。正在实行区上加UNINIT属性能够提防ZI数据正在初始化经过中被清零。
正在很众处境下,用scatter文献来界说货仓和heap的地点会带来少许好处,重要有:全部的存储器分拨音讯荟萃正在一个文献里;转化货仓和heap的地点只消从头联贯就行了,不必要从头编译。
正在ADS1.2境况下,这是最容易的措施。正在前文中援用过2个符号stack_base和heap_base,这2个符号正在汇编模块中创筑,正在scatter文献中各自的实行区里定位(睹外6)。
外7文献中,heap基地点定位正在0x20000上,货仓基地点位于0x40000。目前heap和货仓的身分就能够相当利便地实行编辑了。
这种措施必要正在目的文献中指定好heap和货仓的长度。这正在肯定水平上削弱了本节起源描绘的两个益处。
最初正在汇编源步伐中界说heap和货仓的长度。合节词SPACE用来保存一块存储器空间,NOINT则能够造止清零操作(睹外8)。留意正在这里的源文献中并不必要地点标号。
然后这些个人就能够正在scatter文献中对应的实行区里定位了(睹外9)。联贯器发作的符号指向每一个实行区的基地点和长度限定,这些符号能够被_user_initial_stackheap挪用的重定向代码应用。正在代码中应用DCD来给这些值界说更有心义的名字,能够巩固代码的可读性(睹外10)。
文献把heap基地点定位正在0x15000,货仓地点定位正在0x4000。Heap和货仓的身分能够通过编辑对应实行区的地点利便地转化。
散开加载描绘文献供ARM-ADS链接器应用,用来决心各个代码段和数据段的存储身分,下面为一个增添说明后的.scf文献例子: