浅析iar的icf分散加载文件-基于STM32的例程

2023-12-07 05:30

本文主要是介绍浅析iar的icf分散加载文件-基于STM32的例程,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

浅析iar的icf分散加载文件-基于STM32的例程

  • 关于分散加载文件
  • 分散加载文件stm32f103xC.icf

关于分散加载文件

IAR编译器在链接的时候,是根据分散加载(.scf后缀的文件)来确定程序的加载域和运行域的。加载域就是程序运行前在flash中具体分区情况,执行域就是程序运行后,程序在flash和ram中的分区情况。这里引用野火关于加载视图和执行视图的对比图:
在这里插入图片描述可以看到,左边是加载视图,RW段和RO段对应的存储空间我们称为加载域。当程序运行后,RW段中的数据会被复制到RAM中,同时还会初始化一个ZI段用来存放没有初始化和被初始化为零的相关变量。因此右边的相关储存空间我们称为执行域。

分散加载文件stm32f103xC.icf

那么怎么确定程序运行前、运行后的代码、数据等相应的地址和空间的呢?让我们找一个分散加载文件看看。打开一个STM32的工程,找到工程配置的入口,选中Linker,从在Config栏下,可以看到使用的是默认的分散加载文件。
在这里插入图片描述
我们根据链接文件的目录:$TOOLKIT_DIR$\config\linker\ST\stm32f103xC.icf,找到该分散加载文件并使用编辑器打开,如下图:
在这里插入图片描述
我们将内容复制出来如下:

define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x0803FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x2000BFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x1000;
define symbol __ICFEDIT_size_heap__   = 0x1000;
/**** End of ICF editor section. ###ICF###*/define memory mem with size = 4G;
define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };initialize by copy { readwrite };
do not initialize  { section .noinit };place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };place in ROM_region   { readonly };
place in RAM_region   { readwrite,block CSTACK, block HEAP };

后面稍微看一下具体的含义。

define symbol __ICFEDIT_region_ROM_start__ = 0x08000000;
define symbol __ICFEDIT_region_ROM_end__   = 0x0803FFFF;
define symbol __ICFEDIT_region_RAM_start__ = 0x20000000;
define symbol __ICFEDIT_region_RAM_end__   = 0x2000BFFF;
/*-Sizes-*/
define symbol __ICFEDIT_size_cstack__ = 0x1000;
define symbol __ICFEDIT_size_heap__   = 0x1000;

define类似我们C语言的宏定义用法,第一句表示定义了一个__ICFEDIT_region_ROM_start__的符号,且该符号的值为0x08000000,分号为语句的结束符。从符号的命名来看,该符号为STM32F103xC系列芯片内部Flash的起始地址,紧接着为内部Flash结束地址__ICFEDIT_region_ROM_end__,内部RAM的起始地址__ICFEDIT_region_RAM_start__,内部RAM的结束地址__ICFEDIT_region_RAM_end__,以及栈和堆的大小__ICFEDIT_size_cstack__和__ICFEDIT_size_heap__。
在这里插入图片描述
这里有个不理解的地方,我查了一下发现STM32F103xC的内部Flash大小为256k,内部RAM的大小为48k,分散加载文件这里默认给的Flash范围0x08000000到0x0803FFFF,其大小只有64K,同样RAM的大小也没对应上。或许默认只使用一部分?了解的朋友麻烦告知一下。

define memory mem with size = 4G;

这里定义可编程空间为4G,STM32的地址总线为32位,可寻址空间为2^32=4G,这里可以参考STM32的存储映射情况。

define region ROM_region   = mem:[from __ICFEDIT_region_ROM_start__   to __ICFEDIT_region_ROM_end__];
define region RAM_region   = mem:[from __ICFEDIT_region_RAM_start__   to __ICFEDIT_region_RAM_end__];

这里定义了两个区域ROM_region和RAM_region,括号里描述了他们的地址范围。

define block CSTACK    with alignment = 8, size = __ICFEDIT_size_cstack__   { };
define block HEAP      with alignment = 8, size = __ICFEDIT_size_heap__     { };

这里定义了两个块CSTACK 和HEAP,后面的参数alignment=8表示八字节对齐,size = __ICFEDIT_size_cstack__描述了其大小。

initialize by copy { readwrite };
do not initialize  { section .noinit };

initialize by copy,表示程序运行时,需要从ROM中复制到RAM中的内容。我们在程序里定义并且初始化的全局变量,就需要执行这样的操作,因此在这里添加readwrite。如果有程序段需要放到RAM中执行,也需要将程序段对应的section放到这里,才能在程序运行时被复制到RAM。例如将函数放在了段.funtion_in_ram下,需要运行在RAM中,则此处需要添加initialize by copy { readwrite, section .funtion_in_ram}。当然除此之外,还要正确的定义.funtion_in_ram的存储地址。

