ARM分散加载

在ARM开发当中,希望某些代码或者数据,在编译时放置在指定位置。

关键词:scf(scatter file分散加载文件) _attribute_属性  makefile编译 map文件 bin文件

1. 分散加载文件:

bin文件的加载方式:

code区+RO(read only data)+RW&ZI(已初始化的变量和未初始化的变量)

执行方式:

code区+RO区:如果flash片上可执行,则可直接在该nor flash则可直接在该nor flash上直接执行。否则则要拷贝至RAM当中执行。

RW&ZI区,拷贝至RAM的执行域进行执行。

通过分散加载文件去指定加载域或者执行域的地址。

(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|

CMP  R1,   R2

LDRCC R3,   [R0], #4

STRCC R3,   [R1], #4

BCC  %b0

C 引用:

extern unsigned char Load$$Exec_RAM1$$Base;

extern unsigned char Image$$Exec_RAM1$$Base;

extern unsigned char Image$$Exec_RAM1$$Length;

void MoveRO(void)

{

unsigned char * psrc, *pdst;

unsigned int  count;

count = (unsigned int)   &Image$$Exec_RAM1$$Length;

psrc  = (unsigned char *)&Load$$Exec_RAM1$$Base;

pdst  = (unsigned char *)&Image$$Exec_RAM1$$Base;

while (count--)

{

*pdst++ = *psrc++;

}

}

二.分散加载应用

前面提到过,从NAND Flash启动,对于S3C2410而言,由于片内具有4K的称作"SteppingStone"的SRAM,NAND FLASH的最低4K代码可以自动复制到"SteppingStone",因此可以将初始化等代码放在NAND FLASH的低4K区域内,其他的代码放置在4K以外,在初始化代码内将这些代码复制到外部SDRAM,从而这些代码可以在外部SDRAM内运行。

1.应用实例描述

先完成初始化操作,并且在初始化代码中将NAND FLASH的4K范围以外的代码(简单起见,这部分代码可以操作LED灯)复制到外部SDRAM中。主要目的是使用分散加载文件以及将NAND FLASH中的数据代码复制到SDRAM中。

2.分散加载文件

NAND_FLASH_LOAD 0x0 0x1000

{

RAM_EXEC +0 0x1000

{

;参见前面的加载文件语法

}

}

NAND_FLASH_LOAD2 0x1000

{

SDRAM_EXEC 0x30000000

{

;参见前面的加载文件语法

}

}

(1)将一些初始化代码放在第一个加载区(根区:加载地址和执行地址相同的区域,每一个分散加载描述文件必须至少要有一个根区。),地址范围为:0x0000~0x0fff的4K,其执行区的地址范围也是0x0000~0x0fff的4K,这正好是NAND FLASH启动时自动复制的地址范围。

(2)其他代码放在第2个加载区,从地址0x1000开始,由于这一部分不能自动复制,因此在初始化代码中应该将这一部分复制到外部SDRAM中,其执行区的起始地址为外部SRDAM的地址。

3. 二进制文件烧录

由于有2个加载区,因此生成的二进制文件有2个,文件名对应于相应的执行区名,分别是RAM_EXEC和SDRAM_EXEC,需要注意的是,应该将存放初始化代码的加载区对应的二进制文件RAM_EXEC烧录NAND FLASH的低4K区域,第二个加载区对应的二进制文件SDRAM_EXEC烧录到4K以后的区域。这个可以通过修改Samsuang的sjf烧录程序实现,原来的烧录程序是按BLOCK(16K)烧录,可以修改为按4K的Section烧录,即将1个Block分为4个Section(4K)。主要修改k9s1208.c中的K9S1208_Program函数,需要注意的是,由于NAND FLASH写入前应该擦除,擦除是按Block擦除,由于现在是按Section写,因此应该注意只有在第1次写某一块中的Section前进行擦除,以后再写着一块的其它Section前不能再进行擦除。

这样RAM_EXEC烧录到0 SECTION,SDRAM_EXEC烧录到1 SECTION开始的以后的区域中,完成后复位即可。

部分内容转载至CSDN。

在编译时,仅通过分散加载文件指定了load_region_name和exec_region_name的地址,以及通过在C语言当中指定段,下载后,发现编译器会自动优化。

依据:

查看map地址,确定地址。查看bin文件。

下载完成后,将下载后的BIN文件拷贝出来,发现该地址处无指定的数据。

修改makefile的链接属性

http://gcc.gnu.org/onlinedocs/gcc-4.3.2//gcc/Function-Attributes.html

unused
This attribute, attached to a function, means that the function is meant to be possibly unused. GCC will not produce a warning for this function. 
used

This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.

时间: 2024-10-08 00:54:29

ARM分散加载的相关文章

Keil sct分散加载文件

首先介绍几个概念: 1.ARM映像文件 ARM映像文件是一个层次性结构的文件,其中包含了域(region).输出段(output section)和输入段(input section).各部分关系如下: 一个映像文件由一个或多个域组成 每个域包含一个或多个输出段 每个输出段包含一个或多个输入段 各输入段包含了目标文件中的代码和数据 输入段中包含了4类内容:代码.已经初始化的数据.未经初始化的存储区域.内容初始化成0的存储区域.每个输入段有相应的属性,可以为只读的(RO).可读写的(RW)以及初始

liteos分散加载(十四)

1. 概述 1.1 基本概念 分散加载是一种实现特定代码快速启动的技术,通过优先加载特定代码到内存,达到缩短从系统开机到特定代码执行的时间.可被应用来实现关键业务的快速启动. 嵌入式系统通过uboot加载flash上的镜像文件到内存并执行,而镜像文件本身可能较大,由于flash读取速度的限制,将镜像全部加载完再执行可能无法满足时间敏感的业务对启动速度的要求. 分散加载的思想是先加载部分镜像并执行,这部分镜像包含了时间敏感的关键业务,从而达到快速启动关键业务的效果. Huawei LiteOS的分

ubuntu arm妙算加载cp210x驱动

在妙算TK1上安装ros后,插上usb串口竟然没有驱动 无奈装 从http://www.silabs.com/products/mcu/pages/usbtouartbridgevcpdrivers.aspx#Linux下载 cp210x的驱动 编译生成cp210x.ko insmod cp210x.ko,就可以看到ttyUSB0了. 另外我们还需要ubuntu上电自动加载驱动模块 步骤如下 1. depmod -a 2. 在/etc/modules加入cp210x 3. 拷贝cp210x.ko

关于 ARM Cortex-M3 的启动文件分析及分散加载

原文 https://blog.strongwong.top/posts/%E5%85%B3%E4%BA%8E-ARM-Cortex-M3-%E7%9A%84%E5%90%AF%E5%8A%A8%E6%96%87%E4%BB%B6%E5%88%86%E6%9E%90%E5%8F%8A%E5%88%86%E6%95%A3%E5%8A%A0%E8%BD%BD.html 原文地址:https://www.cnblogs.com/dreamblog/p/11404104.html

Android系统定制——Download Android System 及加载system镜像文件

定制android系统(配置及相关系统的镜像文件),具体可参考:Driver_All_in_One_V1.0--MT6735_6753.pdf文档,特别需要理解的是Download部分. 与之对应的软件是:Smart Phone Flash Tool,一般是在菜单栏的Download部分进行选择操作. Download-agent(下载代理):选择 \升级固件与升级固件的工具\SP_Flash_Tool_exe_Windows_v5.1536.00.000 文件(通常不用特别选择,使用默认的即可

ARM汇编- LDR加载指令,LDR伪指令

1,ldr加载指令LDR指令的格式为:LDR{条件}  目的寄存器,<存储器地址>LDR指令用亍从存储器中将一个32位的字数据传送到目的寄存器中.该指令通常用亍从存储器中读取32位的字数据到通用寄存器,然后对数据迕行处理.当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转.该指令在程序设计中比较常用,丏寻址方式灵活多样,请读者认真掌握.指令示例: LDR R0,[R1]                                     

ARM中LDR伪指令与LDR加载指令

ARM指令集中,LDR通常都是作加载指令的,但是它也可以作伪指令. LDR伪指令的形式是“LDR Rn,=expr”.下面举一个例子来说明它的用法. COUNT EQU       0x40003100 …… LDR       R1,=COUNT MOV      R0,#0 STR       R0,[R1] COUNT是我们定义的一个变量,地址为0x40003100.这中定义方法在汇编语言中是很常见的,如果使用过单片机的话,应该都熟悉这种用法. LDR       R1,=COUNT是将C

ARM开发板加载Realtek-8188CUS USB无线网卡(一)

平台参数: 内核: Linux 3.6 文件系统:Busybox-1.20.2 硬件参数:S3C2416 在ARM-Linux支持并自动挂载U盘中已经验证好,USB接口是完全正常的,所以不用担心硬件上的故障. 一.引子 BZ使用的是"迅捷"(FAST)的一个USB接口无线网卡,型号FAST FW150US,关于这个网卡的故事... 实物如图: 通过Linux的lsusb命令可以查看它内部使用的是Realtek 8188CUS芯片: 二.正式开场 1.首先在Realtek官网下载对应的驱

【转】arm汇编—ldr加载指令,ldr伪指令

1,ldr加载指令 LDR指令的格式为:LDR{条件}  目的寄存器,<存储器地址>LDR指令用亍从存储器中将一个32位的字数据传送到目的寄存器中.该指令通常用亍从存储器中读取32位的字数据到通用寄存器,然后对数据迕行处理.当程序计数器PC作为目的寄存器时,指令从存储器中读取的字数据被当作目的地址,从而可以实现程序流程的跳转.该指令在程序设计中比较常用,丏寻址方式灵活多样,请读者认真掌握.指令示例:LDR R0,[R1]         :将存储器地址为R1的字数据读入寄存器R0.LDR R0