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.

[参考译文] 编译器/TM4C1294NCPDT:使用code_section和run_start提供错误的地址

Guru**** 2553260 points
Other Parts Discussed in Thread: TM4C1294NCPDT

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

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/584084/compiler-tm4c1294ncpdt-using-code_section-and-run_start-giving-wrong-address

零件号:TM4C1294NCPDT

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

我喜欢使用pragma code_section在特定内存中设置一组函数

在源文件中,我使用了像这样的code_section pragma

#pragma code_section (initBuffer,"my_sect")
void initBuffer(void);

在链接程序cmd文件中,我创建了一个部分

 my_sect:  > flash,load_start (_RamfuncsLoadStart),load_end (_RamfuncsLoadEnd),run_start (_RamfuncsRunStart)

映射文件如下所示

my_sect   000000   f9c   0.0014万     
                 0万f9c   0.0014万    test_sm.obj (my_sect:initBuffer)

...

地址  名称                           
---------   ---

0万f9d initBuffer    

我现在的问题是,函数initBuffer()位于0xF9D,但变量_RamfuncsRunStart或甚至_RamfuncsLoadStart的地址为0xF9C。

如果我尝试像这样运行功能

UINT32_t _RamfuncsLoadStart;
UINT32_t _RamfuncsLoadEnd;
UINT32_t _RamfuncsRunStart;

typedef void (*fctCall)();
fctCall fCall;

extern void initBuffer(void);

void testFctCall(void){

fCall = initBuffer;//有效
fCall();

fCall =(fctCall)&_RamfuncsRunStart;//不起作用
fCall();
} 

将不起作用。

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

    My Problem now is the function initBuffer() is at address 0xF9D but variable _RamfuncsRunStart or even _RamfuncsLoadStart have the address 0xF9C。

    在arm-v7体系结构中,BX或BLX指令分支地址中最不重要的位设置目标状态。 如果分支地址位0为零,处理器将变为或保持布防状态。 如果分支地址位0是其中一个, 处理器将更改为Thumb状态或保持Thumb状态。

    实施 ARM-v7M架构的Cortex-M4仅支持Thumb状态,尝试进入ARM状态会导致使用故障-请参阅   Cortex-M4设备通用用户指南中的分支指令。

    因此, 当initBuffer函数放在 闪存中的地址0xF9C (位0为零)时,分支地址必须为地址 0xF9D (位0为一)。 这就是 为什么fCall =(fctCall)&_RamfuncsRunStart语句将导致 fCall()失败的原因。

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

    但为什么RamfuncsRunStart的地址是错误的?
    我能做些什么让它运行吗?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    但为什么RamfuncsRunStart的地址错误?[/QUOT] RamfuncsRunStart具有正确的地址,清除了位0,以提供代码必须复制到的起始地址。

    我是否可以执行某些操作来使其运行?[/QUOT]将 RamfuncsRunStart转换为函数指针时,您需要设置位零以确保使用Thumb模式。 例如:

    /*将目标地址的位设置为零,以确保使用Thumb模式*/
    fCall =(fctCall)(((size_t)&_RamfuncsRunStart)| 1);
    fCall(); 

    我附上 了一个TM4C1294NCPDT示例项目,其中演示了这一点,包括将 initBuffer函数从闪存复制到SRAM。

    e2e.ti.com/.../TM4C_5F00_code_5F00_section.zip

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

    是否可能在拇指模式下执行一个功能,而在ARM状态下执行另一个功能?
    我应该自行处理执行模式,还是可以对所有功能使用此变通办法?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    一个函数是否可能在Thumb模式下执行,另一个是否处于ARM状态?

    Cortex-M设备(如TM4C1294NCPDT )仅支持Thumb模式,因此不可能在ARM模式下执行函数。

    而基于Cortex-A的设备允许混合执行Thumb和ARM状态。

    我应该自行处理执行模式,还是可以对所有函数使用此变通办法?[/QUOT]正常使用情况是通过获取函数符号名称的地址来使用函数指针,例如语句 fCall = initBuffer;  其中,编译器和链接器处理地址的位零设置,以控制Thumb和ARM状态的选择。

    尝试使用fCall =(fctCall)&_RamfuncsRunStart;的原因是什么?

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

    感谢您清除这种行为。

    我的目的是要有一个包含函数(指针)的内存块,我可以很容易地迭代这些函数。

    但是我不想初始化数组,因为函数可以位于我项目的每个模块中。

    我不需要固定长度的数组,因为函数的数量可能会发生变化。

    我需要的是一个指针列表,如

    pInitBufferA.
    pInitBufferB
    ....
    pInitBufferL
    pInitBufferM
    等等

    并通过重复

    fCall =(fctCall)&_RamfuncsRunStart;
    fCall();
    fCall++;
    fCall(); 

    直至内存块结束

    我已经用类似的data_section

    #pragma data_section(pInitBuffer,"my_sect")
    void initBuffer(void);
    UINT32_t *pInitBuffer =(UINT32_t*)initBuffer; 

    但地图文件中的内存区域未初始化

    my_sect   20万   2000000万   0000万    未初始化

    当函数仍在项目中时。

    0.0004万ed initBuffer

    所以我的下一个路径是code_section,以这个问题结尾。

    在您的帮助下,我现在意识到我无法使用code_section this迭代此内存块。

    您是否有更多解决方案?

    我在另一个ARM项目(而不是TI项目)中看到了这种逻辑。 它也是通过data_section,但原始的ARM编译器完成的。

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

    切斯特-我明白了。

    我必须使用Retain pragma,否则编译器会删除指针pInitBuffer。

    非常感谢,您的解释对我深入了解此主题有很大帮助。


    #include <stdint.h> #include <string.h> char bufferA[20]; char bufferB[20]; typedef void (* fctCall)(); fctCall fCall; void initBufferA(void); #pragma retain(pInitBufferA) #pragma data_section(pInitBufferA,"my_sect") fctCall pInitBufferA = initBufferA; void initBufferB(void);#pragma retain(pInitBufferB) #****************************************data_section(pInitBufferB,"my_Bufferb; pragma = initBufferb; pragma ferb void initBufferA(void){ memset (bufferA, 0xee, sizeof (bufferA)); } void initBufferB(void){ Memset (bufferB,0x55,sizeof (bufferB)); }//****************************************************** UINT32_t _MySectLoadStart; UINT32_t _MySectLoadEnd; int main (void) { UINT32_t *fctCallPointer =&_MySectLoadStart; while (fctCallPointer <&_MySectLoadEnd){ fCall =(fctCall)(*fctCallPointer++); fCall(); } 返回0;}

    链接程序命令文件中的此行

    my_sect:  > SRAM load_start(_MySectLoadStart),load_end(_MySectLoadEnd)

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

    我的目的是拥有一个包含函数(指针)的内存块,我可以轻松地迭代这些函数。

    但是我不想初始化数组,因为函数可以位于我项目的每个模块中。

    我不需要固定长度的数组,因为函数的数量可能会发生变化。[/QUOT]在线程 中,如何使用C/C++将初始化的数据正确声明为闪存 ,还有另一个示例可以帮助您。