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.

[参考译文] TM4C129ENCPDT:被放置在堆栈上同一位置的局部变量覆盖而损坏的全局变量

Guru**** 2614265 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/774962/tm4c129encpdt-global-variables-corrupted-by-being-overwritten-by-local-variables-being-placed-in-same-location-on-the-stack

器件型号:TM4C129ENCPDT

我的 Tiva C Tm4c129有问题。  我知道全局变量被视为不良做法、但我正在移植代码、该代码目前在设备较少的 M3 Stellaris MCU 上正常工作。   

我查看了从 StellarisWare 迁移到 Tivaware 的文档。

我正在使用 GPIO、UART、SSI、SysTick 和 I2C 外设、没有任何问题、代码按预期运行。

我遇到的问题是变量被覆盖。  

一切似乎都正常、但在函数中、我发现函数局部数组使用已被全局变量占用的 RAM 位置。

无论我对堆栈大小进行何种更改、问题都仍然存在。  我进行其他更改以降低调用栈深度、它只是将问题移至新位置。

我从 IAR 7.5开始、现在将 IAR 8.32用于 ARM。  我尝试使用默认链接器文件、更改堆栈大小。  我使用了 Tiva 示例文件夹中的链接器和 startup_ewarm。

起初我遇到了 STTOK 问题。  我会调用它、在离开后、会发现文件全局变量的值与 strtok 分配给我的令牌指针的指针的值相同。

考虑到从 Stellaris 迁移、是否使用无符号整型等数据类型会导致问题?  我查看了映射文件、大小看起来正确。

还有哪些其他因素可能导致这种行为?  任何专家的建议都非常感谢!

谢谢你。

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

    您如何声明全局变量? 您是否对进行了任何优化? 全局变量是跨文件使用还是在 ISR 中使用?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我没有启用优化。  我遇到了在文件开头声明且仅在文件中使用的静态变量以及在文件开头声明并在文件之间使用的外部非静态变量的问题。

    我很奇怪的是、我有很多 RAM。  我使用的最后一个处理器具有32KB、这个处理器具有256KB。  我很确定堆栈不会扩展到数据区域。  在链接器中、我将 SRAM 的起始地址更改为 0x20010000。  存储器的覆盖方式完全相同、但全局变量位置偏移量为0x10000。  我在代码中进行更改、现在问题出在其他地方。

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

    我个人认为这不是 RAM 问题。

    您是否曾尝试将全局变量声明为易失性变量?

    如果在任何 ISR 中使用它们、对于确保正确更新和保留值而言非常重要。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我不熟悉 IAR 工具、但看起来堆栈是在文件"startup_ewarm.c"中创建的。 此文件的默认版本(在 project0中)的栈大小为64字(256字节)、位于".noinit"段中。  IAR 链接器是否会创建映射文件? 与堆栈位置相比、被破坏的全局变量的位置是什么? 堆栈起始地址(高地址)被编程到闪存的0x00000000位置。

    //
    //
    //为系统堆栈保留空间。
    ////
    *****************
    静态 uint32_t pui32stack[64]@".noinit";
    
    //*********
    //
    //描述向量表条目的联合体。 需要使用 union
    //、因为第一个条目是栈指针、而余数是函数
    //指针。
    ////
    *****************
    typedef union
    {
    void (* pfnHandler)(void);
    uint32_t ui32Ptr;
    }
    uVectorEntry;
    
    //*********
    //
    //矢量表。 请注意、必须在这个上放置适当的结构、以
    //确保它在物理地址0x0000.0000处结束。
    ////
    *****************
    __root const uVectorEntry __vector_table[]@".intvec"=
    {
    {.ui32Ptr =(uint32_t) pui32Stack + sizeof (pui32Stack)}、
    //初始堆栈指针
    ResetISR、 //重置处理程序
    NmiSR、 // NMI 处理程序
    

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    //
    //
    //应用程序启动代码的入口点。
    ////
    *****************
    extern void __IAR_program_start (void);
    
    //*********
    //
    //为系统堆栈保留空间。
    //(链接器保留空间,如 IDE 和.ICF 文件中指定)
    //
    *********
    #pragma SECTION ="CSTACK"
    
    //*********
    //
    //描述向量表条目的联合体。 需要使用 union
    //、因为第一个条目是栈指针、而余数是函数
    //指针。
    ////
    *****************
    typedef union
    {
    void (* pfnHandler)(void);
    void*__ptr;
    }
    uVectorEntry;
    
    //*********
    //
    //矢量表。 请注意、必须在这个上放置适当的结构、以
    //确保它在物理地址0x0000.0000处结束。
    ////
    *****************
    __root const uVectorEntry __vector_table[]@".intvec"=
    {
    .__ptr =__SFE ("CSTACK")}, //初始堆栈指针
    _IAR_program_start、 //重置处理程序 

    非常感谢!  这就是问题所在。  已设置 Stellaris 的原始项目、请使用链接器文件设置 RAM。  我将 startup_ewarm.c 更改为使用链接器。