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.

[参考译文] TM4C129EKCPDT:保留非触摸存储器空间

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1259947/tm4c129ekcpdt-reserving-untouched-memory-space

器件型号:TM4C129EKCPDT

您好!

我正在尝试保留一块 RAM 用于从引导代码和主应用进行信息传输。 我现在正在编写引导代码、并尝试在0x20000000 (len=0x400)保留存储器。

以下是我的链接命令文件:

--retain=g_pfnVectors
--retain=PrebootVector
--retain=标题
--retain=ExHeader

内存
{
   Flash (RX):origin = 0x00000000、length = 0x00008000 last (__IMG_SIZE)
   SRAM (rwx):origin = 0x20000400、length = 0x00040000 - 1K


/*以下命令行选项作为 CCS 项目的一部分设置。    */
/*如果您正在使用命令行进行构建,或者出于某种原因想要   */
/*在此处定义它们,您可以根据需要取消注释和修改这些行。     */
/*如果您使用 CCS 进行构建、则最好制作任何此类项目*/
/*对 CCS 项目的修改,并保留该文件。              */
/*                                                                          */
/*--heap_size=0                                                            */
/*--stack_size=256                                                         */
/*--library=rtsv7M4_T_le_eabi.lib                                          */

/*内存中的段分配*/

部分
{
   .pbootvec:   >0x00000000
   .header:   > 0x00000120
   .intvecs:  > 0x00000200
   .text  :  >闪存
   .const :  >闪存
   cinit :  >闪存
   请输入您的密码 :  > FLASH
   init_array:> FLASH

   .vtable:  > 0x20000400
   .data  :  > SRAM
   bss   :  > SRAM
   .sysmem:  > SRAM
   .stack :  > SRAM


__STACK_TOP =_STACK + 512;

请注意、SRAM 范围从0x20000400开始。我希望不会触及此位置(0x20000000 -0x200003ff)。 为了验证这一点、我做了一个实验、为该位置分配一些值。 我启动一个调试会话、并确保已分配这些值、然后我停止调试会话、在电源复位电路板的情况下、我再次启动调试会话。 理论上、由于 MCU 尚未进行电源复位、分配的值应该仍然存在。 但事实并非如此。  即使该位置不在定义的 SRAM 范围内、它似乎始终被初始化为某个值。 由于项目中没有其他地方能做到这一点,我怀疑是_c_int00()中的代码造成了这一问题。

我还在不同的 IDE (Semens' CodeBench)上进行了类似的实验、结果是预期得到的。

有没有解决这个问题的办法?

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

    您好、Tianle、

     是的,它是在_c_init00()被输入后自动初始化的一部分。 但是、我不知道如何提供只能绕过部分 RAM 在复位后进行初始化的解决方案。 我需要将您的帖子转给我们的编译器专家以寻求建议。 请注意、E2E 论坛将在接下来的两天内维护。 请等待我们的专家的延迟回复。   

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

    编译器生成的代码以及 RTS 库中的所有代码、包括启动代码、假设唯一有效的存储器范围是 内存 指令。  因此,这是...

    我怀疑是_c_int00()中的代码做了这个把戏

    ...不正确。

    因为我无法解释发生了什么、所以我已将此主题的责任转给了器件软件专家。

    谢谢。此致、

    -乔治

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

    您好、下面是问题的简单步骤:

    1.使用 main()函数创建新的 CCS 项目

    2.按如下所示修改.cmd 文件中的2行

       SRAM (rwx):origin = 0x20000000、length = 0x00040000

       SRAM (rwx):origin = 0x20000400、length = 0x00040000 - 1K

       .vtable:  > 0x20000000

       .vtable:  > 0x20000400

    3.定义 main 函数

    int main (空)
    {
       uint32_t* test=0x20000000;
       *test = 0xaaaaaaaa;

       while (1);

    4.调试项目、让固件运行、这样将值为0xaaaaaaaaaa 的位置0x20000000分配

    5.停止调试会话并重新启动它、而不会将目标电源复位

    6.检查0x20000000处的存储器

    0x20000000处的值不再为0xaaaaaaaaaa。

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

    您好,天磊,

      在您的情况下、它在0x20000000处发生了什么变化? 我使用您的确切代码。 我尝试做三件事:

     1.系统复位

     2.重新启动

     3.停止调试会话,以断开调试器与 MCU 的连接。 断开后、我立即再次连接到器件。

     但0x20000000处的值未更改。 上述三个步骤不影响值0xAAAAAA。  

    下面是我使用的.cmd 文件、它与您所做的几乎相同-更改 SRAM 的起始地址和.vtable。  

    --retain=g_pfnVectors
    
    /* The following command line options are set as part of the CCS project.    */
    /* If you are building using the command line, or for some reason want to    */
    /* define them here, you can uncomment and modify these lines as needed.     */
    /* If you are using CCS for building, it is probably better to make any such */
    /* modifications in your CCS project and leave this file alone.              */
    /*                                                                           */
    /* --heap_size=0                                                             */
    /* --stack_size=256                                                          */
    /* --library=rtsv7M3_T_le_eabi.lib                                           */
    
    /* The starting address of the application.  Normally the interrupt vectors  */
    /* must be located at the beginning of the application.                      */
    #define APP_BASE 0x00000000
    #define RAM_BASE 0x20000000
    
    /* System memory map */
    
    MEMORY
    {
        /* Application stored in and executes from internal flash */
        FLASH (RX) : origin = APP_BASE, length = 0x00100000
        /* Application uses internal RAM for data */
        SRAM (RWX) : origin = 0x20000400, length = 0x00040000 - 0x400
    }
    
    /* Section allocation in memory */
    
    SECTIONS
    {
        .intvecs:   > APP_BASE
    
        .text   :   > FLASH
        .const  :   > FLASH
        .cinit  :   > FLASH
        .pinit  :   > FLASH
        .init_array : > FLASH
    
        .vtable :   > 0x20000400
        .data   :   > SRAM
        .bss    :   > SRAM
        .sysmem :   > SRAM
        .stack  :   > SRAM
    
    
    }
    
    __STACK_TOP = __stack + 512;

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

    尊敬的 Charles:

    在启动下一个调试会话之前、您是否终止了(红色按钮)上一个调试会话?

    从你发布的图像来看、0x00000000之后的存储器内容跟我的模式是一样的、看起来非常像矢量表。 如果未触及该区域、那么它不应该是随机值?

    此致、

    天磊

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

    您好,天磊,

     是的、根据我在前面介绍的第三个实验、我通过按下红色方形按钮来停止调试会话。 断开连接后、我立即再次连接到目标。 查看0x20000000处的存储器内容时、该值保持不变。 请注意、当我重新连接时、PC 在来自之前调试会话的 while (1)中仍在旋转。  

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

    尊敬的 Charles:

    上一会话中的这一步骤未终止。 如果它被终止,新的会话应该在 main ()的入口处中断。

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

    您好,天磊,

     在第一个调试会话中、我首先运行代码。 代码运行后、它 将 0xAAAAAAAA 写入0x20000000、然后到达 while (1)。 即使您断开连接、它也将保持 while (1)。 断开(当您按下红色方形按钮时)仅意味着调试器从目标器件上断开。 器件将继续运行 while (1)。 重新连接后、我看到 PC 停留在 while (1)并且内存没有改变。 请自行重试、或告诉我如何"终止"调试会话。  

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

    尊敬的 Charles:

    我不知道为什么你的设备保持 while (1)当重新连接。 由于 PC 已经处于 while (1)、因此仍存在0xAAAAAAAA 也就不足为奇了。

    我的观察结果与您的观察结果完全相同(当我按下红色按钮时、调试器停止工作)。 唯一的区别是当我重新连接(启动一个新的调试会话)时,固件将重新启动,并在 main 的第一行自动停止()。

    这实际上是我报告的问题。 在 mian ()的第一行,值0f 0xAAAAAAAA 没有被代码分配,但如果器件之前运行过代码,没有经历掉电,该值仍然应该保留,因为"此后没有任何代码有意更改该值"。

    谢谢

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我的观察结果与您的观察结果完全相同(当我按下红色按钮时、调试器只会脱离接触)。 唯一的区别是,当我重新连接(启动一个新的调试会话)时,固件将重新启动,并在 main 的第一行自动停止()。

    您好、Tianle、

     您是如何重新连接的? 您是否通过按如下所示的"调试"按钮重新连接? 通常、如果对代码或编译设置进行了任何更改、这将重新编译项目。 然后,它将连接到目标,重新加载代码,程序将在 main ()运行并中断。  

    我重新连接的方式是、只需右键点击项目目录中的目标配置文件并选择 Launch Selected Configuration。 这只会连接到目标、而不会重新启动代码。  

     -首先在 CCS->View->Target Configurations 下打开 Target Configurations

     -下一步转至您的项目并右键单击目标配置文件。 我使用的是示例闪烁。 在 blinky 示例项目中、有 target_config.ccxml 文件。 右键点击它、您将看到另一个选择菜单。  

     -选择启动 所选配置。 这将重新连接到您的设备。  

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

    尊敬的 Charles:

    我从未使用"Target Configuration"选项卡中的"Launch Selected Configuration"选项。

    在我终止之前的会话后、我可以进入运行/调试来重新启动新会话。

    另一种方法是转到"Run/Debug History"并选择了最新的、或者转到"Run/Debug Configurations... 然后手动选择要调试的项目。

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

    您好,天磊,

     您能尝试一下我展示的内容吗?  

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

    尊敬的 Charles:

    我尝试了您的步骤、但 Launch Selected Configuration 似乎对我不起作用。 选择选项后、IDE 无法成功连接目标、尽管它已经处于调试会话中。 在 Registers 窗口中、所有寄存器都显示为"Error:Cannot Read (错误:无法读取)"。 在 Memory 窗口中、所有的位置都显示为"?"。

    我不知道这种做法的目的。 即使我的结果与你的结果相同、它也不会证明任何事情。 我的目的是让代码重新启动、而不仅仅是被调试器重新使用。

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

    您好,天磊,

     如果我通过单击"调试"按钮启动调试会话、我就可以重现现有情况。 当我执行该操作时、我将看到0x20000000处的内容被覆盖、并使用指向堆栈顶部的指针值。 在我的示例中、我的链接器具有以下代码片段。 我将在0x20000000处看到被0x20000600值覆盖、即__STACK_TOP。 _STACK_TOP 符号等于__STACK + 512。 __stack 为0x20000,400,512为0x200。 添加它们会产生0x20000600。 我不知道 CCS 或 BootCode 在这方面是如何工作的、也不知道为什么它需要将__STACK_TOP 放在0x20000000上。 我需要咨询我们的编译器专家。 我将在这里附上我非常简单的项目、以便我们的专家可以复制这些项目。 也许是某些 CCS 或链接器设置需要更改、但我不确定。  

    内存
    {
    /*存储在内部闪存中并从内部闪存执行的应用程序*/
    FLASH (RX):origin = APP_BASE,length = 0x00100000
    /*应用程序使用内部 RAM 进行数据*/
    SRAM (rwx):origin = 0x20000400、length = 0x00040000 - 0x400

    /*内存中的段分配*/

    部分
    {
    .intvecs:> app_base

    .text :>闪存
    .const :>闪存
    cinit :>闪存
    请输入您的密码:> FLASH
    init_array:> FLASH

    .vtable:> 0x20000400
    .data :> SRAM
    bss :> SRAM
    .sysmem:> SRAM
    .stack:> SRAM


    __STACK_TOP =_STACK + 512;

     

    e2e.ti.com/.../sram_5F00_init.zip

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

     尊敬的 Tienlei:

      我想已经发生的情况是、在你通过按下调试按钮来启动一个全新的调试会话后、闪存加载程序算法被复制到 RAM 中。 它使处理器执行闪存加载程序算法。 以便加载新的固件映像、而无论映像是否更新。 如果您确实需要通过为目标配置文件选择"Launch Selected Configurations"来断开连接和重新连接、我建议使用我的方法。  

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

    尊敬的 Charles:

    我做了更多的实验、结果表明更改值的不是加载器算法。

    下面是我的项目代码:

    #包含
    #include "stdbool.h"
    #include "inc/hw_memmap.h"
    #include "driverlib/sysctl.h"
    #include "driverlib/gpio.h"

    int main (空)
    {

       uint32_t* test=0x20000000;
       int MemOk=(*测试== 0xaaaaaaaaaa);
       *test = 0xaaaaaaaa;

       SysCtlPeripheralEnable (SYSCTL_Periph_GPIOF);
       GPIOPinTypeGPIOOutput (GPIO_PORTF_BASE、GPIO_PIN_0);
       GPIOPadConfigSet (GPIO_PORTF_BASE、GPIO_PIN_0、GPIO_strength_4mA、GPIO_PIN_TYPE_STD);


       GPIOPinWrite (GPIO_PORTF_BASE、GPIO_PIN_0、MemOk? 0x00:0xff);


       while (1);

    我使用一个由 GPIO 引脚驱动的 LED 来指示测试位置的值。 我将代码刻录到了 MCU 中。 首次上电时、LED 熄灭、然后我在保持供电的同时通过下拉 RESET 引脚来复位 MCU。 复位后、LED 仍然熄灭。 这意味着位置0x20000000总是被"另一个实体"更改。

    有趣的是、如果我将测试位置更改为0x20003000、它运行得非常好。 上电时、LED 熄灭、但热复位时、LED 点亮。

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

    您好,天磊,

     我不确定您要如何处理下面的行。 您需要使用==而不是=。 您真的想将== 用作比较运算符吗?  

    int MemOk=(*test ) == 0xaaaaaaaa);

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

    假设您是要使用==运算符、则我认为您要配置 RESET 引脚行为以生成系统复位而不是模拟 POR。  

    将以下行添加到您的代码中。  

    SysCtlResetBehaviorSet (SYSCTL_ONRST_EXT_SYS);

    当您进行此操作时、在电源循环后首次将 MemOk 为零、这是因为*测试还未被指定一个值并且 (*测试== 0xaaaaaaaaaa)将失败。 此时,LED 将会亮起,因为 MemOk? 0x00:0xff 将评估是否将 1写入 PF0以打开 LED。  

    如果您下次按下复位管脚、*测试仍然保留其之前的值、即0xaaaaaaaa。 这将使 (* test == 0xaaaaaaaa)为 true 并且 MemOk 变为1。 当 MemOk 时? 0x00:评估0xff、将0x00写入 PF0以关闭 LED。  

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

    尊敬的 Charles:

    如果存储器位置(0x20000000)的值为0xaaaaaaaaaa、则 MemOk 将被分配1;

    否则、将为其分配0。

    这表示值0xaaaaaaaaaa 是否保留在位置0x20000000。

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

    当代码开始运行时(当 main ()被输入时)、它首先检查内存位置0x20000000来查看它是否含有值0xaaaaaaaa。 如果是、则会点亮 LED、否则会熄灭 LED。

    然后不管怎样、它将把值0xaaaaaaaaaa 放置到位置0x20000000。

    预期的代码行为为:

    电源复位时、LED 应该熄灭。

    热复位时、LED 应该亮起。

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

    您好,天磊,

     您是否已添加以下行? 如果您确实这样做了、那么在您应用复位引脚之后、RAM 不会发生任何变化。  

    SysCtlResetBehaviorSet (SYSCTL_ONRST_EXT_SYS);

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

    尊敬的 Charles:

    我正在努力理解你的宗旨。 我正在下拉复位(NMI)引脚以强制 MCU 进行热复位。 我不需要配置它。

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

    尊敬的 Charles:

    我正在努力理解你的宗旨。 我正在下拉复位(NMI)引脚以强制 MCU 进行热复位。 我不需要配置它。

    对于电源复位、我只需拔下电源插头再插回。

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

    您好,天磊,

     系统复位和 POR 复位之间存在差异。 有关详细信息、请参阅数据表中的复位行为控制。 这就是为什么我要求将复位行为更改为仅生成系统复位、而不是内部 POR 复位。  

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

    尊敬的 Charles:

    在我将行添加到

    SysCtlResetBehaviorSet (SYSCTL_ONRST_EXT_SYS);

    与代码相关联、它开始按预期工作。

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

    这是否意味着当进入调试会话时、CCS 将强制 MCU 进行电源复位?

    有趣的是、我在使用另一个 IDE (CodeBench)时不存在此类问题。 这是否意味着通过 JTAG、IDE 可以强制 MCU 进行系统复位或上电复位?  只是试着解释我的观察。

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

    您好,天磊,

     如前所述、新的调试会话将强制 CCS 将闪存加载程序算法复制到 RAM 中。 这将覆盖 Flash 加载程序所需的空间。 起初、我认为这是您的问题、因为您正在进行实验以断开调试会话、然后启动一个新的调试会话。  

     在您最近在未连接调试器的情况下进行的实验中、您报告拉复位引脚后 RAM 内容已更改。 这提示我、认为这与如何根据 RESET 引脚的行为配置相关。 默认情况下、nRST 引脚将生成仿真 POR (更像冷复位)。 它执行与 系统复位(热复位)不同的器件初始化。 冷复位将影响 RAM 的内容、而不是热复位。  

     或许对于 CodeBench、除非您另有要求、否则新的调试会话不会自动将闪存加载程序算法加载到 RAM 中。 我不知道在这方面有什么工具。  

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

    非常感谢 Charles!