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.

[参考译文] TM4C1231H6PM:勘误表 SYSCTL#01

Guru**** 2526340 points


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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/773146/tm4c1231h6pm-errata-sysctl-01

器件型号:TM4C1231H6PM
主题中讨论的其他器件:TM4C123

大家好、

我有一个从某些传感器采样数据、然后进入深度睡眠模式的系统。 系统从深度睡眠模式唤醒的方法是通过来自外部源的 GPIO 中断。 我的系统有多个 GPIO 中断源、因此我的系统可以由不同的源进行唤醒。

后来我意识到、我的系统偶尔不会从深度睡眠模式唤醒。 在查看 TM4C123勘误表后、我意识   到我的系统设置解决了 SYSCTL_01问题、对于特定的时钟配置、器件可能无法从深度睡眠模式唤醒。

因此、我选择了权变措施、在进入深度睡眠模式之前禁用 PLL、并在触发 GPIO 中断时启用 PLL (在单独的 ISR 中启用 PLL)

这是一个问题;在进入深度睡眠之前、我将禁用 PLL、但是、如果在深度睡眠 API 被调用之前的这一刻、GPIO 中断进入并启用 PLL、那么我的系统在进入深度睡眠之前处于勘误表的状态、 这将使我的系统有可能无法从深度睡眠中唤醒。

//伪代码

 

//典型 GPIO ISR

void GPIO_ISR (){

enable_pll ();

做 ISR 工作...

(笑声)

//运行状态(唤醒状态)的时钟设置

SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTAL_XTAL_16MHz | SYSCTL_USE_PLL | SYSCTL_OSC_MAIN);

//.... 进入深度睡眠之前的步骤

SysTickDisable()

系统深度睡眠时钟集(SYSCTL_DSLP_DIV_4 | SYSCTL_DSLP_OSC_INT30 | SYSCTL_DSLP_PIOSC_PD);

SysCtlClockSet (SYSCTL_SYSDIV_4 | SYSCTL_XTAL_16MHz | SYSCTL_USE_OSC | SYSCTL_OSC_MAIN); //禁用 PLL

SysCtlDeepSleep PowerSet (SYSCTL_TEMP_LOW_POWER | SYSCTL_FLASH_LOW_POWER | SYSCTL_SRAM_LOW_POWER);

SysCtlLDODeepSlepSet (SYSCTL_LDO_0_90V);

>>哦、这里没有 GPIO 中断、并且启用 PLL <<<

SysCtlDeepSleep ();

我认为这个问题的一个原因是将代码的这个部分包含在一个临界区内、这样应该防止中断在这个期间改变我的 PLL 设置。 但是、在离开临界区和进入深度睡眠之间、中断仍然存在一小段距离。 因此,我的这种变通办法还不够好。

有人能帮我解决这个问题吗? 我是否有任何方法可以禁用 PLL 并平稳进入深度睡眠而不受任何干扰? 我不希望更改我的系统设置、也不使用 PIOSC、但我们非常感谢任何权变措施。

提前感谢!

Jacky

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在中断例程中、您能否检查 PLL 是否被禁用? 如果是、请启用它、执行中断工作、然后在返回到进入深度睡眠的代码之前再次禁用它。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bob:


    感谢您的回复。 是的、我可以检查 PLL 的状态。

    顺便说一下、我的系统使用 FreeRTOS。 我的系统的设计是、如果它处于运行状态、它将保持运行状态、除非有明确的命令指示它进入深度睡眠状态。 如果处于深度睡眠状态、并且触发了 GPIO 中断、则系统将唤醒、处理 ISR 并保持运行状态(除非命令指示它进入深度睡眠状态、否则不会进入深度睡眠状态)。

    以下是 GPIO ISR 的简要结构、其中考虑了您的建议:

    void GPIO_ISR(){
    
    if (PLL is disabled){
    enable_pll();
    DO _ISR_eroes();
    disable_pll();
    }否则{
    DO _ISR_eroes();
    }
    
    


    我的顾虑:

    如果我的系统当前处于深度睡眠状态、这意味着 PLL 处于禁用状态、那么 GPIO 中断进入、处理中断、然后禁用 PLL、但由于我的系统应保持运行状态、我应该启用 PLL。

    2.与上述相同的情形,如果 Do _ISR_ITESS()实际上正在发送消息队列以解除任务的阻断,该怎么办? 如果 PLL 被禁用、我的未阻止任务是否会正常运行?  

    谢谢、

    Jacky

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这是一个好问题。 WFI 指令之后的指令应该重新使能 PLL。 禁用所有中断、禁用 PLL、然后仅启用可使系统脱离深度睡眠(GPIO)的中断、然后执行 WFI 指令是合理的。 在 WFI 指令之后、应启用 PLL、然后启用其他中断。

    这会给我带来一个独立于 PLL 问题的问题。 当您在执行 WFI 指令之前获取 GPIO 中断并在中断例程中解除任务阻止时、会发生什么情况。 当中断返回时、您可以在 RTOS 评估任务未被阻止之前执行 WFI 指令。 然后、您必须等待下一个 GPIO 事件再次唤醒器件。 您几乎想在 GPIO 中断例程中找到一种方法、在从中断返回时确定不想执行 WFI 指令。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Bob:


    是的、这是我要进入的方向。

    顺便说一下、我刚刚找到了另一个解决此问题的潜在解决方案、请告诉我这是否正常。

    此解决方案需要修改 SysCtlDeepSleep () API。

    具体来说、我将把它放置在 SysCtlDeepsleep () API 中、而不是每次我进入 ISR (当前代码流)时调用 Enable_PLL()、而是像这样:

    void
    SysCtlDeepSleep (void)
    {
    //
    //启用深度睡眠。
    //
    HWREG (NVIC_SYS_CTRL)|= NVIC_SYS_CTRL_SLEEPDEEP;
    
    //
    等待中断。
    //
    CPUwfi();
    
    //
    禁用深度睡眠,以便将来的睡眠正常工作。
    //
    HWREG (NVIC_SYS_CTRL)&&~(NVIC_SYS_CTRL_SLEEPDEEP);
    
    >>插入 Enable_PLL ();此处<<
    } 

    或者、我可以将 Enable_PLL()恰好放在 SysCtlDeepsle()调用之后。

    这样、当我离开睡眠状态时、我将仅启用 PLL。 这将防止在进入深度睡眠之前由于 ISR 而对 PLL 进行任何修改

    请告诉我您的想法。


    谢谢、
    Jacky

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    是的、这更好。 我担心、由于执行时间的原因、您需要在中断服务例程中重新启用 PLL。 但是、如果 ISR 很短(和正常情况一样)、最好不要在 WFI 指令之后重新启用。