[ArmCompiler6--armlink]Keil-MDK中scatter load机制
来源:互联网 发布:熊神进淘宝店 编辑:程序博客网 时间:2024/06/04 18:03
简述
Keil MDK工具中,Armlink使用scatter加载机制来描述一份image在memory map中的划分。
image的memory map由regions和output sections组成。
Scatter加载
需要使用Scatter加载的场景
- 复杂的memory map,比如各种切分等
- 不同类别的memory设备,RAM, ROM, SRAM,外设等
- 固定函数放在指定位置
- 使用symbols来识别heap和stack
当使用scatter file时,如下的符号将未被定义
- Image–RO–Base.
- Image–RO–Limit.
- Image–RW–Base.
- Image–RW–Limit.
- Image–XO–Base.
- Image–XO–Limit.
- Image–ZI–Base.
- Image–ZI–Limit.
使用scatter file时,如果没有为stack和heap使用特定region,或没有重新实现__user_setup_stackheap(), 将会产生错误信息。
scatter file指定stack和heap
ARM C库为__user_setup_stackheap()提供了多种实现,并会根据statter file情况自动选择合适的一种实现。当然如果自己实现了user_setup_heap()的话,ARM C库提供的所有实现都会被覆盖。
另外在scatter file中定义两个特别的execution regions(ARM_LIB_HEAP和ARM_LIB_STACK)来选择两种region内存模式,这两种region都有EMPTY属性,一旦使用了这两种region内存模式,ARM C库提供的所有实现也会被无效掉,因为ARM C库中的user_setup_heap()使用了如下的synbols:
- Image–ARM_LIB_STACK–Base.
- Image–ARM_LIB_STACK–ZI–Limit.
- Image–ARM_LIB_HEAP–Base.
- Image–ARM_LIB_HEAP–ZI–Limit.
需要确保只有一个ARM_LIB_STACK或ARM_LIB_HEAP region的指定,且必须分配空间,因为user_setup_heap()会使用这些数据:
LOAD_FLASH …{ … ARM_LIB_STACK 0x40000 EMPTY -0x20000 ; Stack region growing down { } ARM_LIB_HEAP 0x28000000 EMPTY 0x80000 ; Heap region growing up { } …}
另外也可以只在scatter file中定义ARM_LIB_STACKHEAP,这样user_setup_stackheap()将使用如下symbol的值:
- Image–ARM_LIB_STACKHEAP–Base
- Image–ARM_LIB_STACKHEAP–ZI–Limit
复杂image scatter file示例
与此图对应的scatter file如下:
LOAD_ROM_1 0x0000 ; Start address for first load region (0x0000){ EXEC_ROM_1 0x0000 ; Start address for first exec region (0x0000) { program1.o (+RO) ; Place all code and RO data from ; program1.o into this exec region } DRAM 0x18000 0x8000 ; Start address for this exec region (0x18000), ; Maximum size of this exec region (0x8000) { program1.o (+RW, +ZI) ; Place all RW and ZI data from ; program1.o into this exec region }}LOAD_ROM_2 0x4000 ; Start address for second load region (0x4000){ EXEC_ROM_2 0x4000 { program2.o (+RO) ; Place all code and RO data from ; program2.o into this exec region } SRAM 0x8000 0x8000 { program2.o (+RW, +ZI) ; Place all RW and ZI data from ; program2.o into this exec region }}
这里是比较复杂的例子,即将program1和program2分别放在两个load region中。在一些不这么复杂的情况下,ARM推荐 *或.ANY 来指代剩下的code和data。
Root execution region的情况
Root region指的是load address和execution address相同的region。
image的初始化entry point必须在root region之内。
ABSOLUTE属性
ABSOLUTE属性可以用来指定root region。
为了使execution region address和load region address一样,如下条件满足其中之一即可:
ABSOLUTE属性用法示例如下:
LR_1 0x040000 ; load region starts at 0x40000 { ; start of execution region descriptions ER_RO 0x040000 ABSOLUTE ; load address = execution address { * (+RO) ; all RO sections (must include section with ; initial entry point) } … ; rest of scatter-loading description}
FIXED属性
FIXED属性用于创建固定地址的root regions。
对应的scatter file如下:
LR_1 0x040000 ; load region starts at 0x40000 { ; start of execution region descriptions ER_RO 0x040000 ; load address = execution address { * (+RO) ; RO sections other than those in init.o } ER_INIT 0x080000 FIXED ; load address and execution address of this ; execution region are fixed at 0x80000 { init.o(+RO) ; all RO sections from init.o } … ; rest of scatter-loading description}
可以使用该属性将某个函数,或一块数据(如常数表、校验值)放置在固定的地址。
例如一些初始化代码需要放在ROM的开头,校验码可能要放在ROM的末尾,那么一些memory内容可能是无用的。使用*或.ANY将其余的code或data填满初始化代码和校验码之间的memory空间。
为维护和调试方便,Keil建议在scatter file中只使用必要的指定地址防止,将大部分的都交给linker来做。
在固定地址放置函数或数据
armlinker允许在固定地址放置一个section,具体如下:
为将一个函数或变量放在指定地址,该函数或变量必须放在它自己的section中:
不使用scatter file而实现函数or数据放置在固定地址
- 创建main.c
#include <stdio.h>extern int sqr(int n1);const int gValue __attribute__((section(".ARM.__at_0x5000"))) = 3; // Place at 0x5000int main(){ int squared; squared=sqr(gValue); printf("Value squared is: %d\n", gSquared);}
- function.c
int sqr(int n1){ return n1*n1;}
- 编译与链接
armclang -target arm-arm-none-eabi -march=armv8-a -c -g function.carmclang -target arm-arm-none-eabi -march=armv8-a -c -g main.carmlink --cpu=8-A.32 --map function.o main.o -o squared.axf
使用scatter的命名section实现函数or数据放置在固定地址
- main.c
#include <stdio.h>extern int sqr(int n1);int gSquared __attribute__((section("foo"))); // Place in section fooint main(){ gSquared=sqr(3); printf("Value squared is: %d\n", gSquared);}
- function.c
int sqr(int n1){ return n1*n1;}
- scatter file
LR1 0x0000 0x20000{ ER1 0x0 0x2000 { *(+RO) ; rest of code and read-only data } ER2 0x8000 0x2000 { main.o } ER3 0x10000 0x2000 { function.o *(foo) ; Place gSquared in ER3 } ; RW and ZI data to be placed at 0x200000 RAM 0x200000 (0x1FF00-0x2000) { *(+RW, +ZI) } ARM_LIB_STACK 0x800000 EMPTY -0x10000 { } ARM_LIB_HEAP +0 EMPTY 0x10000 { }}
- 编译与链接
armclang -target arm-arm-none-eabi -march=armv8-a -c -g function.carmclang -target arm-arm-none-eabi -march=armv8-a -c -g main.carmlink --cpu=8-A.32 --map --scatter=scatter.scat function.o main.o -o squared.axf
使用scatter的指定地址实现函数or数据放置在固定地址
- main.c
#include <stdio.h>extern int sqr(int n1);// Place at address 0x10000const int gValue __attribute__((section(".ARM.__at_0x10000"))) = 3;int main(){ int squared; squared=sqr(gValue); printf("Value squared is: %d\n", squared);}
- function.c
int sqr(int n1){ return n1*n1;}
- scatter file
LR1 0x0{ ER1 0x0 { *(+RO) ; rest of code and read-only data } ER2 +0 { function.o *(.ARM.__at_0x10000) ; Place gValue at 0x10000 } ; RW and ZI data to be placed at 0x200000 RAM 0x200000 (0x1FF00-0x2000) { *(+RW, +ZI) } ARM_LIB_STACK 0x800000 EMPTY -0x10000 { } ARM_LIB_HEAP +0 EMPTY 0x10000 { }}
- 编译与链接
armclang -target arm-arm-none-eabi -march=armv8-a -c -g function.carmclang -target arm-arm-none-eabi -march=armv8-a -c -g main.carmlink --cpu=8-A.32 --no_autoat --scatter=scatter.scat --map function.o main.o -o squared.axf
- [ArmCompiler6--armlink]Keil-MDK中scatter load机制
- [ArmCompiler6--armlink]Keil-MDK中scatter file语法
- [ArmCompiler6--armlink]armlink使用介绍
- armlink - Scatter file文件格式
- armlink - Scatter file文件格式
- ARMLink scatter file(1)
- ARMLink scatter file(2)
- armlink scatter file
- keil(mdk)中宏定义
- Keil MDK
- Keil MDK中 异常问题收集
- Keil MDK 中MicroLib库的使用
- Keil MDK中生成.BIN文件
- keil MDK在RAM中调试
- Keil-MDK 中 [WEAK] 的作用
- Keil (MDK)中变量定义位置
- Keil-MDK 中 [WEAK] 的作用
- keil(MDK)中出现error: #513:
- Minimum Moves to Equal Array Elements问题及解法
- yum更新源
- POJ-3757: Simple Distributed storage system【简单01分数规划(二分)】
- Unity3D调用摄像头,画面为翻转的问题
- Docker Rest API使用入门
- [ArmCompiler6--armlink]Keil-MDK中scatter load机制
- Android简单动画相关
- Centos 7安装配置MariaDB
- (转载)wordpress插件推荐
- Jmeter使用BeanShell 断言进行判断
- 浅谈密码加SALT原理
- 细数网站建设中存在的那些霸王条款
- SELinux 宽容模式(permissive) 强制模式(enforcing) 关闭(disabled) 几种模式之间的转换
- C#技术漫谈之垃圾回收机制(GC)