3

有谁知道如何处理以下问题:
我有一个 IAR Embedded 工作台。该项目也使用 SDRAM 来运行它的代码和 Flash 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 };

然后 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"));
}

但是,我不明白,首先,MYSECTION_init 和 MYSECTION 之间有什么区别。另外,如果我有一个全局变量:

SomeClass myclass;

而且它应该放在SDRAM中,那么它的初始化是怎么做的呢?我想手动初始化变量,并将初始化函数放入闪存 ROM。(问题是通过将变量放置到 SDRAM 中,它的初始化函数也放置到了 SDRAM 中)。

4

1 回答 1

4

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

您没有提及您正在使用的 IAR 的特定风格。以下内容来自Renesas IAR 编译器参考指南,但您应该查看正确的参考指南以确保语法完全相同并了解预定义部分是什么。

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

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

void f(void) @ "FUNCTIONS";

void g(void) @ "FUNCTIONS"
{
}

#pragma location="FUNCTIONS"
void h(void);

要覆盖默认段分配,您可以显式指定除默认值之外的内存属性:

__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 };

实际名称、地址和大小会有所不同,但应该看起来相似。我只是使用数据表中前两个动态内存区域的完整大小。这里发生的是您为不同类型的内存(即您的 SD 卡和 SDRAM)分配名称到地址空间,以便在编译期间命名的部分将由链接器放置在正确的位置。

所以首先你必须定义地址空间define memory

可能的可寻址存储器的最大大小

define memory指令定义了具有给定大小的内存空间,这是可寻址内存的最大可能数量,不一定是物理可用的。

然后告诉它哪些芯片去哪里define region

可用物理内存

define region指令在可用存储器中定义了一个区域,其中可以放置应用程序代码的特定部分和应用程序数据的部分。

接下来,链接器需要知道region将命名section的内容放在什么位置place in

在区域中放置部分

place at和指令将place into具有相似属性的部分集合放入先前定义的区域中。

并告诉链接器您想要覆盖它的部分初始化initialize manually

初始化应用程序

指令initializedo 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();
}

为了在多个不同的内存设备之间自定义启动初始化,您需要非常仔细地学习IAR Development Guide for ARM 。还可以尝试打开该--log initialization选项并研究日志和地图文件,以确保您得到您想要的。

于 2012-12-07T12:47:35.013 回答