【C语言常识】Keil MDK的分散加载文件.sct

xiaoxiao2021-02-27  379

出处:http://blog.csdn.net/tracing/article/details/9720157

面对这样一个新东西,先去官网看看,或者看看IDE的帮助,基本上你想要的东西都有了,

BAIDU来的都不全面,这是一种学习方法。

    http://www.keil.com/support/man/docs/armlink/armlink_BABDDHBF.htm

    这个链接是我在官网上找到的关于分散加载文件的资料。讲的比较详细了。这里通过一

个例子记录下我学习的过程,通过分散加载文件把代码从flash里拷贝到ram里运行, 基于LPC1788。

    先贴下我的sct文件:

[cpp] view plain copy LR_IROM1 0x00000000 0x00002000     {        ER_IROM1 0x00000000 0x00020000         {           *.o (RESET, +First)           *(InRoot$$Sections)           startup_lpc177x_8x.o (+RO)           system_LPC177x_8x.o (+RO)       }              RW_IRAM1 0x20000000 0x00004000         {           .ANY (+RW +ZI)       }   }      LR_IROM2 0x00002000 0x0007E000   {       VECTOR 0x10000000 EMPTY 0xE4       {       }              ER_IRAM1 +0       {           .ANY (+RO)       }   }  

这里有两个加载域(load region)LR_IROM1和LR_IROM2,LR_IROM1是初始化程序,拷贝代码等,

从ROM的地址0开始,LR_ROM2是应用程序,从ROM的0x2000开始。+RO表示只读,代码或者只

读数据,一般用来表示代码,+RW表示可读可写的数据,+ZI表示初始化为0的数据。大括号里面的

为运行域(execution region),一个加载域可以包含几个运行域,LR_ROM2里面有两个运行域,

VECTOR和ER_IRAM1,我用VECTOR来表示中断向量区域,ER_IRAM1来表示应用程序区,+0表示

紧接着VECTOR排放,EMPTY表示空的,这里空出0xE4的大小,用来放中断向量,.ANY表示除了

上面用到的代码之外的代码,官网上有专门解释.ANY的一节。

    下面用一张图来表示这个程序的加载域和执行域:

 

其实加载域的empty这块区域是不用空出来的,主要是运行域要空出来,用来拷贝中断向量,看个人喜好了,

我觉得空出来方便引用这块区域的执行域地址。

    这样框架就比较清楚了,拷贝的程序清单如下:

[cpp] view plain copy extern unsigned char Image VECTOR Base;   extern unsigned char Image VECTOR Length;      extern unsigned char Load ERIRAM1 Base;   extern unsigned char Image ERIRAM1 Base;   extern unsigned char Image ERIRAM1 Length;      void CopyCode2Ram ()   {       unsigned char *pSrc, *pDes;       unsigned int count;              SCB->VTOR = 0x10000000;              pSrc = 0;       pDes = (unsigned char*)&Image VECTOR Base;       count = 0xE4;              while (count--)       {           *pDes++ = *pSrc++;       }                     count = (unsigned int)&Image ERIRAM1 Length;       pDes = (unsigned char*)&Image ERIRAM1 Base;       pSrc = (unsigned char*)(&Load ERIRAM1 Base + 0xE4);              while (count--)       {           *pDes++ = *pSrc++;       }   }   其中拷贝中断向量的时候要指定中断向量的偏移地址。Load ERIRAM1 Base表示执行域ER_IRAM1的加载地址;Image ERIRAM1 Base表示执行域ER_IRAM1的执行地址;Image ERIRAM1 Length表示执行域ER_IRAM1的实际长度,VECTOR区域因为是EMPTY,所以实际长度是0, 而中断向量的长度是固定的,所以程序里就写了个常数。

出处:http://blog.163.com/yaochen_good/blog/static/5673636320131523020888/

分散加载能够将加载和运行时存储器中的代码和数据描述在被称为分散加载描述文

件的一个文本描述文件中,以供连接时使用。 (1)分散加载区 分散加载区域分为两类: ? 加载区,包含应用程序复位和加载时的代码和数据。 ? 执行区,包含应用程序执行时的代码和数据。应用程序启动过程中,从每个加载区可创

建一个或多个执行区。 映象中所有的代码和数据准确地分为一个加载区和一个执行区。 (2)分散加载文件示例 ROM_LOAD 0x0000 0x4000 {     ROM_EXEC 0x0000 0x4000; Root region     {         * (+RO); All code and constant data     }     RAM 0x10000 0x8000     {         * (+RW, +ZI); All non-constant data     } }

 

