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.

[参考译文] RM46L852:Hercules 热复位改变时钟速度

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/575378/rm46l852-hercules-warm-reset-changing-clock-speeds

器件型号:RM46L852
主题中讨论的其他器件:HALCOGEN

我正在使用 Hercules 自举。 它从上电复位开始正常运行。 当我执行 JTAG 复位或按下热复位按钮时、它会重新启动正常。


但是、如果我在以不同时钟速度运行的 RTOS 应用中执行自举、则 JTAG 复位和热复位会重置到 Hercules 自举中、但它会挂起、等待 PLL csvstat 在严格的 while 环路中达到其预期值。 这在 Hercules 示例引导映射时钟函数中。

是否有一些示例汇编器(或更好的 C)代码将解锁 PLL、以便引导程序以新的时钟速率启动?

谢谢、Steve

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

    您好、Steve、

    这似乎与器件上的已知问题有关。 您能否查看勘误表 SSWF0221#45并查看建议的变通办法是否能够有效地修复此问题? 相应的勘误文档将取决于您使用的器件的修订版。

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

    你好、Chuck、

    我运行的是出现故障的版本 c。 似乎勘误表仅讨论 PLL 上电故障。 到目前为止、在 POR 模式下、我始终得到一个锁定。 JTAG 系统复位或电路板的"热复位"按钮都会出现问题。 这并不奇怪、因为至少在这个 Hercules 电路板上、JTAG 复位会进行热复位。 我的实际使用模式是当 RTOS 跳转到引导程序并且引导程序想要设置整个系统、包括时钟频率时-它只是在以下等待循环中挂起。


    这是 Hercules 引导加载程序(rm46_CAN_ boot)示例的 system.c 中的挂起例程:

    void mapClocks (void)(空)

       
    /*用户代码开始(11)*/
    /*用户代码结束*/

       /**@b 初始化@b 时钟@b 树:*/
       /**-可调/启用时钟域*/
       systemREG1->CDDIS=(false << 4)/* AVCLK 1 off */
                         |(true<<5 )/* AVCLK 2 off */
                        |(false <<8 )/* VCLK3关闭*/
                        |(false << 10)/* AVCLK 3 off */
                         |(false << 11);// AVCLK 4 off */

       /**-等待直到时钟锁定*/
       while ((systemREG1->CSVSTAT &((systemREG1->CSDIS ^ 0xFF)& 0xFF)!=((systemREG1->CSDIS ^ 0xFF)& 0xFF))
       {
       }

    这个 while 循环挂起、直到 csvstat 的位完全等于0x73。 当我执行上电复位或通过 JTAG 重新加载固件时、它会起作用。 当我进入挂起状态并在 ccsv6中按 PAUSE 时、ccsvstat 等于0x33


    根据 TRM、这意味着 pll2位未置位。

    感谢你的任何帮助。

    Steve

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

    大家好、我只想重申一个案例、我觉得很有趣:

    当我执行上电复位或通过 JTAG 重新加载固件时、它会起作用。

    因此、通过 JTAG 复位不会修复挂起、但执行固件重新加载会解决此问题? 在设置时钟时、必须有一些神奇的解释、这将使我摆脱挂起的状态。

     

    此致、Steve

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

    在进入 while 循环之前、您能否检查 PLL1和2中的 PLL 滑动标志的值以查看它们是否已设置? 您可能会看到 PLL 上的一些毛刺脉冲、这是由于被捕捉为 PLL 跳周事件的时钟/ PLL 的复位/重启引起的。 鉴于所描述的行为、这很可能出现在 PLL2中。 您应该能够通过评估 ESM 寄存器的内容来检查是否出现了差异。 您还可以通过查看 TRM 的"14.5.3 PLL 故障行为"部分了解一些要尝试的操作。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Chuck Davenport"] TRM 的"14.5.3 PLL 故障行为"部分。

    这使我感到困惑。 我使用 spnu514b.pdf 上的 TRM - PLL 信息位于第2.5节和第10.5节。

    在 第10.5.4节"从 PLL 故障中恢复"中、其说明"的全局状态寄存器(GLBSTAT)中的 RFSLIP 或 FBSLIP 状态标志均不是

    系统和外设控制寄存器被置位。" 我确认、它挂起、但没有滑动指示器。 pll2没有 ROS 位。

    但是、无论如何、查看这些部分以及 ccsv6向我展示的有关2个寄存器的信息、我尝试忽略 pll2位:

    /**-等待直到时钟锁定*/
    while ((systemREG1->CSVSTAT &(systemREG1->CSDIS ^ 0xFF)& 0xBF)!=((systemREG1->CSDIS ^ 0xFF)& 0xBF))

    请注意、我将"有趣的位"掩码从0xff 更改为 bbf。

    那么、凭经验、这可以解决我的重启 PLL 挂起问题、但我不想忽略它-可能存在真正的问题? 我如何知道以及是否有批准的正式途径来重新启动 PLL?

    谢谢、Steve

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

    很抱歉、章节编号存在混淆。 我在 TRM 中查看了类似 Hercules 器件型号的相同信息、章节映射稍有不同。

    而忽略 PLL2的位。 您是否在项目中使用 PLL2? 当您重新启动时钟时、您是否也会重新启动 PLL2? 否则、可能是该位从未设置、因为它尚未重新启动/重新锁定。 也就是说、在上电时、PLL2脱离掉电状态、因此它在锁定时设置位、但当您通过 nRST 时、它永远不会循环、因此该位永远不会再次被置位(以某种方式它脱离同步)。 您能否添加代码以显式初始化和锁定 PLL2并查看这是否有帮助?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    [引用 user="Chuck Davenport"]您能否添加代码以显式初始化和锁定 PLL2并查看这是否有帮助?


    我正在使用 TI 提供的示例引导加载程序启动代码。 我可以告诉它在这个测试前明确设置 pll1、pll2和 pll3。 我认为没有 pll3、但有 pll3控制寄存器。

    总之、我们认为我们不使用 pll2 -它似乎是用于通过 GPIO 为某些异步外部器件计时的? 因此、我想我只会忽略锁并等待相关问题。


    感谢您的帮助、Steve

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

    Steve、

    因此、在查看使用最新版本的 Hlacogen 生成的 Halcogen 代码时、时钟启动例程使用以下禁忌

    /*禁用 PLL1和 PLL2 */
    systemREG1->CSDISSET = 0x00000002U | 0x00000040U;
    /*SAFETYMCUSW 28 D MR:NA "硬件状态位读取检查"*/

    这在启动时用于确保 PLL 在重新初始化之前被关断。

    此外、您能否将整个时钟配置代码发布到它挂起的位置、以便我可以查看是否缺少任何可能提高稳健性的代码。

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

    否、我找不到用于禁用 PLL 的代码。 我应该将其放入 setupPLL 函数中吗?

    总之、这里是 TI ZIPed Hercules 自举库"system.c"中的代码

    void setupPLL (void)

    unsigned int 乘法器;

    /*用户代码开始(3)*/
    /*用户代码结束*/

    /**-配置 PLL 控制寄存器*/
    /**@b 初始化@b Pll1:*/

    /**-设置 PLL 控制寄存器1:
    * -振荡器跳周时的设置复位
    * —设置 PLL 跳周旁路
    * -在锁定前将 PLL 输出时钟分频器设置为最大值
    * -振荡器故障时的设置复位
    * -设置参考时钟分频器
    * —设置 PLL 倍频器
    *

    /*固定 DIV:参考 CLK DIV=6;输出 DIV=2;R DIV=2用于 RM42/LS04、1用于其他*
    /* Muiflier:乘法器=(SYS_CTL_CLK*6*2*2)/晶振= 160*6*2*1/16=120 */
    /* Muiflier:乘法器=(SYS_CTL_CLK*6*2*2)/晶振= 80*6*2*1/16=60 */
    #IF 已定义(TMS570LS04)||已定义(RM42)
    乘法器=(SYS_CLK_FREQ*6*2*2)/crystal_FREQ;
    其他
    乘法器=(SYS_CLK_FREQ*6*2*1)/crystal_FREQ;
    #endif

    systemREG1->PLLCTL1 = 0x000000000000U
    | 0x20000000U
    |((0x1F)<< 24U) /* R-分频器,稍后将在 mapClock()中进行编程*/
    | 0x000000000000
    |((6U - 1U)<<16U)/*参考时钟分频器:6 */
    |((乘法器- 1U)<<8U);/*乘法器:120*/

    /**-设置 PLL 控制寄存器2
    * -启用/禁用频率调制
    * -设置传播速率
    * -设置带宽调整
    * —设置内部 PLL 输出分频器
    * -设置摊铺量
    *
    systemREG1->PLLCTL2 = 0x000000000000U
    |(255U << 22U)
    |(7U << 12U)
    |((2U-1U)<<9U)/*输出分频器:2*/
    | 61U;

    /**@b 初始化@b Plll2:*/

    /**-设置 pll2控制寄存器:
    * -在锁定前将 PLL 输出时钟分频器设置为最大值
    * -设置参考时钟分频器
    * —设置内部 PLL 输出分频器
    * —设置 PLL 倍频器
    *
    systemREG2->PLLCTL3 =((2U-1U)<<29U)
    |((0x1F)<< 24U)
    |((5U - 1U)<<16U)
    |((30U - 1U)<<8U);

    /**-启用 PLL 以启动或锁定*/
    systemREG1->CSDIS = 0x000000000000U
    | 0x000000000000
    | 0x00000008U
    |0x00000080U
    | 0x000000000000
    | 0x000000000000
    | 0x000000000000;



    void mapClocks (void)(空)


    /*用户代码开始(11)*/
    /*用户代码结束*/

    /**@b 初始化@b 时钟@b 树:*/
    /**-可调/启用时钟域*/
    systemREG1->CDDIS=(false << 4)/* AVCLK 1 off */
    |(true<<5 )/* AVCLK 2 off */
    |(false <<8 )/* VCLK3关闭*/
    |(false << 10)/* AVCLK 3 off */
    |(false << 11);// AVCLK 4 off */

    /**-等待直到时钟锁定*/
    while ((systemREG1->CSVSTAT &(systemREG1->CSDIS ^ 0xFF)& 0xBF)!=((systemREG1->CSDIS ^ 0xFF)& 0xBF))



    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^μ A 用0xff ^^^^^^^^^^^^^^^^^屏蔽时在这里挂起


    // while (!(systemREG1->CSVSTAT & 0x040);

    /*用户代码开始(12)*/
    /*用户代码结束*/

    /*现在 PLL 被锁定并且 PLL 输出可被向上加速*/
    /* R 分频器被设定为0xF。 现在、该分频器已更改为编程值*/
    #IF 已定义(TMS570LS04)||已定义(RM42)
    systemREG1->PLLCTL1 =(systemREG1->PLLCTL1 & 0xE0FFFFFF)|((2U - 1U)<< 24U);
    其他
    systemREG1->PLLCTL1 =(systemREG1->PLLCTL1 & 0xE0FFFFFF)|((1U - 1U)<<24U);
    #endif
    systemREG2->PLLCTL3 =(systemREG2->PLLCTL3 & 0xE0FFFFFF)|((1U - 1U)<<24U);

    /**-将器件时钟域映射到所需的源并配置顶级分频器*/
    /**-到目前为止,所有时钟域都在关闭默认时钟源*/
    /**-可以使用 HALCoGen GUI 轻松修改以下分配*/

    /**-为正常运行、断电模式和唤醒后设置 GCLK、HCLK 和 VCLK 时钟源*/
    systemREG1->GHVSRC =(SYS_PLL1 << 24U)
    |(SYS_PLL1 << 16U)
    | SYS_PLL1;

    /**-为 VCLK1、VCLK2、VCLK3设置同步外设时钟分频器*/
    #IF 已定义(TMS570LS04)||已定义(RM42)
    systemREG1->VCLKR = 1;//1U;
    systemREG1->VCLK2R = 1;//1U;
    systemREG2->VCLK3R = 1U;
    其他
    systemREG1->VCLKR = 1;//1U;
    systemREG1->VCLK2R = 1;//1U;
    systemREG2->VCLK3R = 1U;
    #endif
    /*用户代码开始(13)*/
    /*用户代码结束*/

    /**-设置 RTICLK1和 RTICLK2时钟*/
    systemREG1->RCLKSRC =(1U <<24U)
    |(SYS_VCLK << 16U)
    |(1U << 8U)
    | SYS_VCLK;

    /**-为 AVCLK1和 AVCLK2设置异步外设时钟源*/
    systemREG1->VCLKASRC =(SYS_VCLK <<8U)
    | SYS_VCLK;

    systemREG2->VCLKACON1 =(1U <<24)
    | 1 << 20U
    |(SYS_VCLK << 16)
    |(1U <<8)
    | 1 << 4U
    #IF 已定义(TMS570LS04)||已定义(RM42)
    | SYS_VCLK;
    其他
    | SYS_PLL2;
    #endif
    /*用户代码开始(14)*/
    /*用户代码结束*/

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

    Steve、

    是的、我会添加 CSDIS 写入来在函数开始时禁用 PLL1和 PLL2。 基本上添加以下行:

    void setupPLL (void)
    {
    
    /*用户代码开始(3)*/
    /*用户代码结束*/
    
    /*禁用 PLL1和 PLL2 */
    systemREG1->CSDISSET = 0x00000002U | 0x00000040U;
    /*SAFETYMCUSW 28 D MR:NA "硬件状态位读取检查"*/
    while ((systemREG1->CSDIS & 0x42U)!= 0x42U)
    {
    /*等待*/
    }
    
    /*清除全局状态寄存器*/
    systemREG1->GBLSTAT = 0x301U;
    

    基本上、在引导加载程序情况下、最好确保在重新初始化和重新启用之前禁用 PLL。 这可能会有所帮助、但我认为它们不是根本原因。 使用 Halcogen 生成的当前代码时、mapClocks 函数中的 while 循环也不同、我怀疑它已更新、因为他们发现寄存器读取在某种程度上被优化掉或未在 condition 语句中正确更新。 mapClocks 现在具有以下功能:

    /* sourceId:system_sourceId_005 */*
    DesignId:system_DesignId_005 */*
    要求:HL_SR469 */
    void mapClocks(void)
    {
    uint32 SYS_CSVSTAT、SYS_CSDIS;
    
    /*用户代码开始(11)*/
    /*用户代码结束*/
    
    /**@b 初始化@b 时钟@b 树:*/
    /**-禁用/启用时钟域*/
    systemREG1->CDDIS =(UINT32)((UINT32)0U <<4U)/* AVCLK 1关闭*/
    |(uint32)((uint32) 1U << 5U)// AVCLK 2 off */
    |(uint32)((uint32) 0U << 8U)// VCLK3 off */
    |(uint32)((uint32) 0U << 9U)// VCLK4 off */
    |(uint32)((uint32) 0U << 10U)// AVCLK 3 off */
    |(uint32)((uint32) 0U << 11U);// AVCLK 4 off */
    
    
    /*勘误表的解决方法 SYS#46:
    *
    *勘误表说明:
    * 时钟源切换不符合时钟源使能和时钟源有效的要求
    *权变措施:
    * 始终检查 CSDIS 寄存器以确保时钟源已打开并检查
    * CSVSTAT 寄存器以确保时钟源有效。 然后写入 GHVSRC 以切换时钟。
    *
    /**-等待直到时钟锁定*/
    SYS_CSVSTAT = systemREG1->CSVSTAT;
    SYS_CSDIS = systemREG1->CSDIS;
    while ((SYS_CSVSTAT &(SYS_CSDIS ^ 0xFFU)& 0xFFU))!=((SYS_CSDIS ^ 0xFFU)& 0xFFU)
    {
    SYS_CSVSTAT = systemREG1->CSVSTAT;
    SYS_CSDIS = systemREG1->CSDIS;
    } /*等待*/
    

    当然、如果您不使用 PLL2、您只需禁用它、而不用担心所有这些。 这也会导致功率降低。