IAR 初始化函数放置

max*_*mus 5 embedded iar

有谁知道如何处理以下问题:
我有一个 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)。

emb*_*yle 5

您可以通过使用指定变量和函数的位置pragma预处理器指令来指定变量和函数的位置。您将需要使用预定义部分之一或定义您自己的部分。

你没有提到你正在使用的 IAR 的具体风格。以下内容来自《Renesas IAR 编译器参考指南》,但您应该检查正确的参考指南,以确保语法完全相同并了解预定义部分的内容。

使用@运算符或#pragma位置指令将函数组或全局变量和静态变量放置在命名段中,而无需对每个对象进行显式控制。变量必须声明为__no_init或const。例如,可以将段放置在内存的特定区域中,或者使用段开始和结束运算符以受控方式进行初始化或复制。如果您想要单独链接的单元(例如应用程序项目和引导加载程序项目)之间的接口,这也很有用。当不需要对单个变量的放置进行绝对控制或没有用时,请使用命名段。

将函数放置在命名段中的示例

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";
Run Code Online (Sandbox Code Playgroud)

编辑

根据您的评论,您应该有一个名为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选项并研究日志和地图文件,以确保您获得所需的结果。