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:在 SLEEP 模式下无法将闪存存储体置于睡眠状态

Guru**** 2754175 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/1609773/tms570lc4357-cannot-put-flash-banks-to-sleep-while-in-sleep-mode

器件型号: TMS570LC4357

 在此问题之后、尝试在器件进入睡眠状态时将闪存组置于睡眠状态(遵循参考手册第 2.4.3.1 节所述的顺序)会在唤醒中断时触发预取错误、最终在睡眠期间将 VDDIO 电流保持在 30mA 附近 (~100mW)、以保持一个闪存组通电、这对于我们的应用来说过高。
我们尝试将 TMS570LS0714PZ_LPC Ms_Wakeup 存储库中的代码调整为我们正在使用的 TMS570LC 器件、但不符合预期结果、因为 TMS570LC 器件缺少寄存器 FBFALLBACK 和 FPAC2 来控制闪存组回退电源模式、只允许通过 FBPWRMODE 寄存器更改当前模式。


将 SHUTDOWN / WAKEUP 序列和 GIO 中断处理程序置于 RAM(.ramTEXT 段)中不会改变结果。

我们是否缺少一些在睡眠模式下将闪存置于睡眠状态的配置?

以下是我们的开关/唤醒序列:


pragma SET_CODE_SECTION(“.ramTEXT")“)

void systemPowerDown(Uint32 模式)

  uint32_t flashFbPwrMode;
  uint32_t clkTest、cdis、cddis、ghvsrc、pllctl1、 pllctl2、pllctl3;

  flashFbPwrMode = flashWREG->FBPWRMODE;//保存配置以在唤醒时恢复它

  clkTest = systemREG1->CLKTEST;
  csdis = systemREG1->CSDIS;
  cddis = systemREG1->CDDIS;
  pllctl1 = systemREG1->PLLCTL1;
  pllctl2 = systemREG1->PLLCTL2;
  pllctl3 = systemREG2->PLLCTL3;
  ghvsrc = systemREG1->GHVSRC;

  systemREG1->CLKTEST =(clkTest &~(1 << 25))|(1 << 24);//禁用范围检测
  pmmTurnOFFLogicPowerDomain (PMM_LOGICPD4);
  pmmTurnOFFLogicPowerDomain (PMM_LOGICPD5);

  while (flashWREG->FBBUSY 和 ((1U << 7)|(1U << 1)|(1U << 0)));//等待所有闪存组处于空闲状态

  FlashWREG->FBAC =(0x00 << 16)//OTP 编程被禁用
          |(0x0F);//用于唤醒的 VREFAD 设置
  flashWREG->FPAC1 &&~1U;//电荷泵备用电源模式=睡眠
  FlashWREG->FBPWRMODE =(3U <<(0 * 2))//闪存组 0 电源模式(0:睡眠、1:待机、3:活动)
             |(0U <<(1 * 2))//闪存组 1 功耗模式(0:睡眠、1:待机、3:活动)
|(0U <<(7 * 2));//闪存组 7 功耗模式(0:睡眠、1:待机、3:活动)

 //禁用时钟源和域
  systemREG1->CSDISSET = MODE & 0x000000FFU;
  systemREG1->CDDIS =(MODE >> 8U)& 0x00000FFFU;

  /*空闲 CPU */
  asm volatile (
    “ WFI \n“// wait-for-Interrupt 指令
    “ nop \n“// 4 个噪声以清除管道
    “ nop \n“
    “ nop \n“
    “ nop \n“
);

  flashWREG->FBPWRMODE = flashFbPwrMode;//唤醒闪存
  systemREG1->CSDISCLR =(~csdis)& 0x31;//首先启用 LF LPO、HF LPO 和振荡器
  if (mode &~csdis &(1U << 1U))//如果禁用了 LP mode pll1
  {
    systemREG1->PLLCTL1 =(0U << 31U) //打滑时无复位
              |(1U << 29U) //启用打滑旁路
              |(0x1F << 24U)//锁定前输出分频器到最大值
              |(pllctl1 和 0x00FFFFFF);

    systemREG1->PLLCTL2 =(0U << 31U)//禁用频率 调制的组合
              |(pllctl2 和 0x7FFFFFFF);
  }
  if (mode &~csdis &(1U << 6U))//如果禁用了 LP 模式、则 pll2
  {
    systemREG2->PLLCTL3 =(7U << 29U)//锁定前输出分频器最大值
              |(pllctl3 和 0x1FFFFFFF);
  }

  systemREG1->CSDIS = cdis;
  systemREG1->CDDIS = cddis;

  //等待时钟被锁定、然后恢复剩余的 PLL 参数
  while ((systemREG1->CSVSTAT &(~cdis)& 0xFF)!=((~cdis)& 0xFF));

  systemREG1->PLLCTL1 = pllctl1;
  systemREG1->PLLCTL2 = pllctl2;
  systemREG1->GHVSRC = ghvsrc;

  //恢复振荡器监视
  systemREG1->CLKTEST = clkTest;

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

    尊敬的法国:

    对延迟的回复表示歉意、我现在正在处理您的问题、并将尽快就此向您回复。

    --
    此致、
    Jagadish。

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

    尊敬的 Jagadish:
    感谢您的答复。

    修改后的实现更改了 2 个事项:
    -它关闭银行 2 到 6 ,这是不存在的;
    -它增加了一个小的延迟和检查 FMSTAT。 由于预取错误发生在唤醒时执行第一行之前、因此这不起作用。 等待或 PLL 锁定时已经增加了延迟。 我添加了 FMSTAT 检查反正,没有任何影响 的问题。

    我已经尝试将唯一的活动中断处理程序 (GIO) 移至 RAM、它对问题没有任何影响。
    勘误表未列出与睡眠模式或将闪存组置于睡眠状态相关的任何内容。
    我看不到预取缓冲区会导致任何问题的任何原因、所有周围代码都在 RAM 中、但我可以尝试禁用它。 你有什么办法呢?

    谢谢。
    此致、
    Loïc μ s

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

    尊敬的 Loic:

    对延迟的回复表示歉意!

    让我们重点关注预取缓冲区问题、这似乎是根本原因。

    禁用预取缓冲区

    以下是一个在 TMS570LC4357 上禁用预取缓冲器的例程:

    void disablePrefetchBuffer(void)
    {
        /* Clear the PBENA bit in FRDCNTL register */
        flashWREG->FRDCNTL &= ~(1U << 0);
        
        /* Optional: Flush the pipeline with NOPs */
        asm volatile ("nop");
        asm volatile ("nop");
        asm volatile ("nop");
        asm volatile ("nop");
        asm volatile ("nop");
    }
    
    void enablePrefetchBuffer(void)
    {
        /* Set the PBENA bit in FRDCNTL register */
        flashWREG->FRDCNTL |= (1U << 0);
    }

    更全面的方法

    由于您仍然遇到问题、让我们尝试更全面的方法:

    void prepareFlashForSleep(void)
    {
        /* 1. Disable prefetch buffer */
        flashWREG->FRDCNTL &= ~(1U << 0);
        
        /* 2. Wait for any ongoing flash operations to complete */
        while (flashWREG->FBBUSY & 0x83);
        
        /* 3. Set appropriate read wait states for low power mode */
        uint32_t temp = flashWREG->FRDCNTL;
        temp &= ~(0xFU << 8);          /* Clear current wait states */
        temp |= (0xFU << 8);           /* Set maximum wait states for reliability */
        flashWREG->FRDCNTL = temp;
        
        /* 4. Configure flash bank power modes */
        flashWREG->FBPWRMODE = (3U << 0)   /* Bank 0 active - contains critical code */
                             | (0U << 2);  /* Bank 1 sleep */
                             
        /* 5. Wait for power mode transition */
        volatile uint32_t delay;
        for(delay = 0; delay < 100; delay++); /* Short delay */
        
        /* 6. Verify flash status */
        while (flashWREG->FBSTAT & 0x00010000);
    }
    
    void restoreFlashAfterWakeup(void)
    {
        /* 1. Restore all flash banks to active mode first */
        flashWREG->FBPWRMODE = 0x0F;  /* All banks active */
        
        /* 2. Wait for transition to complete */
        volatile uint32_t delay;
        for(delay = 0; delay < 100; delay++); /* Short delay */
        while (flashWREG->FBSTAT & 0x00010000);
        
        /* 3. Restore original wait states if needed */
        uint32_t temp = flashWREG->FRDCNTL;
        temp &= ~(0xFU << 8);          /* Clear wait states */
        temp |= (0x2U << 8);           /* Set to default value (adjust as needed) */
        flashWREG->FRDCNTL = temp;
        
        /* 4. Re-enable prefetch buffer */
        flashWREG->FRDCNTL |= (1U << 0);
    }
    --
    此致、
    Jagadish。