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.

[参考译文] Linux/AM4378:DMTimer 从待机状态唤醒

Guru**** 2582405 points
Other Parts Discussed in Thread: AM4378, AM4372

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

https://e2e.ti.com/support/processors-group/processors/f/processors-forum/630170/linux-am4378-dmtimer-wakeup-from-standby

器件型号:AM4378
主题中讨论的其他器件: AM4372

工具/软件:Linux

实际上是否可以使用 DM计时 器上的溢出中断将处理器从待机状态唤醒?

我正在尝试编写一个内核模块、以将 AM4378从待机状态唤醒。  我使用的是 Linux 内核版本4.1.18。  我会使用 DMTimer0、它似乎一直处于打开状态并支持唤醒、但我无法确定如何使用现有的驱动程序访问它。  因此、我决定使用 DMTimer3、因为它可用。

当我没有将处理器置为待机状态时、定时器会正确中断、但一旦处理器进入待机状态、中断就会被忽略。  我将`PRCM_CM_PER_TIMER3_CLKCTRL MODULEMODE`值设置为`2h`、以确保始终启用时钟。  如果我在计时器经过之前手动唤醒电路板、它会在适当的时间中断、因此我很确定中断实际上是在处理器处于待机状态时发生的、但不会唤醒任何内容。   

有关此主题的文档有点少、并且存在一些冲突信息。  在 AM335x (1)和 AM437x (2) TRMS 中、DMTimer (DMTimer0除外)没有唤醒功能、但在 AM335x 电源管理待机用户指南(3)中、它提供了使用 DMTimer7唤醒 AM335x 的示例代码。

那么事实是什么?

