0. 数据类型说明

主要包括4类:

  1. Code (inc. data) ,属于RO,也就是写的函数代码(包括代码中的变量)
  2. RO Data , 属于RO,使用const修饰的变量。
  3. RW Data, 属于RW,变量。
  4. ZI Data,   属于RW,没有初始化的变量。

1. mdk 设置Scatter 文件

默认情况下,片内会有两大存储块IROM(只读存储器RO,用来存常量、代码等),IRAM(读写存储器RW,用来存变量,包括被默认初始化为0的变量),如下图 "Target"选项卡。

来看“Linker”选项卡,下面介绍操作:

1. 默认的选项是使用的“Target”的内存分区,需要把这个勾去掉。

2. 去掉勾后会出现一个“.sct"文件,点击Edit就可以修改了,对文件做了注释说明如下:

LR_IROM1 0x08000000 0x00080000  {    ; load region size_region, 装载区域
; LR_IROM1, 这是一个名字,随便起。可以理解为一块存储器的名字。
; 0x08000000,这是起始地址。
; 0x00080000,代表size,也就是存储器的最大空间。 ER_IROM1 0x08000000 0x00080000 { ; load address = execution address, 执行区域
*.o (RESET, +First) ; *.o, 是说对于任意的".o"文件
; RESET 是说含有“RESET”的section名称的
; +First 是说最先匹配
; 合起来就是在所有的“.o”文件中找到含有“RESET”字段的内容放到“ER_IROM1"这块存储区域内
*(InRoot$$Sections)
.ANY (+RO) ; '.ANY' 可以理解成 '*' ,是说把剩下的RO类型的数据(常量和代码)放到这里。
}
RW_IRAM1 0x20000000 0x00010000 { ; RW data
.ANY (+RW +ZI) ; 是说把剩下的RW,ZI类型的数据(常量和代码)放到这里。
}
}

从上面可以看到这里只做了两个区分,大体上就是RO和RW的区别,下面说明自定义区域。

3. 这里我们定义两个区域,一个用来存放函数,一个用来存放数据:

LR_IROM1 0x08000000 0x00080000  {    ; load region size_region
ER_IROM1 0x08000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
} MY_FUN 0x20000000 0x00000080 { ; 自定义函数存储位置,地址及大小仅作说明。
.ANY (pg_fun)
} MY_DATA 0x20000080 0x00000080 { ; 自定义数据存储位置,地址及大小仅作说明。
.ANY (pg_data)
} RW_IRAM2 0x20000100 0x0000FF00 {
.ANY (+RW +ZI) ; RW data
}
}

4. 在“inc.h"头文件中:

#define PG_FUN_ATTRIBUTES  __attribute__ ((section("pg_fun")))
#define PG_DATA_ATTRIBUTES __attribute__ ((section("pg_data"))) void test1 (void);

5. 在”test.c"文件中:

#include "inc.h"

typedef struct tt{    // 自定义结构体
int a;
double b;
}tt_t; // 变量定义,分配到定义的数据区域内
static tt_t t0 PG_DATA_ATTRIBUTES = {
.a = ,
.b = ,
};
static char t1[] PG_DATA_ATTRIBUTES; // 函数定义,分配到定义的函数区域内
void test1 PG_FUN_ATTRIBUTES()
{
t0.a = ;
}

6. 在“main.c"文件中:

#include "stm32f10x.h"
#include <stdint.h>
#include "inc.h"
#include <stdio.h> static char tc2[] PG_DATA_ATTRIBUTES;
void foo PG_FUN_ATTRIBUTES()
{
tc2[] = ;
} int main()
{
foo();
test1();
return ;
}

7. 文件“test.map" 查看结果:

    Execution Region MY_FUN (Base: 0x20000000, Size: 0x00000018, Max: 0x00000080, ABSOLUTE)

    Base Addr    Size         Type   Attr      Idx    E Section Name        Object

    0x20000000   0x0000000c   Code   RO                pg_fun              main.o
0x2000000c 0x0000000c Code RO pg_fun test.o Execution Region MY_DATA (Base: 0x20000080, Size: 0x0000002c, Max: 0x00000080, ABSOLUTE) Base Addr Size Type Attr Idx E Section Name Object 0x20000080 0x00000005 Data RW pg_data main.o
0x20000085 0x00000003 PAD
0x20000088 0x00000022 Data RW pg_data test.o

可以看到,函数和代码都以如愿以偿。

结构体编译出错,参考这篇文章:MDK KEIL 机构体初始化

