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.

[参考译文] TMS570LS1224:SafetyDiag + LowPowerMode 问题

Guru**** 2558250 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/854267/tms570ls1224-safetydiag-lowpowermode-issue

器件型号:TMS570LS1224

您好!

此问题是指与低功耗模式相关的安全诊断。

在 TMS570LS1224上实现低功耗模式期间 、我发现(使用  帮助)对于某些配置、我无法切换到低功耗模式(QJ Wang 注意  到 SYS_STARTUP 源文件中的 PBIST 可能存在问题。 看起来 MCU 切换到低功耗模式、无法唤醒... 当他注释掉大部分安全检查代码时、低功耗模式工作正常。

现在我进一步研究、结果我知道、如果我想使用低功耗模式功能、应该禁用一些安全功能。 在下图中,您可以看到我的工作配置(使用此配置,我可以成功唤醒)。 如果我检查、例如 MIBSPI1或 HET 低功耗模式将崩溃(无法唤醒)。 原因是什么? 是否可以添加这些安全检查并在低功耗模式下工作?

/*唤醒中断:RTI 比较0 */
vimREG->WAKEMASKCLR0 = 0xFFFFFFFF;
vimREG->WAKEMASKCLR1 = 0xFFFFFFFF;
vimREG->WAKEMASKCLR2 = 0xFFFFFFFF;
vimREG->WAKEMASKSET0 =(1U <<2U)/* RTI CAP0 */
|(1U <<23U)/* GPIO 低*/
|(1U <<16U);/* CAN1 High */

/*闪存*/ flashWREG->FPAC2 = 0x7; flashWREG->FMAC = 0x6; flashWREG->FBAC = 0x70F; flashWREG->FMAC = 0x0; flashWREG->FBAC = 0x70F; /*设置闪存组电源模式*/ flashWREG->FBFALBACK = 0x000000000000 |(UINT32)((UINT32) SYS_SLEEP << 14U)//组7 */ |(UINT32)((UINT32) SYS_SLEEP << 0U);//组0 */ /*闪存电荷泵降级功率模式*/ flashWREG->FPAC1 &=(1UL <<0); //进入打盹模式 /*重置 RTI 计数器0 */ rtiStopCounter (rtiCOUNTER_BLOCK0); rtiResetCounter (rtiCOUNTER_BLOCK0); /*使用 OSCIN 的时钟 RTI */ systemREG1->RCLKSRC = 0x0; /*唤醒时间设置*/ rtiREG1->CMP[0U].Compx = 30000000U; rtiREG1->CMP[0U].UCPx = 30000000U; rtiREG1->INTFLAG = 0x0007000FU; rtiREG1->CLEARINTENA= 0x00070F0FU; rtiREG1->SETINTENA = rtiNOTIFICATION_COMPARE0; /*起始计数器0 */ rtiStartCounter (rtiCOUNTER_BLOCK0); /**-为正常运行、断电模式和唤醒后设置 GCLK、HCLK 和 VCLK 时钟源*/ systemREG1->GHVSRC =(UINT32)((UINT32) SYS_OSC << 24U) |(UINT32)((UINT32) SYS_OSC << 16U) |(UINT32)((UINT32) SYS_PLL1 << 0U); systemREG1->CSDISSET = 0xFE; systemREG1->CDDISSET = 0xFFBF; asm (" NOP"); asm (" NOP"); asm (" NOP"); asm (" WFI"); asm (" NOP"); asm (" NOP"); asm (" NOP"); asm (" NOP");

在我的开机自检唤醒代码下面:

systemREG1->CSDISCLR = 0x31;

/*将闪存组/泵回退模式重新配置为"有效"*/
flashWREG->FBFALBACK = 0x000000000000
|(UINT32)((UINT32) SYS_ACTIVE << 14U)//组7 */
|(UINT32)((UINT32) SYS_ACTIVE << 0U);//组0 */

mapClocks(); 

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

    您好、Michal、

    我将对此进行研究、并在今天稍后的时间返回给您。

    此致、Sunil

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

    米歇尔

    我能够使器件进入打盹模式、即使每次安全诊断检查都被启用(CPU 和 CCM 自检除外)。 您是否记得禁用主振荡器的监控? 您正在禁用除主振荡器之外的所有时钟源、因此时钟监视器将检测到"振荡器故障"并将时钟域切换到已禁用的 HF LPO 时钟源。 这会导致代码尝试使用不可用的时钟源执行的状态、并且需要使用看门狗 PMIC 等外部安全监控器来复位器件。

    /*禁用振荡器监控以防止检测到振荡器故障*/
    systemREG1->CLKTEST = 0x010A0000;

    此致、Sunil

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

    您好、Michal、

    我正在粘贴代码以进入打盹模式:

    int main (void)
    {
    /*用户代码 begin (3)*/
    
    unsigned int 命令;
    
    /*初始化 RTI、由 OSCIN 计时/2 = 8MHz、每1秒生成比较0中断/唤醒*
    rtiInit();
    
    /*初始化 GIO:GIOB[2]、引脚142被用作唤醒源、GIOA[1:0]被用来选择 LPM */
    gioInit();
    
    /*启用 CPU 对中断请求的响应*/
    _enable_interrupt_();
    
    while (1)
    {
    命令= gioGetPort (gioPORTA)& 0x3; //读取 GIOA[1:0]端口状态
    
    如果(命令= 0x0)
    {
    /*保持活动*/
    }
    其他
    {
    /* GIOA[1:0]配置为进入其中一种低功耗模式*/
    
    /*将闪存泵激活宽限期设置为7个 HCLK/16个周期*/
    flashWREG->FPAC2 = 0x7;
    
    /*银行7 */
    flashWREG->FMAC = 0x6;
    flashWREG->FBAC = 0x70F;
    
    /*组0 */
    flashWREG->FMAC = 0x0;
    flashWREG->FBAC = 0x70F;
    
    /*设置闪存模块以将组/泵的回退模式更改为"睡眠"*/
    flashWREG->FBFALBACK = 0x000000000000
    |(UINT32)((UINT32) SYS_SLEEP << 14U)//组7 */
    |(UINT32)((UINT32) SYS_SLEEP << 2U)/*组1 */
    |(UINT32)((UINT32) SYS_SLEEP << 0U);//组0 */
    
    /*禁用振荡器监控以防止检测到振荡器故障*/
    systemREG1->CLKTEST = 0x010A0000;
    
    /*根据 GIOA[1:0]进入低功耗模式*/
    if (命令==打盹)
    {
    enter_doze(); //通过由 OSCIN 计时的 RTI 唤醒
    }
    否则(命令== snooze)
    {
    ENTER_snooze(); //通过由 LF LPO 计时的 RTI 唤醒
    }
    其他
    {
    enter_sleep(); //仅通过 GIOB[2]上升沿唤醒
    }
    post_wakeup();
    
    }
    }/*
    
    用户代码结束*/
    
    返回0;
    }
    
    
    /*用户代码开始(4)*/
    
    void enter_doze (void)
    {
    /* RTI 被配置为每隔10秒生成比较0中断,使用16MHz OSCIN 作为源*/
    /*重置并重新启动 RTI 计数器0 */
    rtiStopCounter (rtiCOUNTER_BLOCK0);
    rtiResetCounter (rtiCOUNTER_BLOCK0);
    
    /**-清除所有挂起的中断*/
    rtiREG1->INTFLAG = 0x0007000FU;
    
    /**-禁用所有中断*/
    rtiREG1->CLEARINTENA= 0x00070F0FU;
    
    /**-启用 RTI 比较0中断**/
    rtiREG1->SETINTENA = rtiNOTIFICATION_COMPARE0;
    
    /*起始计数器0 */
    rtiStartCounter (rtiCOUNTER_BLOCK0);
    
    /**-为正常运行、断电模式和唤醒后设置 GCLK、HCLK 和 VCLK 时钟源*/
    systemREG1->GHVSRC =(UINT32)((UINT32) SYS_OSC << 24U)
    |(UINT32)((UINT32) SYS_OSC << 16U)
    |(UINT32)((UINT32) SYS_PLL1 << 0U);
    
    /*关闭除主振荡器之外的所有时钟源*/
    systemREG1->CSDISSET = 0xFE;
    
    /*关闭除 RTICLK 以外的所有时钟域*/
    systemREG1->CDDISSET = 0xFFBF;
    
    asm (" WFI");
    asm (" nop");
    asm (" nop");
    asm (" nop");
    asm (" nop");
    }
    
    void post_wakeup (void)
    {
    /*切换 GIOA[7]以发出唤醒信号*/
    gioSetPort (gioPORTA、gioGetPort (gioPORTA)^0x80);//切换 GIOA[7]
    
    /*重新启动主振荡器、LF LPO 和 HF LPO 优先*/
    systemREG1->CSDISCLR = 0x31;
    
    /*根据原始配置配置配置 PLL */
    /**-设置 PLL 控制寄存器1:
    * -振荡器跳周时的设置复位
    * —设置 PLL 跳周旁路
    * -在锁定前将 PLL 输出时钟分频器设置为最大值
    * -振荡器故障时的设置复位
    * -设置参考时钟分频器
    * —设置 PLL 倍频器
    *
    systemREG1->PLLCTL1 =(uint32) 0x00000000U
    |(UINT32) 0x20000000U
    |(UINT32)((UINT32) 0x1FU << 24U)
    |(UINT32) 0x00000000U
    |(UINT32)((UINT32)(6U - 1U)<<16U)
    |(uint32)((uint32)(165U - 1U)<<8U);
    
    /**-设置 PLL 控制寄存器2
    * -设置传播速率
    * -设置带宽调整
    * —设置内部 PLL 输出分频器
    * -设置摊铺量
    *
    systemREG1->PLLCTL2 =(uint32)((uint32) 255U << 22U)
    |(uint32)((uint32) 7U << 12U)
    |(uint32)((uint32)(2U-1U)<<9U)
    |(uint32) 61U;
    
    /*重新启动所有其它时钟源。 所有时钟域都将自动启用。 *
    systemREG1->CSDISCLR = 0xFF;
    
    /*将闪存组/泵回退模式重新配置为"有效"*/
    /**-设置闪存组电源模式*/
    flashWREG->FBFALBACK = 0x000000000000
    |(UINT32)((UINT32) SYS_ACTIVE << 14U)//组7 */
    |(UINT32)((UINT32) SYS_ACTIVE << 2U)/*组1 */
    |(UINT32)((UINT32) SYS_ACTIVE << 0U);//组0 */
    
    
    /*恢复原始时钟源/域绑定*/
    mapClocks();
    
    /*恢复振荡器监控*/
    systemREG1->CLKTEST = 0x000A0000;
    
    }
    

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

    Sunil、

    我已添加至代码"可禁用并启用振荡器监控"、但在启用某些存储器内置自检时、唤醒(使用 RTI)仍有问题。

    在代码中,在 post_wake()中设置 PLLCTL1、 PLLCTL2,然后使用 mapClock();这样做的原因是什么? 在 mapClocks()中,还设置了 PLLCTL1和2。

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

    米歇尔

    mapClocks()仅配置 PLL 控制寄存器中的最终分频器级。 其它分频器的配置由 setupPLL()函数在该函数之外完成。

    作为实验,您能否将 pbistStop()函数更新为如下所示:

    void pbistStop (void)
    {
    //用户代码开始(20)*/
    
    pbistREG->PACT = 0x0U;
    systemREG1->MSTGCR &= 0xFFFFFFF0U;
    systemREG1->MSTGCR |= 0xAU;
    systemREG1->MSTGCR &= 0xFFFFFFF0U;
    systemREG1->MSTGCR |= 0x5U;
    
    #if 0
    
    //用户代码结束*/
    /*禁用 pbist 时钟和 ROM 时钟*/
    pbistREG->PACT = 0x0U;
    systemREG1->MSTGCR &= 0xFFFFFFF0U;
    systemREG1->MSTGCR |= 0x5U;
    //用户代码开始(21)*/
    
    #endif
    
    //用户代码结束*/
    } 

    此致、Sunil

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

    米歇尔

    您是否能够正确设置进入/退出打盹模式?

    此致、Sunil