place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };

这里将段.intvec中只读属性部分,放在__ICFEDIT_intvec_start__地址处。有看过启动文件的朋友应该知道,.intvec就是启动文件里定义的段。因此这里是将中断向量表放在0x08000000处。

place in ROM_region   { readonly };
place in RAM_region   { readwrite,block CSTACK, block HEAP };

place in 表示将对应的段或块等放在指定的空间里。前面已经定义了ROM_region和RAM_region的空间范围。place in ROM_region { readonly },描述的是将readonly 属性的内容(代码段和const变量等)放到ROM_region 中;place in RAM_region { readwrite,
block CSTACK, block HEAP }描述的是将readwrite属性,以及前面定义的block CSTACK和 block HEAP放到RAM_region中。

本次的分享就到这里,欢迎批评指正。

这篇关于浅析iar的icf分散加载文件-基于STM32的例程的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/464651

相关文章

Spring如何使用注解@DependsOn控制Bean加载顺序

《Spring如何使用注解@DependsOn控制Bean加载顺序》:本文主要介绍Spring如何使用注解@DependsOn控制Bean加载顺序,具有很好的参考价值,希望对大家有所帮助,如有错误... 目录1.javascript 前言2. 代码实现总结1. 前言默认情况下,Spring加载Bean的顺

浅析如何保证MySQL与Redis数据一致性

《浅析如何保证MySQL与Redis数据一致性》在互联网应用中,MySQL作为持久化存储引擎,Redis作为高性能缓存层,两者的组合能有效提升系统性能,下面我们来看看如何保证两者的数据一致性吧... 目录一、数据不一致性的根源1.1 典型不一致场景1.2 关键矛盾点二、一致性保障策略2.1 基础策略:更新数

springboot加载不到nacos配置中心的配置问题处理

《springboot加载不到nacos配置中心的配置问题处理》:本文主要介绍springboot加载不到nacos配置中心的配置问题处理,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑... 目录springboot加载不到nacos配置中心的配置两种可能Spring Boot 版本Nacos

使用Python获取JS加载的数据的多种实现方法

《使用Python获取JS加载的数据的多种实现方法》在当今的互联网时代,网页数据的动态加载已经成为一种常见的技术手段,许多现代网站通过JavaScript(JS)动态加载内容,这使得传统的静态网页爬取... 目录引言一、动态 网页与js加载数据的原理二、python爬取JS加载数据的方法(一)分析网络请求1

IDEA下"File is read-only"可能原因分析及"找不到或无法加载主类"的问题

《IDEA下Fileisread-only可能原因分析及找不到或无法加载主类的问题》:本文主要介绍IDEA下Fileisread-only可能原因分析及找不到或无法加载主类的问题,具有很好的参... 目录1.File is read-only”可能原因2.“找不到或无法加载主类”问题的解决总结1.File

浅析Java如何保护敏感数据

《浅析Java如何保护敏感数据》在当今数字化时代,数据安全成为了软件开发中至关重要的课题,本文将深入探讨Java安全领域,聚焦于敏感数据保护的策略与实践,感兴趣的小伙伴可以了解下... 目录一、Java 安全的重要性二、敏感数据加密技术(一)对称加密(二)非对称加密三、敏感数据的访问控制(一)基于角色的访问

重新对Java的类加载器的学习方式

《重新对Java的类加载器的学习方式》:本文主要介绍重新对Java的类加载器的学习方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐教... 目录1、介绍1.1、简介1.2、符号引用和直接引用1、符号引用2、直接引用3、符号转直接的过程2、加载流程3、类加载的分类3.1、显示

在 PyQt 加载 UI 三种常见方法

《在PyQt加载UI三种常见方法》在PyQt中,加载UI文件通常指的是使用QtDesigner设计的.ui文件,并将其转换为Python代码,以便在PyQt应用程序中使用,这篇文章给大家介绍在... 目录方法一:使用 uic 模块动态加载 (不推荐用于大型项目)方法二:将 UI 文件编译为 python 模

Spring框架中@Lazy延迟加载原理和使用详解

《Spring框架中@Lazy延迟加载原理和使用详解》:本文主要介绍Spring框架中@Lazy延迟加载原理和使用方式,具有很好的参考价值,希望对大家有所帮助,如有错误或未考虑完全的地方,望不吝赐... 目录一、@Lazy延迟加载原理1.延迟加载原理1.1 @Lazy三种配置方法1.2 @Component

浅析如何使用xstream实现javaBean与xml互转

《浅析如何使用xstream实现javaBean与xml互转》XStream是一个用于将Java对象与XML之间进行转换的库,它非常简单易用,下面将详细介绍如何使用XStream实现JavaBean与... 目录1. 引入依赖2. 定义 JavaBean3. JavaBean 转 XML4. XML 转 J