*.sct分散加载文件是根据芯片内部FLASH和SRAM存储器概况生成的配置文件,链接器根据该文件的配置分配各个节区地址,生成分散加载代码,通过修改该文件可以定制节区的具体存储位置。例如控制代码的加载区与执行区位置,将代码加载区设定为NAND-FLASH的程序位置,执行区设定为外部SDRAM中的位置,使得链接器生成配套的分散加载代码, 把NAND-FLASH中的代码加载到外部SDRAM中,内核再从外部SDRAM中运行主体代码(大部分运行Linux系统的代码都是这样加载的),进而实现低成本存储。

一、分散加载文件的格式

sct文件中主要包含描述加载域及执行域的部分,一个文件中可包含有多个加载域,而一个加载域可由多个部分的执行域组成。 同等级的域之间使用花括号“{}”分隔开,最外层的是加载域,第二层“{}”内的是执行域, 其整体结构如图

加载域

//方括号中的为选填内容
加载域名 基地址 | ("+" 地址偏移) [属性列表] [最大容量]
"{"执行区域描述
"}"

执行域

//方括号中的为选填内容
执行域名 基地址 | ("+" 地址偏移) [属性列表] [最大容量 ]
"{"输入节区描述
"}"

输入节区描述

//除模块选择样式部分外,其余部分都可选选填
模块选择样式"("输入节区样式",""+"输入节区属性")"
模块选择样式"("输入节区样式",""+"节区特性")"模块选择样式"("输入符号样式",""+"节区特性")"
模块选择样式"("输入符号样式",""+"输入节区属性")"

模块选择样式:用于选择o及lib目标文件作为输入节区,它可以直接使用目标文件名或“*”通配符,也可以使用“.ANY”。其中“.ANY”选择语句的优先级是最低的,所有其它选择语句选择完剩下的数据才会被“.ANY”语句选中。

输入节区(符号)样式:用于选择要控制的节区和符号。

输入节区属性:可以使用的节区属性描述符见下表。

节区属性描述符

说明

RO-CODE及CODE

只读代码段

RO-DATA及CONST

只读数据段

RO及TEXT

包括RO-CODE及RO-DATA

RW-DATA

可读写数据段

RW-CODE

可读写代码段

RW及DATA

包括RW-DATA及RW-CODE

ZI及BSS

初始化为0的可读写数据段

XO

只可执行的区域

ENTRY

节区的入口点

节区特性:节区特性可以使用“+FIRST”或“+LAST”选项配置它要存储到的位置,FIRST存储到区域的头部,LAST存储到尾部。 通常重要的节区会放在头部,而CheckSum(校验和)之类的数据会放在尾部。

二、具体应用

编写sct文件优先使用内部SRAM空间,在需要的时候使用一个关键字指定变量存储到外部SDRAM,并把堆区分配到外部SDRAM,从而可以使用C语言标准库的malloc函数动态从外部SDRAM中分配空间进行内存管理。

(1)修改启动文件,在__main执行之前初始化外部SDRAM

; Reset handler
Reset_Handler    PROCEXPORT  Reset_Handler             [WEAK]IMPORT  SystemInitIMPORT  __main;从外部文件引入声明IMPORT SDRAM_InitLDR     R0, =SystemInitBLX     R0;在__main之前调用SDRAM_Init进行初始化LDR   R0, =SDRAM_InitBLX   R0LDR     R0, =__mainBX      R0ENDP

(2)sct文件配置

; *************************************************************
; *** Scatter-Loading Description File generated by uVision ***
; *************************************************************
LR_IROM1 0x08000000 0x00100000  {    ; load region size_regionER_IROM1 0x08000000 0x00100000  {  ; load address = execution address*.o (RESET, +First)*(InRoot$$Sections).ANY (+RO)}RW_IRAM1 0x20000000 0x00030000  {  ; 内部SRAM.ANY (+RW +ZI)      ;其余的RW/ZI-data都分配到这里}RW_ERAM1 0xD0000000 0x00800000 {  ; 外部SDRAM*.o(HEAP)            ;选择堆区.ANY (EXRAM)       ;选择EXRAM节区}
}

上述sct文件在保留内部SRAM执行域默认配置的基础上,新增了一个外部SDRAM的执行域, 并且使用了“*.o(HEAP)”语句把堆区分配到了外部SDRAM空间(栈区和堆区属于ZI-data类,默认情况下会分配到内部SRAM),使用“.ANY(EXRAM)”语句把名为“EXRAM”的节区分配到外部SDRAM空间。

(3)指定变量分配到节区

//使用 __attribute__ 关键字定义指定变量定义到某节区
//语法: 变量定义 __attribute__ ((section ("节区名"))) = 变量值;
uint32_t testValue  __attribute__ ((section ("EXRAM"))) =7 ;//使用宏封装
//设置变量定义到“EXRAM”节区的宏
#define __EXRAM  __attribute__ ((section ("EXRAM")))//使用该宏定义变量到外部SDRAM
uint32_t testValue __EXRAM =7 

