工具/软件:TI C/C++编译器
TI论坛社区您好,
我收到编译器警告,表示库调用"sprintf"是POWER不可恢复的,我应该将函数移到RAM中。
我在本论坛中找到的关于此主题的示例和链接指的是非图书馆,即"我自己的代码"。
如何将以下内容添加到获取参数并返回值的库调用中?
__attribute___((ramfunc)
void f (void){...}
谢谢!
Bob s
This thread has been locked.
If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.
工具/软件:TI C/C++编译器
TI论坛社区您好,
我收到编译器警告,表示库调用"sprintf"是POWER不可恢复的,我应该将函数移到RAM中。
我在本论坛中找到的关于此主题的示例和链接指的是非图书馆,即"我自己的代码"。
如何将以下内容添加到获取参数并返回值的库调用中?
__attribute___((ramfunc)
void f (void){...}
谢谢!
Bob s
以下两个链接均指MSP430的ULP Advisor,而不是MSP432。 但几乎所有信息都适用于这两种设备。
谢谢,此致,
-George
Robert Schaefer 说:将以下行添加到链接器命令文件
链接程序命令文件是项目中的另一个源文件。 它的名称类似于 msp432p401r.cmd。 这是您应该修改的文件。
有关链接程序命令文件的一般了解,请参阅Wiki文章 链接程序命令文件入门。
链接程序命令文件将包含类似于...的行。
#ifdef __TI_Compiler_version__
#if __TI_Compiler_version__>= 1500.9万
.TI.ramfunc :{} load=main, run=sRAM_code, table(BINIT)
#endif
#endif
IF行检查编译器版本符号是否可用,编译器版本是否大于或等于15.9 .0.LTS。 第3行创建名为.ti.ramfunc的输出部分。 它由名为.ti.ramfunc的所有输入部分组成。 这是编译器用于标记有ramfunc属性的函数的部分的名称。 它在主存储器范围内分配了用于加载的空间,并在SRAM_CODE存储器范围内分配了用于运行的空间。 在BINIT表中输入一个条目。 BINIT表由系统启动代码处理。 此处理将此输出部分从主位置复制到SRAM_CODE位置。
下一步是对该代码进行更改,以便出现类似这些行的内容...
.text:rts430-lib_printf:{ rts*.lib<*printf.obj>(.text)} load = flash_execute,run = RAM_execute
这第一个变化只是最终解决方案的中间步骤。 将.TI.ramfunc行更改为这些行...
.ti.ramfunc: { *(.ti.ramfunc) } load=main,run=SRAM_CODE,table (BINIIT)
这与以前完全相同。 行*(.TI.ramfunc)表示以.TI.ramfunc名收集所有输入部分。 此更改的目的是在语法中创建一个点,以便在其中添加库输入部分的条目。 看起来像这样...
.ti.ramfunc: { --library=RTS*.lib<*printf*.obj>(.text) *(.ti.ramfunc) } load=main,run=SRAM_CODE,table (BINIIT)
第3行是新增内容。 --library选项告诉链接程序输入文件不在当前目录中,而是在使用--include_path (或-i)选项列出的目录中。 语法RTS*.lib表示使用以RTS开头,以.lib结尾的任何输入文件。 查看链接程序映射文件以查看使用的RTS库。 您将看到类似 rtsv7R4_T_be_eabi.lib的内容。 语法<*printf*.obj>(.text)表示使用RTS库中具有名称printf的文件中名为.text的所有输入部分。 例如,sprintf.obj。
谢谢,此致,
-George
谢谢你。
我终于找到了链接程序命令文件。 因为我用一个示例项目的副本开始我的项目,它的名称是原始项目的名称-这与我现在的工作无关,所以它总是存在,我只是忽略了它,因为我不知道该文件是什么。
新问题,链接器在您给我的缺口上消失。
但是,由于我使用CCS两次,在Mac上的桌面上编译,然后在Windows框上重新编译以到达目标,因为只有Windows框可以与XDS200 JTAG调试器配合使用,
我有另一个.cmd文件可以查看。 在Windows框中,链接程序修改为:
#ifdef __TI_Compiler_version__
#if __TI_Compiler_version__>= 1500.9万
别名
{
SRAM_CODE (rwx):原始= 0x100万
SRAM_DATA (RW):原点= 0x2000万
}长度= 0x1万
#否则
/*提示:如果用户要使用ram功能,请注意SRAM_CODE */
/*和SRAM_DATA存储器区域重叠。 您需要采取措施分离*/
/* RAM中代码的数据。 这仅对早于15.09 .0.STS.*/的编译器版本有效
SRAM_CODE (rwx):原始= 0x100万,长度= 0x1万
SRAM_DATA (RW):原点= 0x2000万,长度= 0x1万
#endif
当我将以上行重新安装到Mac版本的CCS时,链接成功。 因此,下一步是添加:
.TI.ramfunc :{} load=main, run=SRAM_code, table(BINIT)
但是,我不知道在哪里添加该行。 我将其放在别名上方,链接步骤失败。 我将其放在“别名{"之后,链接步骤失败。 我将其放在端括号后},链接步骤失败。
我会提供一条错误消息,但错误消息会根据我在何处发表声明而发生变化。
接下来应该尝试什么?
我假定您的链接程序命令文件已经有一个类似于的行
.TI.ramfunc :{} load=main, run=SRAM_code, table(BINIT)
如果不是这样,那么使用我所描述的更改是没有意义的。
我为什么会这样想呢? 当您在CCS中启动新项目时,您需要指明您使用的是哪种设备。 根据此选择,将自动设置许多详细信息。 其中包括链接程序命令文件。 对于诸如MSP432之类的ARM设备,所有链接器命令文件都来自类似的目录...
C:\ti\ccsv7\css_base\arm\include
我检查了此目录,只找到了2个MSP432的链接器命令文件。 这两种方法都有相同的.TI.ramfunc线。 因此,我假定您的链接程序命令文件具有此行,并从该处开始工作。
此时,我不确定您有什么链接程序命令文件,或者应该如何更改它。 请将原始链接器命令文件附加到下一篇文章中。 添加文件扩展名.txt,否则论坛将拒绝它。
谢谢,此致,
-George
很抱歉回复太晚,由于某些原因,我在您回复后未收到电子邮件,上周被跟踪。
e2e.ti.com/.../uart_5F00_loopback_5F00_24mhz_5F00_brclk_5F00_ccs.txt
我建议的更改位于本文末尾附加的链接器命令文件中。 虽然我不能测试这些变化,但我非常有信心它能奏效。 主要错误是您在内存指令中有一个节规范。
一个更好的修复…… 您似乎从某些TI软件包中获得了此文件。 更新到该软件包的最新版本,并使用此处找到的链接程序命令文件。
谢谢,此致,
-George
binit输出部分包含一个复制表,处理该表的目的是将.ramfuncs输出部分从主存储器范围复制到SRAM_CODE存储器范围。 此诊断...
Robert Schaefer 说:警告#1.0247万-D:创建不带节规范的输出节".binit "
...意味着.binit在系统内存中分配,无需您的任何指导。 因此,它可能被错误地分配。
当我查看MSP432设备的类似链接器命令文件时,我看到此行...
二进制 :>主页
因此,请先尝试一下。
谢谢,此致,
-George
附加了链接程序指令文件。
映射文件中包含这些行...
.ti.ramfunc * 000008 00008c5万 0000.117万 运行ADDR = 100万 0.0008万c50 000000605万00060</s>0.006万 rtsv7M4_T_le_v4SPD16_eabi.lib:sprintf.obj (.text) 0.0008万cb0 00001110000001110 :_printfi.obj (.text)
这说明.TI.ramfunc输出部分从加载地址0x0.0008万c50开始,运行地址为0x100万。 它只有两个输入部分,即rtsv7M4_T_le_v4SPD16_eabi.lib中printf相关函数的.text输入部分。
您得到“没有匹配的部分”警告,因为链接程序命令文件中的此行...
*(.ti.ramfunc)
...对应于无输入部分。 不能使用选项--ramfunc进行构建,也不能将ramfunc属性应用于任何函数。 ARM编译器手册中介绍了这两种功能。 搜索ramfunc以查找详细信息。 如果您不打算将函数置于RAM中,则可以忽略该警告。
谢谢,此致,
-George
您好,George,
现在我比开始时更困惑。
让我从开始。
当我编译时,我收到警告:“Detected sprintf() operation(s)。 建议在运行期间或不使用时将它们移至RAM,因为它们需要处理/耗电。"
请假设我没有线索,即使 编译器手册中有一个解释,即我不理解如何将 手册说明映射到CCS按钮对按。
但是如果我可以在CCS工具 抽象功能的“属性”迷宫中的某个位置找到--ramfunc开关,那么所有库函数是否都将被移动到RAM中,并且我不需要向 链接器命令文件添加其他语句?
Bob s
您的总体目标是什么? 这将帮助我了解需要关注的方面。
ULP建议的总体目标是帮助您降低系统的功耗。 与闪存相比,它需要较少的电源来执行SRAM。 因此,将使用更多周期的函数放在SRAM中是有意义的。 如果您的系统调用sprintf,则可以合理地假定这需要大量的周期,因此将该例程置于SRAM中是有意义的。
我们讨论的大部分内容都涉及如何在SRAM中获取sprintf (和相关函数)的详细信息。 我怀疑您可能不知道下一部分。 Sprintf例程实际上在闪存中启动。 在系统启动期间,.binit部分中的信息用于将闪存复制到SRAM。 对于系统执行的其余部分,sprintf出现在SRAM中,就像它一直存在一样。
链接程序命令文件中排列此内容的行如下:
.TI.ramfunc :
{
--library=RTS*.lib<*printf*.obj>(.text)
*(.TI.ramfunc)
} load=main,run=SRAM_CODE,table (BINIT)
第1行将输出部分命名为.TI.ramfunc。 第3行说明将RTS库中文件的所有.text部分用作输入部分,文件名中包含printf。 更具体地说,这仅适用于代码实际调用的RTS库中的printf函数。 第4行表示包括任何名为.TI.ramfunc的输入部分。 稍后将介绍更多信息。 第5行说明要将此输出部分分配给主内存范围以进行加载,将此输出部分分配给SRAM_CODE内存范围以执行,并在BINIT复制表中放置一个条目。 BINIT复制表由启动代码自动处理,以将此输出部分从main复制到SRAM_CODE。 在这种特殊情况下,表条目具有.TI.ramfunc输出部分的加载地址,运行地址和长度。 BINIT表项的位置位于名为.binit的不同输出部分中。 虽然名称相似,相互关联,但请将其视为单独的内容。 BINIT是一个复制表,而.binit是包含它的输出部分。
更多信息在第4行... 您可能会感到困惑的是,输出部分名为.ti.ramfunc,还有一些名为.ti.ramfunc的输入部分。 可以重复使用这样的节名称。 事实上,这是很常见的。 即使名称相同,也不要失去输入部分和包含它们的输出部分之间的区别。
更多信息请在第4行... 你得到一个关于这条线的诊断"没有匹配的部分"。 您必须没有名为.TI.ramfunc的输入部分。 有两种方法可以获得名为.TI.ramfunc的输入部分。 如果使用选项--ramfunc进行构建,则每个函数都位于.ti.ramfunc输入部分中。 鉴于您的SRAM有限,这可能不是您想要的。 另一种方法是应用ramfunc函数属性。
__attribute___((ramfunc)
void function_name(void){/*
此处为代码*/
}
使用此方法,您可以选择哪些功能进入SRAM。 是否将您自己的任何功能实际置于SRAM中取决于您。 如果您决定否,则可以忽略"无匹配部分"警告。
谢谢,此致,
-George