• mdk keil 指定变量、函数存储位置,使用 Scatter-Loading Description File, __attribute__(("section“))


    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 = 1,
        .b = 2,
    };
    static char t1[10] PG_DATA_ATTRIBUTES;
    
    // 函数定义,分配到定义的函数区域内
    void test1 PG_FUN_ATTRIBUTES()
    {
        t0.a = 1;
    }

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

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

    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            5    pg_fun              main.o
        0x2000000c   0x0000000c   Code   RO          150    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            6    pg_data             main.o
        0x20000085   0x00000003   PAD
        0x20000088   0x00000022   Data   RW          151    pg_data             test.o

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

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

  • 相关阅读:
    9、SpringMVC:Ajax技术(扩展:百度搜索框提示应用)
    8、SpringMVC:整合SSM
    SpringMVC:多视图解析器配置以及问题
    7、SpringMVC:JSON讲解
    IDEA中lombok的插件配置及使用
    C语言编程练习23:美丽数
    C语言编程练习45:ACM CLUB晚会
    C语言编程练习22:2^x mod n = 1
    C语言编程练习21:找规律填数字
    C语言编程练习20:计算合并
  • 原文地址:https://www.cnblogs.com/qiyuexin/p/9026365.html
Copyright © 2020-2023  润新知