上述代码使用“__attribute__ ((section(“EXRAM”)))”将定义变量分配到外部SDRAM执行域的“EXRAM”节区中。

(4)变量分配测试及结果

//设置变量定义到“EXRAM”节区的宏
#define __EXRAM  __attribute__ ((section ("EXRAM")))//定义变量到SDRAM
uint32_t testValue __EXRAM =7 ;
//上述语句等效于
//uint32_t testValue  __attribute__ ((section ("EXRAM"))) =7 ;//定义变量到SRAM
uint32_t testValue2  =7 ;//定义数组到SDRAM
uint8_t testGrup[3] __EXRAM ={1,2,3};
//定义数组到SRAM
uint8_t testGrup2[3] ={1,2,3};/**
* @brief  主函数
* @param  无
* @retval 无
*/
int main(void)
{uint32_t inerTestValue =10;/*SDRAM_Init已经在启动文件的Reset_handler中调用,进入main之前已经完成初始化*///  SDRAM_Init();/* 初始化串口 */Debug_USART_Config();uint32_t *pointer = (uint32_t*)malloc(sizeof(uint32_t)*3);if(pointer != NULL){*(pointer)=1;*(++pointer)=2;*(++pointer)=3;free(pointer);}else{printf("\r\n使用malloc动态分配变量出错!!!\r\n");}while(1);
}

代码中定义了普通变量、指定到EXRAM节区的变量并使用动态分配内存,还把它们的值和地址通过串口打印到上位机,通过这些变量,我们可以检查变量是否能正常分配。

构建工程后,查看工程的map文件观察变量的分配情况,从map文件中可看到普通变量及栈节区都被分配到了内部SRAM的地址区域,而指定到EXRAM节区的变量及堆空间都被分配到了外部SDRAM的地址区域,与预期一致。

三、相关知识补充

  • map文件说明

map文件是由链接器生成的,它主要包含交叉链接信息,可以分为以下几个部分。

节区的跨文件引用:可以了解工程中各种符号(函数、变量名)之间的引用关系。

删除无用节区:列出了链接过程工程中未被引用的节区,这些节区将会被删除(不加入到*.axf文件,但*.o文件中仍存在)。

符号映像表:列出了被引用的各个符号在存储器中的具体地址、占据的空间大小等信息。

存储器映像索引:主要信息包括存储器中各个节区的类型属性、具体地址以及占据空间大小。

映像组件大小:最常查询的内容,包含各个使用到的*.o文件、不同类型存储器和整个工程具体占据的Code、RO-data、 RW-data和ZI-data大小以及空间汇总信息。

  • 使用malloc管理外部SDRAM空间

C标准库的malloc函数是根据__heap_base及__heap_limit地址限制分配空间的,在启动文件代码定义中,堆基地址__heap_base由链接器自动分配未使用的基地址,而堆顶地址__heap_limit和Heap_Size可以根据用户需要自定义配置。

Heap_Size       EQU     0x00000200AREA    HEAP, NOINIT, READWRITE, ALIGN=3__heap_base
Heap_Mem        SPACE   Heap_Size
__heap_limit    EQU   0xd0800000    ;设置堆空间的极限地址(SDRAM),
;0xd0000000+0x00800000PRESERVE8THUMB
  • SDRAM用于显存的改变

当在代码中直接使用宏定义SDRAM地址作为显存空间时,链接器无法跟踪其内存配置,因此链接器在自动分配变量到SDRAM时,极有可能导致空间冲突出现错误。

解决方案之一是使用__EXRAM定义一个数组空间作为显存,由链接器自动分配空间地址,然后把数组地址作为显存地址。

/* LCD Size (Width and Height) */
#define  LCD_PIXEL_WIDTH    ((uint16_t)800)
#define  LCD_PIXEL_HEIGHT   ((uint16_t)480)#define LCD_FRAME_BUFFER       ((uint32_t)0xD0000000)   //第一层首地址
#define BUFFER_OFFSET          ((uint32_t)800*480*3)     //一层液晶的数据量
#define LCD_PIXCELS            ((uint32_t)800*480)uint8_t LCD_FRAME_BUFFER[BUFFER_OFFSET] __EXRAM;

说明:

(1)如果在外部SDRAM执行域中使用“.ANY(+RW +ZI)”语句,选择将所有RW/ZI类型的数据都自动分配变量到外部SDRAM空间时,需要注意将SDRAM初始化过程所需使用的栈空间以及部分RW-data类型变量通过节区语句(*.o(STACK),xxx.o(+RW)等)分配到内部SRAM的执行域。

(即使内部SRAM的执行域中也使用“.ANY(+RW+ZI)”语句选择所有RW及ZI属性的内容, 但对于符合两个相同选择语句的内容,链接器会优先选择使用空间较大的执行域, 即这种情况下只有当SDRAM执行域的空间使用完,RW/ZI属性的内容才会被分配到内部SRAM,所以在大部分情况下,内部SRAM执行域中的“.ANY(+RW +ZI)”语句是不起作用的)

