使用场景如下:

我需要将bootloader/APP的版本号和一些字段信息定义到指定FLASH地址.

在STM32CubeIDE中的方法:

截止当前STM32CubeIDE还没有提供图形化的针对FLASH划分定义的支持选项, 所以第一步我们需要手动更改 .ld文件 (链接文件).

原文件如下(部分):

/* Memories definition */
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 64K
}

修改后:

/* Memories definition */
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K
FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 8K
VERSION_FLASH (rx) : ORIGIN = 0x8002000, LENGTH = 1K
REMFLASH (rx) : ORIGIN = 0x8002400, LENGTH = 55K
}
/* Sections */
SECTIONS
{
/* The startup code into "FLASH" Rom type memory */
.isr_vector :
{
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
} >FLASH /* The program code and other data into "FLASH" Rom type memory */
.text :
{
. = ALIGN(4);
*(.text) /* .text sections (code) */
*(.text*) /* .text* sections (code) */
*(.glue_7) /* glue arm to thumb code */
*(.glue_7t) /* glue thumb to arm code */
*(.eh_frame) KEEP (*(.init))
KEEP (*(.fini)) . = ALIGN(4);
_etext = .; /* define a global symbols at end of code */
} > REMFLASH .version_code :
{
*(.bl_info.ver)
*(.bl_info.date)
*(.bl_info.detailed);
} > VERSION_FLASH
....略

我们重点看一下修改后的FLASH内存结构.

这里将FLASH的前8K预留出来, 用于存放中断向量表这是硬规! 所以我们不能划分FLASH的起始区域自用.

仅中断向量表是用不完8K的,因为后面还有一些其它项的分配如 .ARM.extab, .ARM 所以这里简单预留为8K.

后面的 VERSION_FLASH 用于存储我们的自定义字段. 这里划分为1K.

REMFLASH 用于存放程序代码.

具体变量定义使用如下

volatile const char __RO_BL_INFO_VERSION__[] __attribute__((section(".bl_info.ver"))) = {"XXXX_V1.0"};
volatile const char __RO_BL_INFO_DATE__[] __attribute__((section(".bl_info.date"))) = { __DATE__ };
volatile const char __RO_BL_INFO_DETAIL__[] __attribute__((section(".bl_info.detailed"))) = { "Hello world !" };

定义好之后, 可以通过 .map 文件查看变量具体的存储地址.

如上操作后, 正常情况下 .map 中并不会有你想要的变量. 原因是编译器给优化了.

我尝试使用了很多别的办法, 但是最终只有如下方法可行.

if (__RO_BL_INFO_VERSION__[0] == 'A' && __RO_BL_INFO_VERSION__[2] == 'A'
&& __RO_BL_INFO_DATE__[1] == 'A') {
while (1);
} 如有其它更好的方法, 预防编译器优化. 请留言.

下面是一个重要提示:

切忌不要将上文中的 VERSION_FLASH 分配到FLASH的最后. 例如:

/* Memories definition */
MEMORY
{
CCMRAM (xrw) : ORIGIN = 0x10000000, LENGTH = 64K
RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 128K FLASH (rx) : ORIGIN = 0x8000000, LENGTH = 8K
REMFLASH (rx) : ORIGIN = 0x8002000, LENGTH = 32K
VERSION_FLASH (rx) : ORIGIN = 0x800A000, LENGTH = 1K
}

原因是我们并不清楚(或者非常麻烦)程序到底需要占用多大的FLASH空间. 如果 REMFLASH 定义的非常大, 则最终生成的 bin 文件将非常大(中间会有空填充),

如上的具体大小为 8+32 = 40K, 而实际的有效程序可能只有18K大小(HEX无影响). 该bin文件的大小计算仅仅适用于STM32CubeIDE, 在一些其它的IDE可能会是

40K大小. 但不管计算方法如何, 最终都会造成bin体积的增大. 如果该bin用于APP程序的升级将造成很大的时间浪费.

STM32CUBEIDE 如何将变量定义到指定内存地址的更多相关文章

  1. python的变量,对象的内存地址以及参数传递过程

    作为一个由c/c++转过来的菜鸟,刚接触Python的变量的时候很不适应,应为他的行为很像指针,void* ,不知道大家有没有这样的感觉.其实Python是以数据为本,变量可以理解为标签.作为c/c+ ...

  2. Python中查看变量的类型,内存地址,所占字节的大小

    查看变量的类型 #利用内置type()函数 >>> nfc=["Packers","49"] >>> afc=[" ...

  3. python 变量的赋值【内存地址】

    注意: python所有的数据都是对象,变量只是指向一个对象的地址,一旦将变量的值或者类型改变,变量指向的地址就有可能发生变化 这个特性在使用默认参数的时候一定要注意

  4. ES6学习笔记(一)新的变量定义命令let和const

    1.一些历史 ES6(ECMAScript 6.0)是 JavaScript 语言的新一代标准,于2015 年 6 月正式发布,距今已经4年了,它的目标,是使得 JavaScript 语言可以用来编写 ...

  5. c语言中通过指针将数值赋值到制定内存地址

    1.一种直观的方法 假设现在需要往内存0x12ff7c地址上存入一个整型数0x100.我们怎么才能做到呢? 我们知道可以通过一个指针向其指向的内存地址写入数据,那么这里的内存地址0x12ff7c其本质 ...

  6. iOS开发系列-打印内存地址

    打印内存地址 基本数据类型 定义一个基本数据类型,会根据变量类型分配对应的内存空间.比如定义一个int类型的变量a. int a = 10; 内存如下 输入变量a在内存中内存地址 NSLog(@&qu ...

  7. js高程读书笔记(第4章--变量、作用域和内存)

    JavaScript变量松散类型的本质,决定了它只是在特定时间用于保存特定值的一个名字而已.由于不存在定义某个变量必须要保存何总数据类型值的规则,变量的值及其数据类型可以在脚本的生命周期内改变. 1. ...

  8. JavaScript 高级程序设计(第3版)笔记——chapter4:变量、作用域和内存问题

    Chapter4 变量.作用域和内存问题 l  理解基本类型和引用类型的值 l  理解执行环境 l  理解垃圾收集 4.1基本类型和引用类型的值 l  ECMAScript变量包含两种不同数据类型的值 ...

  9. C++ 用变量定义数组

    较早的编译器是不同意这样做的,所以一些书籍比方以Tc解说的书本都说数组的下标不能是变量.在vc6.0下亦是如此. 只是在一些较新的编译器如dev c++已经支持了,例如以下代码不会报错 #includ ...

  10. JavaScript基础笔记(二)变量、作用域和内存问题

    变量.作用域和内存问题 一.基本类型和引用类型的值 基本类型值:简单的数据段 引用类型值:由多个值构成的对象 基本类型是按值访问的,引用类型是按引用访问的. 不能给基本类型的值添加属性,尽管不会报错. ...

随机推荐

  1. ROS的通信机制

    通信机制 节点--执行单元 执行具体任务的进程.独立运行的可执行文件: 不同节点可以使用不同的编程语言,可分布式运行在不同的主机上. 节点在系统中的名称是必须是唯一的. 节点管理器(ROS Maste ...

  2. OOP第三次大作业

    前言 前言的前言 快期末,也一直在等这次作业发布,我现在只能说终于等到了!!!跟上一个Blog的时间相隔比较大,内容也比较多,涉及范围也比较广7-11次小练习,废话不多说,直接开始吧.如果对我blog ...

  3. Angular:修改启动端口号

    目标 修改预先设定的4200端口号,改为4100 解决方案 在启动命令中添加 --port 4100.参数 --open,会在启动时自动打开浏览器. ng serve --open --port 41 ...

  4. 数据分析师如何用SQL解决业务问题?

    本文来自问答. 提问:数据分析人员需要掌握sql到什么程度? 请问做一名数据分析人员,在sql方面需要掌握到什么程度呢?会增删改查就可以了吗?还是说关于开发的内容也要会?不同阶段会有不同的要求吗? 正 ...

  5. chrome浏览器插件react devtools、redux devtools,无需安装、解压即可用

    react devtools用于调试react代码,可以查看到props.state的值,以及定义的hooks,而redux devtools可以追踪到action的派发.store的变化,两个都是r ...

  6. 高级SQL分析函数-窗口函数

    摘要:本文由葡萄城技术团队于博客园原创并首发.转载请注明出处:葡萄城官网,葡萄城为开发者提供专业的开发工具.解决方案和服务,赋能开发者. 前言 SQL语句中,聚合函数在统计业务数据结果时起到了重要作用 ...

  7. ❤️ GitHub Copilot 读心术揭秘,Copilot 逆向工程笔记

    总览 你是否好奇 GitHub Copilot 如何知道你想写的内容?有时候它聪明得甚至好像读过你项目里其他文件一样,不要怀疑,它确实读过.这篇文章记录了我阅读一个对 Copilot 的逆向工程的笔记 ...

  8. 关于API数据接口获取商品的数据的说明

    ​ 获取商品数据已经成为许多应用程序的重要组成部分.为了实现这一目标,许多公司和技术开发者使用API数据接口来获取相关数据.本文将详细介绍如何使用API数据接口获取商品数据,并使用Python作为编程 ...

  9. C++算法之旅、05 基础篇 | 第二章 数据结构

    常用代码模板2--数据结构 - AcWing 笔试用数组模拟而不是结构体 使用结构体指针,new Node() 非常慢,创建10万个节点就超时了,做笔试题不会用这种方式(优化是提前初始化好数组,但这样 ...

  10. 一文解锁vue3中hooks的使用姿势

    vue3 中的 hooks 是什么? 简单来说如果你的函数中用到了诸如 ref,reactive,onMounted 等 vue 提供的 api 的话,那么它就是一个 hooks 函数,如果没用到它就 ...