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.

[参考译文] RM46L850:启动代码不调用全局 C++构造函数

Guru**** 657930 points
Other Parts Discussed in Thread: HALCOGEN, TMS570LC4357, RM46L850, LAUNCHXL2-RM46
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors

器件型号:RM46L850
主题中讨论的其他器件:HALCOGENTMS570LC4357LAUNCHXL2-RM46

我正在使用 HALCoGen 生成的启动代码和链接器文件。 我正在使用 gcc 格式输出。

在 C++中、如果我有一个实例化全局的类、则永远不会调用构造函数。  

静态 MyClass myClassObj;

我从未在构造函数中遇到断点,也没有设置成员变量。  

我使用 了覆盖构造函数部分中此处概述的一些代码。

https://mcuoneclipse.com/2014/12/26/code-coverage-for-embedded-target-with-eclipse-gcc-and-gcov/

链接器文件已输出.init_array 所需的只是执行此函数。

/* call the coverage initializers if not done by startup code */
voidstatic_init(void) {
  void(**p)(void);
  externuint32_t__init_array_start, __init_array_end; /* linker defined symbols, array of function pointers */
  uint32_tbeg = (uint32_t)&__init_array_start;
  uint32_tend = (uint32_t)&__init_array_end;
 
  while(beg<end) {
    p = (void(**)(void))beg; /* get function pointer */
    (*p)(); /* call constructor */
    beg += sizeof(p); /* next pointer */
  }
}
Is the constructor execution supposed to happen automatically in TI code? In the past I've used HALCoGen and I don't recall needing to do this. 



  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="488537" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors "]

    我正在使用 HALCoGen 生成的启动代码和链接器文件。 我正在使用 gcc 格式输出。

    在 C++中、如果我有一个实例化全局的类、则永远不会调用构造函数。  

    [/报价]

    我发现、对于 HALCoGen 为 GCC 和 TMS570LC4357创建的 hl_sys_startup.c、问题在于 HALCoGen 启动代码直接调用 main()、而不是调用 _start()。 其中 _start()是  newlib 入口点,它将在调用 main 之前调用全局构造函数(在启动操作之间)。

    hl_sys_startup.c 来自一个示例项目、其中代码被插入 到_c_int00 ()函数中的 HALCoGen 用户代码块中来调用_start()并调用全局构造函数。 有一些注释描述了确保_start()设置正确的栈指针所必需的其他项目更改。

    我认为我之前没有向 TI 报告过此问题。

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

    谢谢切斯特  

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

    感谢切斯特的解释和链接。 我遵循了该项目中的所有代码、而我的 newlib _start()函数会在指令"ldmdb R3、{sp}^"处引起_dabort 调用。  

    QJ Wang、TI 是否打算解决此问题? 无论使用"GCC 工具"还是"Texas Instruments "、我都希望输出相同。

    有什么关于我的 newlib 出现故障的原因以及如何修复的想法?  

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

    您好、Michael、

    我们没有更新 HALCOGen 驱动程序的计划、但我会将绕车介绍添加到新的 HAL 发行说明中。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="488537" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors/3782787 #3782787">是否有任何关于我的 newlib 出现故障的原因以及如何修复的想法?  [/报价]

    根据导致 dabort 的指令、可能无法正确设置栈指针。

    您使用的是哪个版本的 GCC?

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

    我使用的是版本  
    GCC 版本6.3.1 20170620 (15:6.3.1+svn253039-1build1)

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="488537" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors/3783294 #3783294)]我正在使用版本  
    GCC 6.3.1 20170620 (15:6.3.1+svn253039-1build1)[/quot]

    已使用 CCS 10.4.0.00006随 HALCoGen v04.07.01一起安装的 gcc-arm-none-eabi-6-2017-Q1-update 为 RM46L850设置了附加项目。

    CCS 安装的 GCC 将其版本报告为"gcc version 6.3.1 20170215 (release)[ARM/embedded-6分支修订版本245512]"、因此 newlib 中可能存在一些差异。

    https://github.com/Chester-Gillon/E2E_example_projects/commit/4437dc6e2b0d589acceb9e1647b4fe132baf34e6 是提交函 数,它将_c_int00()启动函数更改为调用 newlib _start()函数,而不是直接调用 main(),因此显示了上下文中的修改。 除了更改_c_int00()函数、还必须修改链接器脚本以设置 _start()将栈指针设置为的__stack 符号。

    当在 LAUNCHXL2-RM46上运行时、会在串行控制台上产生以下输出:

    C++ test
    global_instance.initialised=0xfeedabba
    stack_instance.initialised=0xfeedabba
    sqrtf(123.45)=11.1108
    sqrt(123.456789)=11.11111106055556
    Division by Zero.

     为 global_instance.initialized 报告的非零值显示调用了全局构造函数。

    如果这些更改仍然存在问题,您能否告诉我下载"gcc version 6.3.1 20170620"的位置,并可能发布链接器映射,因为可能需要进行其他更改才能正确调用_start()。

    e2e.ti.com/.../RM46L850_5F00_GCC_5F00_halcogen_5F00_cpp.zip

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

    你(们)好。 感谢您花时间制作示例项目并对其进行测试。 我在电路板上记录了您的所有更改、并遇到了相同的问题。 关于我的 gcc 版本、我认为它可以在此处下载。  packages.ubuntu.com/.../gcc-arm-none-eabi

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="488537" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors/3788713 #3788713"]关于我的 gcc 版本、我认为可以在此处下载。  packages.ubuntu.com/.../gcc-arm-none-eabi

    好的、我使用以下命令在 Ubuntu 上安装了该版本:

    sudo apt install gcc-arm-none-eabi

    CCS C/C++ General -> Preprocessor include paths -> entries -> TI GNU C++-> CCS Built-In Compiler Settings 具有__version__="6.3.1 20170620"  

    在 CCS 10.4项目中选择了该编译器并进行了重新构建。

    CCS C/C++ General -> Preprocessor include paths -> entries -> TI GNU C++-> CCS Built-In Compiler Settings 具有__version__="6.3.1 20170620"  

    链接器映射文件确认正在使用 Ubuntu 已安装软件包中的库:

    .text 0x0000000000e4 0x68 /usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/lib/thumb/v7-ar/fpv3/hard/crt0.o
    0x0000000000e4 _start
    0x0000000000e4 _mainCRTStartup

    即确认已选择正确的编译器。

    C++测试项目仍成功运行、输出指示全局 C++构造函数已调用:

    C++ test
    global_instance.initialised=0xfeedabba
    stack_instance.initialised=0xfeedabba
    sqrtf(123.45)=11.1108
    sqrt(123.456789)=11.11111106055556
    Division by Zero.

    即不能重复您的失败。

    您是否能够发布不起作用的项目?

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

    谢谢切斯特。 你这么快! 我感谢他们的支持。

    我无法发布项目。 我对 USB 堆栈进行了相同的更改、下面是一些与更改相关的详细信息。


    SYS_LINK_ld

    __stack = 0x08001900;

    SYS_CORE.s

    userSp:  .word 0x08000000+0x00001900
    svcSp:   .word 0x08000000+0x00001900+0x00000100
    fiqSp:   .word 0x08000000+0x00001900+0x00000100+0x00000100
    irqSp:   .word 0x08000000+0x00001900+0x00000100+0x00000100+0x00000100
    abortSp: .word 0x08000000+0x00001900+0x00000100+0x00000100+0x00000100+0x00000100
    undefSp: .word 0x08000000+0x00001900+0x00000100+0x00000100+0x00000100+0x00000100+0x00000100

    SYS_STARTUP.c 条目(与您的代码相同)

        register int *sp asm("sp");
        if (__stack != sp)
        {
            for(;;)
            {
            }
        }
    
        /* Call the newlib entry point, which will call global constructors (amongst start-up actions), before calling main */
        _start();
    
        /* In case _start() returns */
        exit(0);

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="488537" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors/3788859 #3788859"]我对 USB 堆栈进行了相同的更改,下面是一些与更改相关的详细信息。

    我更改了 C++测试程序中的用户堆栈大小以匹配您的值、以防在 newlib 中假设的堆栈对齐出现问题、但仍然无法重复该故障。

    我将尝试启用覆盖、因为这是您在原始帖子中提到的内容。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="91588" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors/3789014 #3789014"]我将尝试启用覆盖,因为这是您在原始帖子中提到的内容。

    我通过 -fprofile-c弧-FTEST-Coverage 选项启用了覆盖。 没有进行更改以保存覆盖数据、但确实:

    a.请参阅编译器 gcov 构造函数,了解从_start()调用的源文件

    b:在内存浏览器中、_gcov0.main 计数随着步进代码而改变

    即仍然无法重新创建导致数据中止的_start()问题。

    尽管它可能与您的失败无关、但在示例链接器脚本中、以下内容允许 C++异常正常工作、而不会导致崩溃:

    /* Work-around the issue where the HALCoGen generated sys_link.ld places the read-only .ARM.extab section in RAM rather than FLASH.
       Placed in a separate linker script due to sys_link.ld not containing any USER CODE blocks to preserve changes.
       For this to work relies upon this linker script being passed to the linker after sys_link.ld by CCS.
    
       The following thread was raised to report the issue:
       e2e.ti.com/.../halcogen-halcogen-04-07-01-hl_sys_link-ld-gcc-linker-script-places-read-only-section-arm-extab-section-in-ram-not-flash
    */
    SECTIONS
    {
       .ARM.extab   : { *(.ARM.extab* .gnu.linkonce.armextab.*) } >FLASH
    }
    

    [报价 userid="488537" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors/3788859 #3788859"]我无法发布项目[/quot]

    您能否仅发布链接器映射文件、因为这可能提供线索。 例如、如果某些段未按照我在 C++异常所需的.arm.extab 段中找到的那样正确放置。

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

    我再看一下您的示例项目和这个线程。 我注意到、您在上面说:

    [引用 userid="91588" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1023130/rm46l850-startup-codes-not-call-global-c-constructors/3788777 #3788777"]。text 0x0000000000e4 0x68 /usr/lib/gcc/arm-none-eabi/6.3.1/../../../arm-none-eabi/lib/thumb/v7-ar/fpv3/hard/crt0.o
    0x0000000000e4 _start

    我的映射文件位于不同的地址、即128个左右。 我再看一下您的示例项目、发现编译器标志和链接库存在一些差异。 我在中添加了这些内容、我不确定其中哪一个修复了它、但它现在可以正常工作。  

    我在中添加的是  

    additional flags for compiler/linker:
    -mfloat-abi=hard
    -mcpu=cortex-r4
    
    and linked to libs:
    c
    stdc++

    感谢所有的帮助!