(2)由于SDRAM需要在初始化并正常工作后才能够将栈分配到外部SDRAM,因此就需要外部SDRAM初始化过程不使用栈空间,也就是只能使用纯粹的寄存器方式配置。具体步骤如下:

  • 修改sct文件,使用“*.o(STACK)”语句把栈空间分配到外部SDRAM的执行域;

  • 根据硬件平台修改SystemInit_ExtMemCtl函数,该函数要实现外部SDRAM的初始化过程,且不能使用栈空间(局部变量);

  • 定义DATA_IN_ExtSDRAM宏,从而使得SystemInit_ExtMemCtl函数被加进(条件)编译,并被SystemInit调用(__main之前),进而在启动文件中被Reset_handler调用执行。

sct分散加载文件格式与应用相关推荐

  1. keil的sct文件_Keil sct分散加载文件

    博主是个还没入门的弱菜,老师让查资料所以我把自己找的资料整理一下搁在这里方便以后查阅用的,自己并没有试过. 如有错误,欢迎指正. 参考资料: 首先介绍几个概念: 1.ARM映像文件 ARM映像文件是一 ...

  2. 【IoT】STM32 分散加载文件 .sct 解析

    1.STM32 启动文件与 .sct 文件分析 1) 定义STACK段,{NOINIT,读写}:分配一段内存大小为0.5K; 2) 定义HEAP段, {NOINIT,读写}:分配一段内存大小为1K; ...

  3. keil的sct文件_STM32 分散加载文件 .sct 解析

    1.STM32 启动文件与 .sct 文件分析 1) 定义STACK段,{NOINIT,读写}:分配一段内存大小为0.5K; 2) 定义HEAP段, {NOINIT,读写}:分配一段内存大小为1K; ...

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

    https://blog.csdn.net/wuhenyouyuyouyu/article/details/71171546?ops_request_misc=%257B%2522request%25 ...

  5. KEIL MDK链接脚本-分散加载文件sct

    在了解keil的链接脚本之前需要了解几个重要概念: RO(ReadOnly):表示程序中的指令和常量 RW(Read/Write):表示程序中已初始化的变量 ZI(Zero):表示程序中未初始化的变量 ...

  6. keil分散加载文件sct写法

    //-------------------------------------------------------------------------------------------------- ...

  7. stm32h7内存分配_stm32h7“分散加载方式管理多块内存”

    默认情况下,我们都是通过 MDK 的 option 选项设置 Flash 和 RAM 大小,如图1 图1 这种情况下,不方便用户将变量定义到指定的 CCM 或者 SDRAM 中.而使用attribut ...

  8. STM32之MDK分析,分散加载

    STM32分散加载 我们知道MDK的分散加载主要是通过.sct文件实现的,链接器根据.sct文件的配置分配各个节区地址,生成分散加载代码,因此我们通过修改该文件可以定制具体节区的存储位置. 如何打开. ...

  9. keil STM32中sct 分散加载文件学习

    sct 分散加载文件简介 MDK 生成一个以工程名命名的后缀为 *.sct 的分散加载文件 (Linker Control File,scatter loading),链接器根据该文件的配置分配各个节 ...

最新文章

  1. 排序算法---选择排序(java版)
  2. 算法--运算的最小翻转次数
  3. 全国计算机二级考试vf知识点总结,VF全国计算机等级考试二级公共基础知识点总结.doc...
  4. 业界 | 如何达到Kaggle竞赛top 2%?这里有一篇特征探索经验帖
  5. 马哥学习笔记二十七——IO复用
  6. 最优化学习笔记(三)最速下降法
  7. Python解压压缩包
  8. 浅析C++游戏开发工程师的工作职责以及任职资格
  9. 计算机基础(二):嵌入式驱动、图像处理知识设备小结
  10. PathProber:基于暴力破解方法探测和发现HTTP路径名
  11. 按月分表(create table)
  12. coreldraw铺花纹_Coreldraw绘图实例教程,教你cdr环形花边绘制方法
  13. Linux配置DNS域名解析服务
  14. imx6q的启动方式
  15. 0ctf – mobile – boomshakalaka writeup
  16. ACdream 1424 Diversion(树链剖分+线段树)
  17. pip install xx 时遇到There was a problem confirming the ssl certificate…的解决办法
  18. 利用Python进行随机取名
  19. H5游戏开发(Egret引擎)及Typescript学习笔记
  20. idea框选为矩形解决方案

热门文章

  1. Google 宣布 GSoC 2014 计划Fwd: Google Summer of Code 2014 + 10 Things
  2. PhotoSwipe 图片浏览插件使用方法 - 简单
  3. VisualSVN的使用
  4. MySQL [1093] You can‘t specify target table ‘titles_test‘ for update in FROM clause
  5. 关于linux下的xinetd服务
  6. win10本地搜索应用没反应怎么解决?
  7. jsp处理的生命周期
  8. 2,JESD204为什么值得关注?
  9. 自动驾驶仿真软件列表
  10. 智能家居云服务器设计规格