(1):AM335x TRM,第4437页,表20-3"闲置/唤醒信号|智能闲置(无唤醒功能)" [http://www.ti.com/lit/ug/spruh73p/spruh73p.pdf]

(2):AM437x TRM,第2752页,表19-3“Idle/Wakeup Signals | Smart Idle (No WAKEUP Capabilities)” [http://www.ti.com/lit/ug/spruhl7g/spruhl7g.pdf]

(3): AM335x 电源管理待机用户指南[ http://processors.wiki.ti.com/index.php/AM335x_Power_Management_Standby_User%27s_Guide#DM_Timer_wakeup]

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    对于 AM437x 器件、DMTimer0是有效的唤醒源。 至于 Linux 支持、实际的 wiki 页面是 processors.wiki.ti.com/.../Linux_Core_Power_Management_User's_Guide_(v4.1)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    感谢您的回复!

    我在链接中没有看到任何有关 DMTimer0作为唤醒器件的信息、但它确实有一些有用的信息。 我还猜测这意味着其他 DMTimers 是*无效的唤醒源吗?

    我将尝试使用直接寄存器存储器操作来将 DMTimer0配置为唤醒源、因为我看不到针对这个特定任务的任何 Linux 支持...
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    作为后续操作、我已将 DMTimer0配置为像 DMTimer3一样溢出、只使用`reADL_LEASGED ()`直接寄存器访问、但现在我无法确定如何正确处理 DMTimer0中断。 ` DMTimer3、我能够使用`omap_dm_timer_request()`re来获取计时器、这允许我调用` omap_dm_timer_get_IRQ ()`、它为我提供了正确的 IRQ 编号、我可以通过内核将其用于` que_IRQ ()。

    如果没有实际的 DMTimer 结构、我无法获取 DMTimer0 IRQ 编号、因此我无法将函数与其中断链接。 我是否有办法使用较低级别的寄存器访问来实现此目的?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Kevin:

    [引用 user ="Kevin Sylvestre93"]是否可以在 DMTimer 上使用溢出中断将处理器从待机状态唤醒?

    是的、我认为这是可能的。

    [引用用户="Kevin Sylvestre93"]我将`PRCM_CM_PER_TIMER3_CLKCTRL MODULEMODE`值设置为`2h`、以确保始终启用时钟。[/QUERT]

    您还可以检查 PRCM_CM_PER_L4LS_CLKSTCTRL[13] CLKACTIVITY_TIMER3_GCLK 和[8] CLKACTIVITY_L4LS_GCLK。

    请注意、通过此 PRCM_CM_PER_TIMER3_CLKCTRL 寄存器、您可以确保功能时钟未门控、但您还应验证接口/互连时钟(L4_PER_CLK、L4LS_GCLK)未门控、请参阅 AM437x TRM:

    6.4.3.2待机

    如果需要额外的或其他唤醒源、相关的外设模块时钟和互连时钟域应保持启用状态(这可能需要相关的 PLL 保持锁定状态)、并且必须通过将其配置为生成一个到 MPUSS 的中断来为唤醒对模块进行适当配置。

    19.1.2.3定时器时钟信号

    定时器[2–7]时钟信号

    [引用用户="Kevin Sylvestre93">有关此主题的文档有点少,并且存在一些冲突的信息。  在 AM335x (1)和 AM437x (2) TRMS 中、DMTimer (DMTimer0除外)没有唤醒功能、但在 AM335x 电源管理待机用户指南(3)中、它提供了使用 DMTimer7唤醒 AM335x 的示例代码。[/引述]

    根据我的理解、您可以使用 DMTimer0和 DMTimer7从待机模式唤醒、但只能使用 DMTimer0从深度睡眠模式唤醒。

    还请确保您符合 AM437x 器件勘误表、建议20 GPTimer:唤醒后读取某些 GPTimer 寄存器所需的延迟

    此致、
    帕维尔

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

    [引用 USER="Kevin Sylvestre93]*作为后续操作,我只使用`reADL_RELEASE_()`直接寄存器访问将 DMTimer0配置为像 DMTimer3一样溢出,但现在我无法确定如何正确处理 DMTimer0中断。 ` DMTimer3、我能够使用`omap_dm_timer_request()`re来获取计时器、这允许我调用` omap_dm_timer_get_IRQ ()`、它为我提供了正确的 IRQ 编号、我可以通过内核将其用于` que_IRQ ()。

    如果没有实际的 DMTimer 结构、我无法获取 DMTimer0 IRQ 编号、因此我无法将函数与其中断链接。 是否有方法可以使用更低级的寄存器访问来实现此目的?

    检查下面的 e2e 线程是否有帮助:

    e2e.ti.com/.../599114

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

    您好、Pavel、

    感谢您迄今提供的帮助!  我又回到了 DMTimer 3模式、在进入待机模式之前和之后、似乎所有时钟都已被适当启用(它们的寄存器值处于所需的状态)。。。   

    待机前:

    • PRCM_CM_PER_L4LS_CLKCTRL  [1-0]  MODULEMODE        = 2h (接口时钟、显式启用)
    • PRCM_CM_PER_L4LS_CLKCTRL  [17-16] IDLST           = 2h (接口时钟、模块完全正常工作)
    • PRCM_CM_PER_TIMER3_CLKCTRL [1-0]  MODULEMODE        = 2h (功能时钟、显式启用)
    • PRCM_CM_PER_TIMER3_CLKCTRL [17-16] IDLEST          = 2h (功能时钟、模块完全正常工作)
    • PRCM_CM_PER_L4LS_CLKSTCTRL [8]   CLKACTIVITY_L4LS_GCLK  = 1h (接口时钟有效)
    • PRCM_CM_PER_L4LS_CLKSTCTRL [13]  CLKACTIVITY_TIMER3_GCLK = 1h (功能时钟有效)
    • PRCM_CM_PER_L4LS_CLKSTCTRL [1-0]  CLKTRCTRL         = 0h (NO_SLEEP:无法启动睡眠转换...)

    请注意、在初始设置为2h 后重新读取 PRCM_CM_PER_L4LS_CLKSTCTRL [1-0] CLKTRCTRL 会产生2h;不确定这是否是问题、但似乎不会在"NO_SLEEP"上保持设置。   

    在这种配置下、只要处理器未设置为待机、定时器就会在适当的时间段后正确中断。  如果处理器设置为待机、则定时器会在系统唤醒后中断。  例如:

    通常...

      # echo 10000 >/sys/kernel/standy-timer/standby_time_ms

      [907.118484] 启动待机计时器

      #[917.117724) 待机计时器已过期

    如您所见、大约经过10000ms (907.118s -> 917.118s = 10000ms)。

    或者、运行具有待机功能的计时器...

      # echo 10000 >/sys/kernel/standy-timer/standby_time_ms

      [1157.227378]正在启动待机计时器

      # echo "standby">/sys/power/state

      [1161.360338] PM:正在同步文件系统... 完成。

      [1161.401763]冻结用户空间进程... (已用0.001秒)。

      [1161.410082]冻结剩余可自由运行的任务... (已用0.001秒)。

      [1161.427833]暂停控制台(使用 NO_console_suspend 进行调试)

      <任意延迟、然后使用 UART 击键手动唤醒>

      [1161.458759] OMAP-hwmod:ADC_TSC:_WAIT_TARGET_DISABLE 失败

      [1161.460424] PM:25.558毫秒后设备挂起完成

      [1161.461716] PM:1.269ms 后器件延迟挂起完成

      [1161.463291] PM:1.553ms 后器件暂停完成

      [1161.463298] PM:成功地将所有电源域置于目标状态

      [1161.463298] PM:唤醒源 UART

      [1161.479192] PM:15.856ms 后器件的 noirq 恢复完成

      [1161.480508] PM:1.045毫秒后完成设备的早期恢复

      [1161.481089] net eth0:正在初始化 cpsw 版本1.15 (0)

      [1161.482274] libphy:找不到 PHY 4a101000.MDIO:00

      [1161.482283] Net eth0:PHY 4a101000.MDIO:00未在从器件0上找到

      [1161.557224] net eth0:找到的 PHY:id 是:0x2000a240

      [1161.762268] PM:281.734毫秒后器件恢复完成

      [1161.844410]正在重新启动任务... 完成。

      #[1167.227358]待机计时器过期

    同样、计时器根据系统时间在10000ms 内过期(1157.227s -> 1167.227s = 10000ms)。  这让我相信、当处理器进入待机状态时、时钟很可能不会保持启用状态。   

    我想知道突出显示的部分是否相关:

    6.4.3.2待机

    如果需要额外的或其他唤醒源、相关的外设模块时钟和互连时钟域应保持启用状态(这可能需要相关的 PLL 保持锁定状态)、并且必须通过将其配置为生成一个到 MPUSS 的中断来为唤醒对模块进行适当配置。

    当我进入待机模式时、如何保持 PLL 锁定和/或使其不关闭?  在 TRM 的第6.4.3节中、表6-13指示主振荡器应在待机模式下保持开启状态、但所有 DPLL 均处于旁路模式。  我使用`CLK_M_OSC`作为 DMTimer 3的时钟源、因此我猜这意味着 TIMER3_GCLK (我的 PICLKTIMER 功能时钟)可能还可以、但可能我仍然会丢失 L4LS_GCLK (我的 PICLKCP 接口时钟)。  理想情况下、我更喜欢一种能够利用现有驱动程序的方法、但此时这并不是很重要。

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

    [引用 USER="Kevin Sylvestre93"] PRCM_CM_PER_L4LS_CLKCTRL  [17-16] IDLST           = 2h (接口时钟、模块完全正常工作)

    [引用 USER="Kevin Sylvestre93"] PRCM_CM_PER_TIMER3_CLKCTRL [17-16] IDLEST          = 2h (功能时钟、模块完全正常工作)

    您能否再次检查该值? IDLEST = 0x2空闲、不起作用。 正确的值应为0x0

    [引用用户="Kevin Sylvestre93">当我进入待机状态时、如何保持 PLL 锁定和/或保持 PLL 不关闭?  在 TRM 的第6.4.3节中、表6-13指示主振荡器应在待机模式下保持开启状态、但所有 DPLL 均处于旁路模式。  我使用`CLK_M_OSC`作为 DMTimer 3的时钟源、因此我猜这意味着 TIMER3_GCLK (我的 PICLKTIMER 功能时钟)可能还可以、但可能我仍然会丢失 L4LS_GCLK (我的 PICLKCP 接口时钟)。  理想情况下、我更喜欢一种使我能够利用现有驱动程序的方法、但此时这并不是很重要。

    L4LS_GCLK 由内核 PLL 生成、确保内核 PLL 在待机期间处于活动状态。 您应该在待机和待机期间(使用 CCS/JTAG)检查内核 PLL 寄存器。 请参阅 AM437x TRM 第6.6.7节"内核 PLL 说明"

    CORE_CLKOUTM4 ->/2 -> L4_PER_CLK -> L4LS_GCLK -> DMTimer3

    您还应在待机期间使用 CCS/JTAG 检查 TIMER3_GCLK 和 L4LS_GCLK PRMC 相关寄存器。 有关详细信息、请参阅 belowwiki 页面:

    此致、
    帕维尔

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

    啊、是的、很抱歉、这是一个"复制和粘贴"错误...  它们正确为"0h"。  我将在待机期间通过 JTAG 确认寄存器值后进行跟进。

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

    关于 DMTIMER3功能时钟、您还可以通过跟踪 Linux 内核计时器驱动程序来检查它的状态(除了在待机期间通过 CCS/JTAG 转储 PRCM 寄存器)。 该时钟称为 timer3_fck:

    linux-kernel/drivers/clk/ti/clk-43xx.c
    linux-kernel/arch/arm/boot/dts/am43xx-clocks.dtsi
    linux-kernel/arch/arm/boot/dts/am4372.dtsi

    计时器驱动程序为:

    linux-kernel/arch/arm/mach-omap2/timer.c
    linux-kernel/arch/arm/plat-omap/dmtimer.c

    您可以跟踪(使用 printk 和/或断点)暂停/恢复流如何通过这两个文件以及中止/恢复如何影响 fck。

    关于 DMTIMER3互连时钟和 DPLL_CORE、您可以跟踪以下代码:

    (DPLL_CORE_CK -> DPLL_CORE_x2_CK -> DPLL_CORE_M4_CK -> SYSCLK_div -> DPLL_CORE_M4_DIV2_CK -> l4ls_gclk)

    linux-kernel/drivers/clk/ti/DPLL.c

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

    您好、Pavel、

    我能够使用此处详述的一些方法在待机期间确认寄存器值(http://processors.wiki.ti.com/index.php/Debugging_AM335x_Suspend-Resume_Issues#Inspecting_the_SoC_state_immediately_prior_to_entering_DeepSleep0)。

    我想、由于进入待机状态、寄存器值被强制进入不同的状态。  即使在待机之前、我设置 了 PRCM_CM_PER_L4LS_CLKCTRL 和  PRCM_CM_PER_TIMER3_CLKCTRL、以便明确启用这些模块(MODULEMODE = 2h)、 PRCM_CM_PER_TIMER3_CLKCTRL 在待机期间显示 IDLEEST= 3h、指示模块已禁用。

    我使用标准的 Linux echo "STANDBY->/sys/kernel/power 命令进入 STANDBY、我相信这会调用到片上 Cortex M3的固件中、我对此并不是很熟悉。  我是否需要修改此处的固件以从根本上更改待机模式、或者是否可以从 A9内核保持这些时钟处于活动状态?

    谢谢、

    Kevin

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

    我已经附加了4个寄存器转储、我使用上面链接中脚本的修改版本执行了这些转储。  文件如下:

    • "...163117.RD1.txt"=以 root 身份登录 Linux 后立即捕获
    • "...163138.RD1.txt"=在加载自定义模块后立即捕获(_init 函数包含一些寄存器操作)
    • "...163155.RD1.txt"=在 DMTimer 3上设置超时值后立即捕获(请注意、出于某种原因、DMTImer3的寄存器值全部显示为0... 读取寄存器的其他方法显示了正确的信息
    • "...163209.RD1.txt"=进入待机状态后立即捕获(M3保持在循环中)

    /cfs-file/__key/communityserver-discussions-components-files/791/8255.am335x_2D00_ctt_5F00_2017_2D00_10_2D00_16_5F00_163117.txt

    /cfs-file/__key/communityserver-discussions-components-files/791/3060.am335x_2D00_ctt_5F00_2017_2D00_10_2D00_16_5F00_163138.txt

    /cfs-file/__key/communityserver-discussions-components-files/791/am335x_2D00_ctt_5F00_2017_2D00_10_2D00_16_5F00_163155.txt

    /cfs-file/__key/communityserver-discussions-components-files/791/am335x_2D00_ctt_5F00_2017_2D00_10_2D00_16_5F00_163209.txt

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

    Kevin、

    [引用用户="Kevin Sylvestre93"]

    我想、由于进入待机状态、寄存器值被强制进入不同的状态。  即使在待机之前、我设置 了 PRCM_CM_PER_L4LS_CLKCTRL 和  PRCM_CM_PER_TIMER3_CLKCTRL、以便明确启用这些模块(MODULEMODE = 2h)、 PRCM_CM_PER_TIMER3_CLKCTRL 在待机期间显示 IDLEEST= 3h、指示模块已禁用。

    我使用标准的 Linux echo "STANDBY->/sys/kernel/power 命令进入 STANDBY、我相信这会调用到片上 Cortex M3的固件中、我对此并不是很熟悉。  我是否需要修改此处的固件以从根本上更改待机模式、或者是否可以从 A9内核保持这些时钟处于活动状态?

    [/报价]

    在调试 Cortex-M3固件之前、我建议您调试计时器驱动程序。 请查看以下帖子中的我的提示:

    此致、
    帕维尔

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

    [引用用户="Kevin Sylvestre93"]

    我已经附加了4个寄存器转储、我使用上面链接中脚本的修改版本执行了这些转储。  文件如下:

    • "...163117.RD1.txt"=以 root 身份登录 Linux 后立即捕获
    • "...163138.RD1.txt"=在加载自定义模块后立即捕获(_init 函数包含一些寄存器操作)
    • "...163155.RD1.txt"=在 DMTimer 3上设置超时值后立即捕获(请注意、出于某种原因、DMTImer3的寄存器值全部显示为0... 读取寄存器的其他方法显示了正确的信息
    • "...163209.RD1.txt"=进入待机状态后立即捕获(M3保持在循环中)

    [/报价]

    从最后一个日志(进入待机模式后)中、我看到 timer3_fck 变为禁用状态、而 l4ls_gclk 保持启用状态。 您可以专注于调试受计时器驱动程序中暂停/恢复流程影响的 timer3_fck。 请参阅以下 e2e 帖子中的我的提示:

    此致、
    帕维尔