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.

[参考译文] TMS570LC4357:软件复位重新初始化 RAM

Guru**** 2463330 points
Other Parts Discussed in Thread: TMS570LC4357

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/655579/tms570lc4357-software-reset-reinitializes-ram

器件型号:TMS570LC4357

大家好、

我正在为 TMS570LC4357开发引导加载程序。

目前、我有一个工作正常的引导加载程序、它允许我写入闪存存储器和应用程序。

当必须启动引导加载程序时、它必须认识到发生了上电复位并跳转到应用程序。

应用程序在运行时必须设置一个 RAM 变量以跳转到引导加载程序;此变量驻留在引导加载程序和应用程序之间的共享 RAM 中。

从应用程序跳转至引导完成设置:systemREG1->SYSECR = 0x8000;

问题是:这个复位不能被识别为一个软件复位、而是一个"NO_RESET";这会导致一个 RAM 初始化、此初始化会删除存储在共享 RAM 中的信息;因此、引导加载程序将跳回到应用程序。

如何避免 RAM 初始化?

我按照这个主题执行了此操作:  

我们将感谢您的任何帮助。

谢谢

Valentina

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    其他信息:复位后、查看寄存器 SYS_ECR、我看到0x00004000、而查看 SYS_ESR、我看到0x00000010
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在进行复位时、您要检查哪个寄存器以确定是否发生了软件复位? 您应该检查 SYSESR、您之前的帖子中显示的位集表示 SWRST (SYSESR 的位4)。 这应该足以允许保留 RAM 并进入适当的执行路径。

    SYSECR 寄存器仅用于启动软件复位、不用作状态寄存器。 因此、即使在回读 SYSECR 时写入1到位15或0到位14来触发软件复位、也会读取0x4000的值。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    大家好、Davenport 先生、

    感谢您的快速回复。  

    为了确定 SW 复位、我要查看 SYSESR、它显示了正确的值。 顺便说一下、我运行了更多的测试、我注意到了这里。

    应用程序必须:

     -接收定义的 SPI 消息

     -将定义的值写入 RAM 地址

     -检查 RAM 地址并最终跳转至引导加载程序。

    当我运行此测试并发送 SPI 消息时、我看到引导加载程序跳转、但它立即切换回应用程序。

    另一方面、如果使用 IDE CCS 7.1、我在运行应用程序时手动将相同的值写入 RAM 地址、则它会跳转到引导加载程序并保持在那里(根据我的需要)。

    这种行为是否有任何解释? 它是否与 SPI 消息有关? 我无法确定这两种情况下有何不同、因为在一种情况下会重新初始化 RAM。

    按照引导加载程序内部的启动代码执行操作(如果可以的话):

    void _c_int00 (void)
    {
    
    /*用户代码开始(5)*/
    /*用户代码结束*/
    
    /*初始化内核寄存器以避免 CCM 错误*/
    _coreInitRegisters_();
    
    /*初始化堆栈指针*/
    _coreInitStackPointer_();
    
    /*复位处理程序:以下指令从系统异常状态寄存器中读取
    *以确定 CPU 复位的原因。
    *
    switch (getResetSource())
    {
    案例 POWERON_RESET:
    调试复位情况:
    案例 EXT_RESET:
    
    //*用户代码开始(6)*/
    *用户代码结束*/
    
    /*初始化 L2RAM 以避免在上电后立即出现 ECC 错误*/
    _memInit_();
    
    /*用户代码开始(7)*/
    /*用户代码结束*/
    
    *用户代码开始(8)*/
    //*用户代码结束*/
    
    
    *用户代码开始(9)*/
    */*用户代码结束*
    
    /*启用 CPU 事件导出*/
    /*这允许 CPU 发出检测到的任何单位或双位错误的信号
    *通过其 ECC 逻辑访问程序闪存或数据 RAM。
    *
    _coreEnableEventBusExport_();
    
    //用户代码开始(10)*/*
    用户代码结束*/
    
    /*检查加电期间是否存在 ESM 组3错误。
    *这些可能发生在电子保险丝自动加载期间或从闪存 OTP 读取期间
    *在加电期间。 器件运行不可靠、不建议这样做
    *。 *
    if ((esmREG->SR1[2])!= 0U)
    {
    esmGroup3Notification (esmREG、esmREG->SR1[2]);
    }
    
    /*初始化系统-时钟、闪存设置、带 Efuse 自检*/
    systemInit();
    
    /*用户代码开始(11)*/*
    用户代码结束*/
    
    /*通过 Vic 控制器启用 IRQ 偏移*/
    _coreEnableIrqVicOffset_();
    
    /*初始化 VIM 表*/
    vimInit();
    
    /*用户代码开始(12)*/
    /*用户代码结束*/
    /*配置系统对发送给 ESM 组1的错误条件的响应*/
    /*可以从 HALCoGen 的"ESM"选项卡配置此函数*/
    esmInit();
    
    /*用户代码开始(13)*/
    /*用户代码结束*/
    
    中断;
    
    案例 OSC_failure_reset:
    /*用户代码开始(14)*/
    /*用户代码结束*/
    中断;
    
    案例安全装置复位:
    案例 WATCHDOG2_RESET:
    /*用户代码开始(15)*/
    /*用户代码结束*/
    中断;
    
    案例 CPU0_RESET:
    //*用户代码开始(16)*/
    //*用户代码结束*/
    
    *用户代码开始(17)*/
    //*用户代码结束*/
    
    *用户代码开始(18)*/
    */*用户代码结束*/
    
    /*启用 CPU 事件导出*/
    /*这允许 CPU 发出检测到的任何单位或双位错误的信号
    *通过其 ECC 逻辑访问程序闪存或数据 RAM。
    *
    _coreEnableEventBusExport_();
    
    //用户代码开始(19)*/*
    用户代码结束*/
    中断;
    
    案例 SW_RESET:
    案例 NO_RESET:
    //用户代码开始(20)*/
    _coreEnableEventBusExport_();
    systemInit();
    _coreEnableIrqVicOffset_();
    vimInit();
    esmInit();
    /*用户代码结束*/
    中断;
    
    默认值:
    //用户代码开始(21)*/
    //*用户代码结束*/
    中断;
    }
    
    /*用户代码开始(22)*/
    /*用户代码结束*/
    
    _mpuInit_();
    
    /*用户代码开始(23)*/
    /*用户代码结束*/
    
    _cacheEnable_();
    
    //用户代码开始(24)*/
    //*用户代码结束*/
    
    
    //*用户代码开始(25)*/
    //*用户代码结束*/
    
    /*初始化全局变量和构造函数*/
    __TI_auto_init();
    
    /*用户代码开始(26)*/
    /*用户代码结束*/
    
    /*调用应用程序*/*SAFETYMCUSW
    296 S MR:8.6 "启动代码(块范围内的库函数)"*/
    /* SAFETYMCUSW 326 S MR:8.2 "startup code (Declaration for main in library)"*/
    /* SAFETYMCUSW 60 D MR:8.8 "启动代码(库中 main 的声明;仅为相同操作 extern)"*/
    main();
    /*用户代码开始(27)*/*
    用户代码结束*/*
    SAFETYMCUSW 122 S MR:20.11 "启动代码(需要存在 EXIT 和 ABORT)"*/
    EXIT (0);
    
    
    /*用户代码开始(28)*/
    /*用户代码结束*/
    
    }
    

    此外,我还按如下方式更改了 getResetSource()函数,因为它总是最终进入外部复位:

    resetSource_t getResetSource (void)
    {
    寄存器 resetSource_t rst_source;
    
    if ((SYS_EXception &(UINT32) powerON_RESET)!= 0U)
    {
    /*上电复位条件*/
    RST_SOURCE = POWERON_RESET;
    
    /*清除所有异常状态标志并在通电后继续进行*/
    SYS_EXception = 0x0000FFFFU;
    }
    //否则(((SYS_EXception &(UINT32) EXT_RESET)!= 0U)
    //{
    /*由于外部复位导致的复位。 */
    // RST_SOURCE = EXT_RESET;
    // SYS_EXception =(UINT32) EXT_RESET;
    //}
    如果((SYS_EXCE异常 和(UINT32) DEBUG_RESET)!=0U)则为其他
    {
    /*由于调试复位请求导致的复位*/
    RST_SOURCE = DEBUG_RESET;
    SYS_EXception =(UINT32) debug_reset;
    }
    如果((SYS_EXception &(UINT32) OSC_failure_reset)!= 0U)则为其他值
    {
    /*由于振荡器故障导致的复位。
    在此处添加用户代码以处理振荡器故障*/
    RST_SOURCE = OSC_FAILY_RESET;
    SYS_EXception =(uint32) OSC_failure_reset;
    }
    如果((SYS_EXCE异常 和(UINT32)安全装置复位)!=0U)则为其他
    {
    /*由于违反看门狗而导致的复位*/
    RST_SOURCE =安全装置复位;
    SYS_EXception =(uint32) watchdog_reset;
    }
    如果((SYS_EXCE异常&(UINT32) WATCHDOG2_RESET)!=0U)则为其他
    {
    /*由于违反看门狗而导致的复位*/
    RST_SOURCE = WATCHDOG2_RESET;
    SYS_EXception =(UINT32) WATCHDOG2_RESET;
    }
    否则(((SYS_EXCE异常&(UINT32) CPU0_RESET)!=0U)
    {
    /*由于 CPU0复位导致的复位。
    CPU 复位可能由 CPU 自检完成、或引起
    通过切换 CPU 复位控制寄存器的"CPU RESET"位。 *
    RST_SOURCE = CPU0_RESET;
    SYS_EXception =(UINT32) CPU0_RESET;
    }
    否则(((SYS_EXception &(UINT32) SW_RESET)!= 0U)
    {
    /*由于软件复位导致的复位。 *
    RST_SOURCE = SW_RESET;
    SYS_EXception =(UINT32) SW_RESET;
    }
    其他
    {
    /*发生了 No_reset。 *
    RST_SOURCE = NO_RESET;
    }
    
    返回 rst_source;
    } 

    感谢您的关注。

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

    我很抱歉、我被拖了一会儿才回到您的位置。 我将审核您的代码、并在周一向您回复任何发现或其他问题/建议。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好 Valentina、

    我很抱歉耽误您的时间、但我认为这里的问题是正在设置的 SYSESR 寄存器中的多个位。 请注意、大多数复位都将 EXT_RST 置为有效、请参阅 TRM 中的以下说明:

    这与 getResetSource()函数中的代码结构相结合,将导致在 if-else if 代码结构期间测试的第一个异常位。 由于这种情况以及 SW 复位的特殊情况/用法,您可能需要在 getResetSource()函数中进行调整,方法是将 EXT_RST 的测试置于 if- if else 语句系列的最后一个测试中。  

    请注意、我最初的想法是删除 else if 语句并使其全部简化 if 语句块、但这会导致返回值、可能会设置多个复位位位、并导致开关情况架构中断。 我建议重新安排 getResetSource()函数中位的测试,以满足您的需要和项目所需的优先级。

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

    您好 Valentina、

    我已经对此进行了一些思考、 getResetSource 的代码更新可能会更加深入、因为这样可以为您的应用提供正确的返回值。

    resetSource_t getResetSource (void)
    {
    寄存器 resetSource_t rst_source;
    
    if ((SYS_EXception &(UINT32) powerON_RESET)!= 0U)
    {
    /*上电复位条件*/
    RST_SOURCE = POWERON_RESET;
    
    /*清除所有异常状态标志并在通电后继续进行*/
    SYS_EXception = 0x0000FFFFU;
    }
    否则(((SYS_EXception &(UINT32) EXT_RESET)!= 0U)
    {
    /*由于外部复位导致的复位。 *
    RST_SOURCE = EXT_RESET;
    SYS_EXception =(UINT32) EXT_RESET;
    
    /***检查 EXT_RESET 的其它优先原因**/ 

    if ((SYS_EXception &(UINT32) OSC_failure_reset)!= 0U) { /*由于振荡器故障导致的复位。 在此处添加用户代码以处理振荡器故障*/ RST_SOURCE = OSC_FAILY_RESET; SYS_EXception =(uint32) OSC_failure_reset;
    } 如果((SYS_EXCE异常 和(UINT32)安全装置复位)!=0U)则为其他 { /*由于违反看门狗而导致的复位*/ RST_SOURCE =安全装置复位; SYS_EXception =(uint32) watchdog_reset; } 如果((SYS_EXCE异常&(UINT32) WATCHDOG2_RESET)!=0U)则为其他 { /*由于违反看门狗而导致的复位*/ RST_SOURCE = WATCHDOG2_RESET; SYS_EXception =(UINT32) WATCHDOG2_RESET; } 否则(((SYS_EXception &(UINT32) SW_RESET)!= 0U) { /*由于软件复位导致的复位。 * RST_SOURCE = SW_RESET; SYS_EXception =(UINT32) SW_RESET; } } 如果((SYS_EXCE异常 和(UINT32) DEBUG_RESET)!=0U)则为其他 { /*由于调试复位请求导致的复位*/ RST_SOURCE = DEBUG_RESET; SYS_EXception =(UINT32) debug_reset; } 否则(((SYS_EXCE异常&(UINT32) CPU0_RESET)!=0U) { /*由于 CPU0复位导致的复位。 CPU 复位可能由 CPU 自检完成、或引起 通过切换 CPU 复位控制寄存器的"CPU RESET"位。 * RST_SOURCE = CPU0_RESET; SYS_EXception =(UINT32) CPU0_RESET; } 其他 { /*发生了 No_reset。 * RST_SOURCE = NO_RESET; } 返回 rst_source; }

    在这里检查我的逻辑、但我认为这应该适合您。

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

    你好、Chuck、

    感谢您的回复。

    遗憾的是、我很匆忙地完成了这个项目、因此我不得不使用 HW 引脚来解决 RAM 问题。 但是、您的解释是有道理的、一旦我有时间、我将测试建议的代码。

    感谢你的帮助。