在 MDK (Keil MDK) 中,__no_init 关键字用于声明不需要初始化的变量。这通常用于保留特定内存区域的内容,例如在复位后保留某些变量的值。 要自动分配变量地址,你可以使用链接器脚本(Scatter File)来定义内存区域,不用手动指定地址。:

1. 创建或修改链接器脚本: 在你的项目中创建一个 .sct 文件(如果还没有的话)。例如,exit.sct
2.在链接器脚本中定义内存区域:
LR_IROM1 0x08000000 0x00080000 { ; load region size_region
ER_IROM1 0x08000000 0x00080000 { ; load address = execution address
*.o (RESET, +First)
*(InRoot$$Sections)
.ANY (+RO)
}
RW_IRAM1 0x20000000 UNINIT 0x00000100 { ;no init section
*(NoInit)
}
RW_IRAM2 0x20000100 0x0000FFF0 { ;all other rw data
.ANY(+RW +ZI)
}
}
3.修改变量声明: 将 __no_init 变量放在一个特定的段中:

使用 Arm Compiler 5 时,请将 zero_init 属性添加到变量中,以防止优化。这会将变量保留为不会初始化的 ZI 数据。

使用 Arm 编译器 6 时,将部分名称“NoInit”重命名为“.bss”。NoInit“的这会在 ZI 节中创建变量,从而阻止初始化。

// Arm Compiler 5
unsigned long NI_longVar __attribute__( ( section( "NoInit"),zero_init) ) ;

// Arm Compiler 6
unsigned long NI_longVar __attribute__( ( section( ".bss.NoInit")) ) ;
//also modify one line of the scatterfile from:
// *(NoInit)
//to:
// *(.bss.NoInit)

也可以使用我如下这种定义,方便快捷

#define __no_init __attribute__( ( section( "NoInit"),zero_init) )
__no_init uint8_t g_noInitTest ;

4.在 MDK 项目设置中:
转到 “Project” -> “Options for Target” -> “Linker” 标签
在 “Scatter File” 字段中,选择你创建的 .sct 文件

这样,链接器会自动将 g_isSoftRst  变量放置在 NO_INIT 区域,而不需要手动指定地址。

注意:确保 NO_INIT 区域的大小足够容纳所有 __no_init 变量。你可以根据需要调整其大小和起始地址。 通过这种方法,你可以让链接器自动管理内存分配,同时仍然保持 __no_init 变量的特性。这样做更灵活,也更容易维护,因为你不需要手动跟踪和分配地址。

 

 

参考资料:

ARM:初始化非初始变量

声明:本站所有文章,如无特殊说明或标注,均为本站原创发布。任何个人或组织,在未征得本站同意时,禁止复制、盗用、采集、发布本站内容到任何网站、书籍等各类媒体平台。如若本站内容侵犯了原著者的合法权益,可联系我们进行处理。