(3)分散加载文件语法 load_region_name  start_address | "+"offset  [attributes] [max_size] {     execution_region_name  start_address | "+"offset  [attributes][max_size]     {         module_select_pattern  ["("                                     ("+" input_section_attr | input_section_pattern)                                     ([","] "+" input_section_attr | "," input_section_pattern)) *                                ")"]     } }  load_region:       加载区,用来保存永久性数据(程序和只读变量)的区域; execution_region:  执行区,程序执行时,从加载区域将数据复制到相应执行区后才能被正确执行; load_region_name:  加载区域名,用于“Linker”区别不同的加载区域,最多31个字符; start_address:     起始地址,指示区域的首地址; +offset:           前一个加载区域尾地址+offset 做为当前的起始地址,且“offset”应为“0”或“4”的倍数; attributes:        区域属性,可设置如下属性:                     PI       与地址无关方式存放;                     RELOC    重新部署,保留定位信息,以便重新定位该段到新的执行区;                     OVERLAY  覆盖,允许多个可执行区域在同一个地址,ADS不支持;                     ABSOLUTE 绝对地址(默认); max_size:          该区域的大小;  execution_region_name:执行区域名; start_address:     该执行区的首地址,必须字对齐; +offset:           同上; attributes:        同上;                     PI          与地址无关,该区域的代码可任意移动后执行;                     OVERLAY     覆盖;                     ABSOLUTE    绝对地址(默认);                     FIXED       固定地址;                     UNINIT      不用初始化该区域的ZI段; module_select_pattern: 目标文件滤波器,支持通配符“*”和“?”;                         *.o匹配所有目标,* (或“.ANY”)匹配所有目标文件和库。 input_section_attr:    每个input_section_attr必须跟随在“+”后;且大小写不敏感;                         RO-CODE 或 CODE                         RO-DATA 或 CONST                         RO或TEXT, selects both RO-CODE and RO-DATA                         RW-DATA                         RW-CODE                         RW 或 DATA, selects both RW-CODE and RW-DATA                         ZI 或 BSS                         ENTRY, that is a section containing an ENTRY point.                         FIRST,用于指定存放在一个执行区域的第一个或最后一个区域;                         LAST,同上; input_section_pattern: 段名;  汇编中指定段:      AREA    vectors, CODE, READONLY C中指定段: #pragma arm section [sort_type[[=]"name"]] [,sort_type="name"]* sort_type:      code、rwdata、rodata、zidata                 如果“sort_type”指定了但没有指定“name”,那么之前的修改的段名将被恢复成默认值。 #pragma arm section     // 恢复所有段名为默认设置。 应用:     #pragma arm section rwdata = "SRAM",zidata = "SRAM"         static OS_STK  SecondTaskStk[256];              // “rwdata”“zidata”将定位在“sram”段中。     #pragma arm section                                 // 恢复默认设置 (4)程序中对区域地址引用的方法 Load$$region_name$$Base             Load address of the region. Image$$region_name$$Base            Execution address of the region. Image$$region_name$$Length          Execution region length in bytes (multiple of 4). Image$$region_name$$Limit           Address of the byte beyond the end of the execution region.  Image$$region_name$$ZI$$Base        Execution address of the ZI output section in this region. Image$$region_name$$ZI$$Length      Length of the ZI output section in bytes (multiple of 4). Image$$region_name$$ZI$$Limit       Address of the byte beyond the end of the ZI output sectionin the execution region.  SectionName$$Base                   Input Address of the start of the consolidated section called SectionName. SectionName$$Limit                  Input Address of the byte beyond the end of the consolidated section called SectionName.  Load:          加载区,即存放地址; Image:         执行区,即运行地址; Base:          区首地址; Limit:         区尾地址; Length:        区长度; region_name:   RO、RW、ZI、load_region_name、execution_region_name;  例如:     “RAM1”区域的首地址:      Image$$RAM1$$Base     上例中“sram”段首地址:    sram$$Base  汇编引用示例:   IMPORT |Load$$Exec_RAM1$$Base|              // Exec_RAM1 为“RW”段   IMPORT |Image$$Exec_RAM1$$Base|   IMPORT |Image$$Exec_RAM1$$Length|   IMPORT |Image$$Exec_RAM1$$Limit|    LDR  R0, =|Load$$Exec_RAM1$$Base|   LDR  R1, =|Image$$Exec_RAM1$$Base|   LDR  R2, =|Image$$Exec_RAM1$$Limit| 0   CMP  R1,   R2   LDRCC R3,   [R0], #4   STRCC R3,   [R1], #4   BCC 

转载请注明原文地址: https://www.6miu.com/read-4558.html

最新回复(0)