mdk keil 指定变量、函数存储位置,使用 Scatter-Loading Description File, __attribute__(("section“))的更多相关文章

  1. STM32 内存分配解析及变量的存储位置

    内存映射 在一些桌面程序中,整个内存映射是通过虚拟内存来进行管理的,使用一种称为内存管理单元(MMU)的硬件结构来将程序的内存映射到物理RAM.在对于 RAM 紧缺的嵌入式系统中,是缺少 MMU 内存 ...

  2. Java学习笔记9---类静态成员变量的存储位置及JVM的内存划分

    笔记8提到了类静态成员变量的访问方式,但静态成员变量存储在哪里呢?在网上查阅不少资料,发现好多内容都是过时的了,其中主流观点是静态成员变量存放在方法区.JDK8之前,静态成员变量确实存放在方法区:但J ...

  3. 【转载】java 中变量的存储位置

    原文链接点这里,感谢博主分享 * 寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. * 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出 ...

  4. java中变量的存储位置

    1.寄存器:最快的存储区, 由编译器根据需求进行分配,我们在程序中无法控制. 2. 栈:存放基本类型的变量数据和对象的引用,但对象本身不存放在栈中,而是存放在堆(new 出来的对象)或者常量池中(字符 ...

  5. Python3基础 使用id() 查询变量的存储位置

    镇场诗: 诚听如来语,顿舍世间名与利.愿做地藏徒,广演是经阎浮提. 愿尽吾所学,成就一良心博客.愿诸后来人,重现智慧清净体.-------------------------------------- ...

  6. C06 变量和存储类型

    目录 全局变量 局部变量 存储类型 全局变量和局部变量 变量的作用域 作用域:某些事物起作用或有效的区域. 变量的使用范围称为变量的作用域. 变量的作用域决定了变量的可操作性和有效性. C语言变量的作 ...

  7. C++中类所占的内存大小以及成员函数的存储位置

    类所占内存的大小是由成员变量(静态变量除外)决定的,虚函数指针和虚基类指针也属于数据部分,成员函数是不计算在内的.因为在编译器处理后,成员变量和成员函数是分离的.成员函数还是以一般的函数一样的存在.a ...

  8. js判断是否存在指定变量或函数

    //是否存在指定变量 function isExitsVariable(variableName) { try { if (typeof(eval(variableName)) == "un ...

  9. c 变量的存储类型auto等(基础知识)和c函数变量

    总结 1).在c语言中每一个变量和函数有两个属性:数据类型和数据的存储类别. 2). 对数据型(如整型.字符型等).存储类别指的是数据在内存中存储的方式. 存储方式分为两大类: 静态存储类和动态存储类 ...

随机推荐

  1. Android中的gen文件为空或者不存在的处理方法

    Android中的gen文件时链接程序和XML中资源定义的桥梁,所以如果gen文件夹为空可能有以下的几个原因: 1.XML文件错误,这时可以检查res文件夹中的文件是否有错误 2.导入新的Androi ...

  2. 分治维护dp——19南昌网络赛C/cf750E

    南昌网络赛,是cf的原题 第一次做到这种题,所以认真想了下,每次给一个询问[L,R],要求出这个区间里有2017子序列,但是不能有2016子序列需要删掉的最少元素个数 首先如果我们之询问一小段区间[L ...

  3. 1.3 React 组件

    1.3.1 React 组件介绍 在 React 中组件是第一元素,是 React 的基础,一个 React 应用就是基于 React 组件的组合而成.前面的 JSX 练习过后,大家应该对 React ...

  4. java.util.Arrays,java.lang.Math,java.lang.System 类的常用方法汇总

    java.util.Arrays类是数组的工具类,一般数组常用的方法包括 二分查找:public static int  binarySearch(array[],int key),返回key的下标i ...

  5. Java方法中形参能否改变实参

    前几天学习了java中的参数传递机制,总结了一些知识点: 1·参数类型为基本数据类型:整型:byte,short,int,long ,浮点型:float,double ,字符型:char ,布尔型:b ...

  6. \t \r \n转义字符

    t \r \n都是转义字符,空格就是单纯的空格,输入时可以输入空格 \t 的意思是 横向跳到下一制表符位置 \r 的意思是 回车 \n 的意思是回车换行 所有的转义字符和所对应的意义: 转义字符 意义 ...

  7. 列表分成N等份

    将一个长列表分为N个短列表 def Equal_division_list(eq_list, n): ''' :param seq:传入的列表 :param n:划分的份数,几等分 :return:返 ...

  8. Webpack4篇

    [Webpack4篇] webpack4 打包优化策略 当前依赖包的版本 1 优化loader配置 1.1 缩小文件匹配范围(include/exclude) 通过排除node_modules下的文件 ...

  9. DFS问题举例:N个整数选k个使其和为x

    N个整数选k个使其和为x,若有多个方案,选择元素平方和最大的一个 #include<cstdio> #include<cmath> #include<cstring> ...

  10. JS数组 选定元素slice() slice() 方法可从已有的数组中返回选定的元素。 语法 arrayObject.slice(start,end)

    选定元素slice() slice() 方法可从已有的数组中返回选定的元素. 语法 arrayObject.slice(start,end) 参数说明: 1.返回一个新的数组,包含从 start 到 ...