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.

[参考译文] 编译器/TMS320F2.8075万:C2000连接器:链接器生成的符号和放大器;节放置-如何将代码长度输入到代码中?

Guru**** 2540720 points
Other Parts Discussed in Thread: CONTROLSUITE

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/575994/compiler-tms320f28075-c2000-linker-linker-generated-symbols-section-placement---how-to-get-the-code-length-into-the-code

部件号:TMS320F2.8075万
主题:controlSUITE中讨论的其他部件

工具/软件:TI C/C++编译器

您好,

我不知道链接程序生成的代码的长度,即进入闪存的所有部分的长度如何能够被“编译”(即由链接程序计算)到生成的代码中。 我尝试了几种方法:

方法1:

链接程序命令文件:

内存{

...

   FLASHE00   :原点= 0x8.8万,
                 长度= FIRMHEAD_SECTSIZE           /*固件标题 */
   FLASHE2J   :原点= 0x8.8万 + FIRMHEAD_SECTIZE,
                 长度= 0x3万 - FIRMHEAD_SECTSZE /* firmware */

}

章节

   /*片上闪存扇区中的固件部分*/
   firmware_header:load_size (_firmhead_size),fill = 0xFFFF
       {
       _firmware_start =.;
       firmware_header(.firmware_header)
       }
       > FLASHE00 页面= 0,对齐(4)

   /*将所有其他Flash部分组合在一起*/
   固件组load_size (_firmware_size){
   codegstart      ://page =0,对齐(4)
   .text          ://page = 0,align(4)
   ramfuncs       :// load = FLASHE2J,
                     RUN = RAMLS0 | RAMLS1 | RAMLS2 |RAMLS3,
                     load_start(_RamfuncsLoadStart),
                     load_size (_RamfuncsLoadSize),
                     load_end (_RamfuncsLoadEnd),
                     run_start(_RamfuncsRunStart),
                     Run_Size (_RamfuncsRunSize),
                     Run_End(_RamfuncsRunEnd)(运行结束(_RamfuncsRunEnd))
                     //page = 0,对齐(4)
   /*初始化的部分进入flash */
   .cinit         ://page = 0,对齐(4)
   .Pinit         ://page = 0,对齐(4)
   econst        ://page =0,align(4)
   .switch        ://page = 0,align(4)

   /*片上闪存中的固件部分结束*/
   firmware_end  :{
       _firmware_end =;
   }
   }> FLASHE2J   page =0,align(4),

}

C文件:

/*将firmware_header放在.firmware_header */部分
#pragma data_section (firmware_header,".firmware_header")

