有人知道如何处理以下问题:
我有一个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中。)
答案 0 :(得分:4)
您可以通过使用pragma
预处理程序指令来指定变量和函数的位置。您需要使用其中一个预定义的部分或定义自己的部分。
您没有提到您正在使用的IAR的特定风味。以下内容来自Renesas IAR Compiler Reference Guide,但您应该查看正确的参考指南,以确保语法完全相同,并了解预定义的部分。
使用
@
运算符或#pragma
位置指令进行放置 命名段中的函数组或全局和静态变量, 没有明确控制每个对象。变量必须是 声明为__no_init
或const
。细分可以,为 例如,放置在特定的内存区域,或初始化或 使用段开始和结束运算符以受控方式复制。 如果您需要单独的接口,这也很有用 链接单元,例如应用程序项目和引导加载程序 项目。在对展示位置进行绝对控制时使用命名细分 个别变量不需要或无用。在命名段中放置函数的示例
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 };
实际的名称,地址和大小会有所不同,但看起来应该相似。我只使用datasheet中前两个动态内存区域的全部大小。这里发生的是你为不同类型的内存(即SD卡和SDRAM)分配地址空间的名称,以便编译期间命名的部分将被链接器放置在正确的位置。
首先,您必须使用define memory
定义地址空间:
可能的可寻址存储器的最大尺寸
define memory
指令定义了给定大小的内存空间, 这是可寻址内存的最大可能量,而不是 必然是物理上可用的。
然后告诉它哪些芯片与define region
:
可用物理内存
define region
指令定义可用内存中的区域 其中应用程序代码和部分的特定部分 可以放置申请数据。
接下来,链接器需要知道将region
与section
放在一起的place 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();
}
为了在多个不同的内存设备之间自定义启动初始化,您需要非常仔细地研究IAR Development Guide for ARM。还可以尝试启用--log initialization
选项并研究日志和地图文件,以确保获得所需内容。