有谁知道如何处理以下问题:
我有一个 IAR 嵌入式工作台。该项目也使用 SDRAM 和闪存 ROM 来运行其代码。SDRAM 的代码是从 SD 卡加载的。然而,在SDRAM中还存储了一些数据,例如全局变量或静态变量。其中一些必须初始化。初始化步骤,即iar_data_init3函数调用,在函数之后进行low_level_init。所以问题是,为了初始化 SDRAM 中的某些变量,需要从 调用初始化函数iar_data_init3,其代码位于 SDRAM 本身内部。这是错误的,因为尚未完成从 SD 卡加载 SDRAM 代码的操作。
我已尝试按照 C/C++ 开发指南中所述进行手动初始化,但这没有帮助。
调用的函数是__sti__routine,它提供变量的初始化。所有这些函数都是由 IAR 生成的。有什么方法可以告诉链接器将初始化函数放入Flash ROM中吗?
编辑 1: 这是来自 IAR C/C++ 手册的信息。这是如何使用手动初始化的示例。
在链接器配置文件中:
initialize manually { section MYSECTION };
Run Code Online (Sandbox Code Playgroud)
然后 IAR 文档说:
您可以使用此源代码示例来初始化该部分:
#pragma section = "MYSECTION"
#pragma section = "MYSECTION_init"
void DoInit()
{
char * from = __section_begin("MYSECTION_init");
char * to = __section_begin("MYSECTION");
memcpy(to, from, __section_size("MYSECTION"));
}
Run Code Online (Sandbox Code Playgroud)
然而,我无法理解,首先,MYSECTION_init 和 MYSECTION 之间有什么区别。另外,如果我有一个全局变量:
SomeClass myclass;
Run Code Online (Sandbox Code Playgroud)
而且它应该放在SDRAM中,那么它是如何进行初始化的呢?我想手动初始化变量,并将初始化函数放置到闪存中。(问题是,通过将变量放置到 SDRAM,它的初始化函数也被放置到 SDRAM)。
您可以通过使用指定变量和函数的位置pragma预处理器指令来指定变量和函数的位置。您将需要使用预定义部分之一或定义您自己的部分。
你没有提到你正在使用的 IAR 的具体风格。以下内容来自《Renesas IAR 编译器参考指南》,但您应该检查正确的参考指南,以确保语法完全相同并了解预定义部分的内容。
使用
@运算符或#pragma位置指令将函数组或全局变量和静态变量放置在命名段中,而无需对每个对象进行显式控制。变量必须声明为__no_init或const。例如,可以将段放置在内存的特定区域中,或者使用段开始和结束运算符以受控方式进行初始化或复制。如果您想要单独链接的单元(例如应用程序项目和引导加载程序项目)之间的接口,这也很有用。当不需要对单个变量的放置进行绝对控制或没有用时,请使用命名段。将函数放置在命名段中的示例
Run Code Online (Sandbox Code Playgroud)void f(void) @ "FUNCTIONS"; void g(void) @ "FUNCTIONS" { } #pragma location="FUNCTIONS" void h(void);要覆盖默认的段分配,您可以显式指定默认值以外的内存属性:
Run Code Online (Sandbox Code Playgroud)__code32 void f(void) @ "FUNCTIONS";
根据您的评论,您应该有一个名为generic_cortex.icf定义内存区域的链接器文件。其中应该有类似于以下内容的说明:
/* Define the addressable memory */
define memory Mem with size = 4G;
/* Define a region named SDCARD with start address 0xA0000000 and to be 256 Mbytes large */
define region SDCARD = Mem:[from 0xA0000000 size 0xFFFFFFF ];
/* Define a region named SDRAM with start address 0xB0000000 and to be 256 Mbytes large */
define region SDRAM = Mem:[from 0xB0000000 size 0xFFFFFFF ];
/* Place sections named MyCardStuff in the SDCARD region */
place in SDCARD {section MyCardStuff };
/* Place sections named MyRAMStuff in the SDRAM region */
place in SDRAM {section MyRAMStuff };
/* Override default copy initialization for named section */
initialize manually { section MyRAMStuff };
Run Code Online (Sandbox Code Playgroud)
实际的名称、地址和大小会有所不同,但看起来应该相似。我只是使用数据表中前两个动态内存区域的完整大小。这里发生的情况是,您正在为不同类型的内存(即 SD 卡和 SDRAM)的地址空间分配名称,以便链接器将在编译期间命名的部分放置在正确的位置。
因此,首先您必须使用以下命令定义地址空间define memory:
可能的可寻址存储器的最大大小
该
define memory指令定义了一个给定大小的内存空间,这是可寻址内存的最大可能数量,不一定是物理上可用的。
然后告诉它哪些芯片去哪里define region:
可用物理内存
该
define region指令定义了可用存储器中的一个区域,可以在其中放置应用程序代码的特定部分和应用程序数据的部分。
接下来链接器需要知道在什么地方放置region命名:sectionplace in
将部分放置在区域中
和指令
place at将place into具有相似属性的节集放置到先前定义的区域中。
并告诉链接器您要使用以下命令覆盖其初始化的一部分initialize manually:
初始化应用程序
指令
initialize并do not initialize控制应用程序应如何启动。使用这些指令,应用程序可以在启动时初始化全局符号,并复制代码片段。
最后,在您的 C 文件中,告诉编译器什么内容进入哪些节以及如何初始化声明的节manually。
SomeClass myClass @ "MyCardStuff";
#pragma section = "MyCardStuff"
#pragma section = "MySDRAMStuff"
void DoInit()
{
/* Copy your code and variables from your SD Card into SDRAM */
char * from = __section_begin("MyCardStuff");
char * to = __section_begin("MySDRAMStuff");
memcpy(to, from, __section_size("MySDRAMStuff"));
/* Initialize your variables */
myClass.init();
}
Run Code Online (Sandbox Code Playgroud)
为了在多个不同的存储设备之间自定义启动初始化,您需要仔细研究ARM 的 IAR 开发指南。还可以尝试打开该--log initialization选项并研究日志和地图文件,以确保您获得所需的结果。