由链接程序命令文件*/定义的/*符号
extern UINT32_t   firmware_start,firmware_size;
外部 UINT32_t   firmware_end;

struct firmware_header firmware_header ={

(UINT32_t)&firmware_size + FIRMHEAD_SECTIZE,

...

};

这会成功编译和链接(使用正确的长度编译),但会发出警告

警告#1.0082万-D:放置被忽略
  对于"ramfuncs": 对象作为"Group_1"的一部分放置

将生成RAMfuns RUN部分并将其置于FLASH (错误!)。

方法2:

在命令文件中没有Group,我试图将.firmware_end部分放在所有内容的末尾(见上文),并使用符号的差异作为长度。

这会导致编译错误

   //(UINT32_t)(&firmware_end -&firmware_start),//错误#28:表达式必须具有常量值

并且不确定是否确实将.firmware_end放在了末尾,因为(SPRU513L):

8.5 .........................5 sections指令

(请注意,内存放置顺序不仅仅是顺序
sections出现在sections指令中。)

其他试验会产生其他错误:

   //(UINT32_t)&firmware_size + FIRMHEAD_SECTIZE)* 2,//错误#28:表达式必须具有常量值
   //(UINT32_t)(&firmware_size +&firmhead_size),//错误#31:表达式必须具有积分类型

任何提示

如何获得编译的长度(多个部分长度的总和)?

-如何控制各部分的顺序(.firmhead作为第一个,.firmware_end作为最后一个)? (高不是解决方案。)

谢谢!

弗兰克

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    稍后编辑... 该员额提出的建议最终未能解决问题。  使用前请阅读整个线程。

    fmdhr 说:
    我想知道链接器生成的代码的长度(即进入闪存的所有部分的长度)如何"编译"(即由链接器计算)到生成的代码中。

    这是我第一次推荐这种特殊技巧。  虽然我非常有信心它能解决您的问题,但我必须承认我可能忽略了一些事情。

    此解决方案的一个核心概念.. 它不知道这些部分在内存中的位置。  它只会累加您指定的区域的大小。  

    下面列出了一些注意事项和限制。  请不要忽略它们。

    在链接程序命令文件中,捕获所有相关部分的大小...

    节
    {
    .text > flash,size (text_size)
    .cinit > flash,size (cinit_size)
    .Pinit > flash,size (Pinit_size)
    /*...等等*/
    } 

    在sections指令后面的一个语句中,将所有这些大小相加并分配给另一个符号...

    _total_size = text_size + cinit_size + Pinit_size; 

    在C或C++代码中,可以引用符号total_size (没有前导下划线)。  有关执行此操作的详细信息  ,请参阅C2000组装工具手册中标题为在C/C++应用程序中使用链接器符号一节

    注意事项和限制

    当使用分段拆分(由操作员>>发出信号)时,此功能不起作用。  例如...

    .text >> FLASH1 | FLASH2,Size (text_size)// silent failure!!! 

    在这种情况下,链接器不计算节大小。  它静默地将值0xffffffff赋给符号text_size,并将其添加到_total_size中。

    如果截面之间存在任何缝隙,则忽略这些缝隙的大小。  因此,此技术与计算大小= end_address - start_address不同。

    C2000工具使用较旧的COFF ABI,而不是较新的EABI。  在COFF ABI下,C或C++中的全局符号在汇编中用前导下划线表示。  因此,C中的total_size在装配体中变为_total_size。  在这种情况下,方向是相反。  _total_size在链接器命令文件中创建,并在C中用作total_size。 如果您在EABI下使用此技术,则可以使用支持EABI的C2000工具,也可以使用支持EABI的其它TI工具集,则只需在整个过程中将符号写入total_size。  忘记前导下划线。

    谢谢,此致,

    -George

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,George,

    感谢您的Profund回复。 我按照您的建议执行了操作,我得到了由链接程序计算并编译的代码大小。 很好。

    但是,我感到非常惊讶-这是错误的。 此外,.map文件也错误。 在我的示例中,我得到的大小为0xecf + 0x20 = 0xeef (结束地址0x88eef),但在0x88ef0处闪存了代码。 请参阅下面.map文件中的代码片段和代码转储。

    我还可以用controlSUITE的标准示例再现奇怪的结果,另请参见下文。

    这让我很好奇...

    此致,

    弗兰克

    *.cmd

       _firmware_size = FIRMHEAD_SECTSZE + codegot_size + text_size +
       ramfuncs_size + cinit_size + Pinit_size + econst_size + switch_size;

    *。map
            名称           使用的原点   长度         未使用  的属性   填充
    ----------------  -----------------  -------------------  -----------------  -----------------  --------  
     FLASHE0.088万             0008800万  0000002万 0000.0014万 0000000c RWIX
     FLASHE2J             8.802万  0002ffe0 00000ecf000000ecf 0002f111 RWIX

    ...

    .cinit    000088   00088ed40000001   a     
                     0.0088万ed4   0000000e40000000e    rts2800_fpu32.lib:exit.obj (.cinit)
                     0.0088万ee2   00000005200000005                      :_lock.obj (.cinit:__lock)
                     0.0088万ee7   00000005700000005                      :_lock.obj (.cinit:__unlock)
                     0.0088万eec   0.0002万    --孔--[填充=0]

    代码启动
    *         000088   00088ef000000002        
                     0.0088万ef0   00000002000000002    F2807x_CodeStartBranch.obj (代码启动)

    ...
    000088    ccc __etext__                            
    0.0088万ccc     图文                                 
    000088    e8c _big_data                             
    0.0088万e9c     _RamfuncsLoadStart                    
    0.0088万ed3     _RamfuncsLoadEnd                      
    000088    ed4 __cinit__                            
    000088    ed4 cinit                                 
    000088    ef0 cod_start                            
    ...
    ABS  0万 Pinit_size                            
    abs  0万 switch_size                           
    ABS  0.0002万 代码start_size                        
    abs  0.0001万a cinit_size                            
    abs  0.0037万 _RamfuncsLoadSize                     
    abs  0.0037万 _RamfuncsRunSize                      
    abs  0.0037万 ramfuncs_size                         
    ABS  0.01万 __stack_size                          
    ABS  0.0001万d0 econst_size                           
    abs  0万cac text_size                             
    abs  0万eef _firmware_size                        


    转储闪存代码:

    0x0.0088万EE0   000000000      FFFE   A81E   0000   8CC00008      FFFE   A82万   0   8CC00008      0000      FFFF   FFFF
    0x0.0088万EF0   004800048   8CC1   FFFF   FFFF FFFF         FFFF    FFFF   FFFF   FFFF   FFFF FFFF       FFFF   FFFF   FFFF   FFFF
    0x0.0088万F00   FFFF   FFFF      FFFF   FFFF    FFFF   FFFF   FFFF   FFFF FFFF       FFFF   FFFF   FFFF   FFFF FFFF       FFFF


    C:\ti\controlSUITE\DEVICE_SUPPORT\F2807x\v190\F2807x_Examples_CPU1\CPU_timers\cpu01</s>2807

    CPU1快擦写配置.map和内存转储:

     FLASHA               8.0002万  00001ffe 0万 00001ffe RWIX
     FLASHB               0.082万00  000020000万02000 00000c940.2万 00000c94 0000136c0万 0000136c RWIX40000136 RWIX

                     0.0082万c8b   0.0008万    F2807x_CodeStartBranch.obj (.text)
                     0.0082万c93   000000029.3万00002    rts2800_fpu32.lib0.0002万 rts2800_fpu32.lib:2800:pre_init.obj (.text)
                     0.0082万c95   000000019.5万00001                      :0.0001万:STARTUP.OBJ (.text)

    000082    c8a __nop                                 
    000082    c93 __SYSTEM_PRE_INIT                     
    000082    c95 __system_post_cinit                   

    0x0.0082万C70   FFFF   0FAB   6004   BE00   D400   6F09   28AB   FFFF   28AA   FFFF   A9A4   88C40902      8AA9   92A67648    
    0x0.0082万C80   2ABF   0.6761万   F   02A0   A820   0.6761万   F   02A0   A81E   0006   0006   561F   7622   B9C02829      0068
    0x0.0082万C90   761A9.0761万A   0048   2B20   9A010006      0006   FFFF      FFFF   FFFF   FFFF FFFF    FFFF   FFFF   FFFF   FFFF FFFF    
    0x0.0082万CA0   FFFF   FFFF FFFF         FFFF FFFF    FFFF   FFFF   FFFF   FFFF FFFF       FFFF   FFFF   FFFF   FFFF FFFF       FFFF


  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您似乎是说大小运算符得到了错误的答案。  我不清楚你们是怎么知道的。  在“闪存代码转储”中,我是否应该假定最后一个值的地址不是FFFF是该部分的结束位置?  您如何知道闪存实用程序(或闪存的任何程序)是否正确?

    谢谢,此致,

    -George

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,George,

    我认为我找到了错误结果的原因:大小正确,大小总和正确,.map正确,闪存实用程序正确。 但是,不考虑对齐操作符产生的孔(是否应该考虑?)。 我换了

       .text          :> FLASHE2J       page = 0,align(4),size (text_size)

    使用

       .text          :> FLASHE2J       page = 0,align(1),size (text_size)

    并获得正确的结果。 但是,我认为,align(4)对于从闪存中快速解封代码(我记得之前读过一些东西...)是很好的,所以最好保留它。

    我可能会更准确地问我的问题:如何获取最后一个使用的单词的地址(以及不同的firmware_end - firmware_start!)? 这会让我回到我在第一篇文章中的第二个问题(分区排序,请参阅上文):如何将分区放在末尾?

    (背景:最终目标是从.out (通过十六进制工具)生成固件代码的C源代码,该代码链接到另一个处理器的固件,然后该处理器可以执行C2000的固件更新。)

    谢谢!

    弗兰克

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我的第一篇文章讲述了该解决方案如何忽略各部分之间的差距。 但我可以看出这一点很容易被忽视。  我建议放弃第一种解决办法。

    请尝试其他建议。  这是对 本帖子中出现内容的调整

    创建#define符号以确定闪存范围的基本地址。  定义闪存范围时使用该名称。  类似以下的东西...

    #define flash_base 0x3000 /*更改为正确的地址*/...
    
    内存
    {
    FLASH:origin = flash_base,length = 0x2000...
    
    } 

    选择闪存范围内的一个输出部分。  现在我将使用.cinit部分。  改变它,使它看起来像这样...

    .cinit > flash (高),end (end_of_flash) 

    然后创建您在C代码中引用的符号...

    _FLASH_SIZE = FLASH_of_FLASH - FLASH_BASE; 

    处理此符号就像我建议在第一篇文章中处理符号_total_size一样。

    我不知道有什么理由更喜欢闪存中的任何输出部分。  但如果有,这就是用于这种技术的方法。

    确保在闪存范围内仅使用一次高电压。

    谢谢,此致,

    -George

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    fmdhr 说:
    (背景:最终目标是从.out (通过十六进制工具)生成一个C固件代码源,该代码链接到另一个处理器的固件,然后该处理器可以执行C2000的固件更新。)

    cG_xml包中的脚本bootimage 的作用非常相似。

    谢谢,此致,

    -George

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,George,

    我的第一篇文章讲述了该解决方案如何忽略各部分之间的差距。 但我可以看出这一点很容易被忽视。 [/引述]

    我自豪地成为另一个负面示例,这是众所周知的事实:几分钟的仔细阅读可以节省实验室数十小时的研究时间...

    很遗憾,您的建议

    [引述用户="George mock"]

    .cinit > flash (高),end (end_of_flash) 

    [/引述]

    也不是我想要的,因为它计算内存部分的大小,而不是我的代码的大小(我在第一篇文章中提到过)。

    也感谢您在其他帖子中提供的链接,我会将其转发给负责这部分工作的同事,如果他可以使用它。 同时,我们有一个解决方案,它采用Hex工具输出,我们从末尾搜索到第一个非0xFF字,以检测尺寸。 不是很优雅和有问题,如果代码以0xFFFF结束,而不是闪存,最初就是0xFFFF。 所以我要求另一个更好,更简单的解决方案...

    谢谢,顺祝商祺

    弗兰克