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.

关于dm365/dm368对deepsleep支持



我阅读手册发现dm368是对deepsleep支持的,我用的内核是2.6.32版本,在mach-davinci没有sleep.S和pm.c文件,请问是dm368平台在2.6版本内核不支持deepsleep吗,我根据3.2版本关于da850对于deepsleep实现的sleep.S和pm.c修改,想实现dm368休眠,但是suspend_devices_and_enter-->dpm_suspend_start()-->dpm_suspend-->device_suspend()失败。我想问dm368支持RAM to suspend吗,关于sleep.S pm.c 需要自己编写吗,还是已经实现,如果已经实现在哪里,怎么配置,如何实现 深度休眠

  • Shi Yanlong,

    硬件上是支持的。但软件上没有官方支持。

    我建议你阅读一下dm36x deepsleep的相关章节,了解进入和退出的流程,重要的是,进入后退出的时候代码必须在芯片内部RAM里面,因为DDR也会需要进入自刷新模式。

  • 我已经根据相关文档进行配置,并添加了pm.c和sleep.S,分别实现代码拷贝到sram 和ddr自刷新等,并最为suspend->enter实现函数,但是当进行休眠操作时,内核完成准备,进行挂起时失败,我打开console打印如下

    # echo mem > /sys/power/state
    [ 14.510000] PM: Syncing filesystems ... IRQs on FIQs on Mode SVC_32 ISA ARM Segment user
    [ 14.580000] Control: 0005317f Table: 828a0000 DAC: 00000015
    [ 14.580000] Process sh (pid: 1003, stack limit = 0xc28d4270)
    [ 14.580000] Stack: (0xc28d5e48 to 0xc28d6000)
    [ 14.580000] 5e40: c28d5e6c c28d5e58 c022927c c0226e20 c03ec910 c03f5770
    [ 14.580000] 5e60: c28d5e9c c28d5e70 c02297f0 c0229254 c2195e60 c21a6858 c0304cac 00000000
    [ 14.580000] 5e80: 00000003 00000003 c0309610 c292f000 c28d5ebc c28d5ea0 c00d3410 c0229468
    [ 14.580000] 5ea0: 00000000 00000003 00000003 c0309610 c28d5ed4 c28d5ec0 c00d360c c00d33e0
    [ 14.580000] 5ec0: c037bcc1 00000003 c28d5efc c28d5ed8 c00d2d60 c00d3570 00000004 c201a570
    [ 14.580000] 5ee0: c29bc140 c2019640 c03e7d44 c28d5f70 c28d5f0c c28d5f00 c01d5f10 c00d2cd8
    [ 14.580000] 5f00: c28d5f3c c28d5f10 c014d014 c01d5f00 c28d5f70 c28a5300 4001f000 c28d5f70
    [ 14.580000] 5f20: 00000004 00000004 c28d4000 00000000 c28d5f6c c28d5f40 c0102f74 c014cf14
    f50 c00a9020 00000000 00000000 c28a5300 00000004 4001f000
    [ 14.580000] 5f60: c28d5fa4 c28d5f70 c01030e4 c0102ecc 00000000 00000000 c28d5fa4 00000000
    [ 14.580000] 5f80: c0110168 00000004 4001f000 401fa5e8 00000004 c008d0c4 00000000 c28d5fa8
    [ 14.580000] 5fa0: c008cf40 c01030b0 00000004 4001f000 00000001 4001f000 00000004 00000000
    [ 14.580000] 5fc0: 00000004 4001f000 401fa5e8 00000004 00000004 000dc29c 00000000 00000000
    [ 14.580000] 5fe0: 4001f000 bea765f0 40138c70 40188abc 60000010 00000001 e59f0b0c ebfe84b4
    [ 14.580000] Backtrace:
    [ 14.580000] [<c0226e10>] (platform_pm_suspend+0x0/0x64) from [<c022927c>] (pm_op+0x38/0x7c)
    [ 14.580000] [<c0229244>] (pm_op+0x0/0x7c) from [<c02297f0>] (dpm_suspend_start+0x398/0x4c8)
    [ 14.580000] r5:c03f5770 r4:c03ec910
    [ 14.580000] [<c0229458>] (dpm_suspend_start+0x0/0x4c8) from [<c00d3410>] (suspend_devices_and_enter+0x40/0x190)
    [ 14.580000] r8:c292f000 r7:c0309610 r6:00000003 r5:00000003 r4:00000000
    [ 14.580000] [<c00d33d0>] (suspend_devices_and_enter+0x0/0x190) from [<c00d360c>] (enter_state+0xac/0xe8)
    [ 14.580000] r7:c0309610 r6:00000003 r5:00000003 r4:00000000
    [ 14.580000] [<c00d3560>] (enter_state+0x0/0xe8) from [<c00d2d60>] (state_store+0x98/0xc0)
    [ 14.580000] r5:00000003 r4:c037bcc1
    [ 14.580000] [<c00d2cc8>] (state_store+0x0/0xc0) from [<c01d5f10>] (kobj_attr_store+0x20/0x24)
    [ 14.580000] [<c01d5ef0>] (kobj_attr_store+0x0/0x24) from [<c014d014>] (sysfs_write_file+0x110/0x148)
    [ 14.580000] [<c014cf04>] (sysfs_write_file+0x0/0x148) from [<c0102f74>] (vfs_write+0xb8/0x164)
    [ 14.580000] [<c0102ebc>] (vfs_write+0x0/0x164) from [<c01030e4>] (sys_write+0x44/0x70)
    [ 14.580000] r8:4001f000 r7:00000004 r6:c28a5300 r5:00000000 r4:00000000
    [ 14.580000] [<c01030a0>] (sys_write+0x0/0x70) from [<c008cf40>] (ret_fast_syscall+0x0/0x28)
    [ 14.580000] r8:c008d0c4 r7:00000004 r6:401fa5e8 r5:4001f000 r4:00000004
    [ 14.580000] Code: bad PC value
    [ 14.900000] ---[ end trace 32fb04b6b288923f ]---

    定位代码是在

    static int device_suspend(struct device *dev, pm_message_t state)
    {
    int error = 0;

    down(&dev->sem);

    if (dev->class) {

    if (dev->class->pm) {
    pm_dev_dbg(dev, state, "class ");
    error = pm_op(dev, dev->class->pm, state);
    } else if (dev->class->suspend) {
    pm_dev_dbg(dev, state, "legacy class ");
    error = dev->class->suspend(dev, state);
    suspend_report_result(dev->class->suspend, error);
    }
    if (error)
    goto End;
    }

    if (dev->type) {
    if (dev->type->pm) {
    pm_dev_dbg(dev, state, "type ");
    error = pm_op(dev, dev->type->pm, state);
    }
    if (error)
    goto End;
    }

    if (dev->bus) {
    if (dev->bus->pm) {
    pm_dev_dbg(dev, state, "");
    error = pm_op(dev, dev->bus->pm, state);
    } else if (dev->bus->suspend) {
    pm_dev_dbg(dev, state, "legacy ");
    error = dev->bus->suspend(dev, state);
    suspend_report_result(dev->bus->suspend, error);
    }
    }
    End:
    up(&dev->sem);

    return error;
    }

    这个函数出错,当执行if (dev->bus) {
    if (dev->bus->pm) {
    pm_dev_dbg(dev, state, "");
    error = pm_op(dev, dev->bus->pm, state);
    }这里调用 pm_op(dev, dev->bus->pm, state);

    函数代码如下

    static int pm_op(struct device *dev,
    const struct dev_pm_ops *ops,
    pm_message_t state)
    {
    int error = 0;

    switch (state.event) {
    #ifdef CONFIG_SUSPEND
    case PM_EVENT_SUSPEND:
    if (ops->suspend) {
    error = ops->suspend(dev);
    suspend_report_result(ops->suspend, error);
    }
    break;
    case PM_EVENT_RESUME:
    if (ops->resume) {
    error = ops->resume(dev);
    suspend_report_result(ops->resume, error);
    }
    break;
    #endif /* CONFIG_SUSPEND */
    #ifdef CONFIG_HIBERNATION
    case PM_EVENT_FREEZE:
    case PM_EVENT_QUIESCE:
    if (ops->freeze) {
    error = ops->freeze(dev);
    suspend_report_result(ops->freeze, error);
    }
    break;
    case PM_EVENT_HIBERNATE:
    if (ops->poweroff) {
    error = ops->poweroff(dev);
    suspend_report_result(ops->poweroff, error);
    }
    break;
    case PM_EVENT_THAW:
    case PM_EVENT_RECOVER:
    if (ops->thaw) {
    error = ops->thaw(dev);
    suspend_report_result(ops->thaw, error);
    }
    break;
    case PM_EVENT_RESTORE:
    if (ops->restore) {
    error = ops->restore(dev);
    suspend_report_result(ops->restore, error);
    }
    break;
    #endif /* CONFIG_HIBERNATION */
    default:
    error = -EINVAL;
    }
    return error;
    }

    执行这个函数出错error = ops->suspend(dev);

    请问知道为什么吗

  • 你好,

    抱歉,我没有调试过这部分。

    你已经发现执行这个函数出错error = ops->suspend(dev);,你能否再跟进去看看,看看为什么返回错误?

  • 你好,我调试休眠过程中发现当suspend davinci_v4l2驱动时出错,于是我不编译/driver/media/davinc/vedio/davinci_dispaly.c可以suspend继续执行,这里我怀疑是空指针,继续运行至davinci_mmc suspend失败,不编译可通过,继续suspend时,驱动vpfe_capture suspend 返回错误,我找到/drive/media/video/davinci/目录,打开vpfe_capture.c 发现关于suspend resume 函数体什么都没写返回值为 -1 ,二高版本返回值为0.于是我改为0,suspend都可以筒过,执行我写的enter函数时,我根据手册设置DDR,然后检测状态判断MCLK是否关闭,总是检测未关闭,导致不能向下执行deepsleep使能。我想请问,我已上方法有什么错误,导致DDR自刷新失败。还有vpfe_capture.c 的suspend为何直接返回0 ,为何没有进行suspend相关操作,这样可以吗,还有davinci_v4l2 及 DaVinci_mmc 为何出现错误?

  • Shi Yanlong,

    suspend前,要把所有访问DDR的操作都停止。例如,display如果使能是会自动从你配置的DDR地址拿数据的。capture如果使能写DDR,也是会自动写到DDR相关位置。你能否再检查一下是否还有其他对DDR操作的地方?

  • 你好,对于这里我研究并不深,我在通过mem触发休眠时,包括一些准备工作至挂起,是否就是在这些是能禁掉也就是将所有DDR操作停止。可能理解有误,不是的话,请问如何操作在suspend前,要把所有访问DDR的操作都停止,谢谢。期待您的回复!

                                                                                                                                    

  • 你好,

    我没有尝试过suspend,但就原理上讲,suspend前,要把所有访问DDR的操作都停止。

    我之前的帖子已经提到了,要关闭display,显示等读写ddr的操作,至于你的系统里面是否还有其他ddr的访问,就需要你来判断了。

  • 你好,我理解你的意思,但我不清楚你所说的如display关闭DDR操作如何实现?谢谢!

  • Shi Yanlong,

    关闭所有的显示窗口。硬件上就是所有的osd bitmap window/video window都disable。

  • 你好,我理解这样可以实现。但是有两个问题,首先可能有很多这类外设,不能一一disable,其次我需要唤醒后可以继续执行我的当前程序,我参考平台下DA850代码好像并未如此(内核3.2以上版本),还有我认为这些DDR进程读写的相管操作,应该由Linux内核源码在suspend准备阶段应该已经实现了,只是我未找到。

    还有就是我看dm368官方代码提供了部分平台驱动的suspend resume 相关代码,但是这些代码如果要被调用需要在平台文件调用PM设备操作,但是官方未提供PM 及deepsleep代码,那么那些平台驱动的suspend resume 相关代码,是不是有一些是不可用的,还有一些只提供接口了。如下

    在 /driver/media/vedio/davinci/vpfe_capture.c文件

    2007 static int vpfe_suspend(struct device *dev)
    2008 {
    2009         return -1;
    2010 }
    2011 
    2012 static int vpfe_resume(struct device *dev)
    2013 {
    2014         return -1;
    2015 }
    2016 
    2017 static const struct dev_pm_ops vpfe_dev_pm_ops = {
    2018         .suspend = vpfe_suspend,
    2019         .resume = vpfe_resume,
    2020 };
    2021 
    2022 static struct platform_driver vpfe_driver = {
    2023         .driver = {
    2024                 .name = CAPTURE_DRV_NAME,
    2025                 .pm = &vpfe_dev_pm_ops,
    2026         },
    2027         .probe = vpfe_probe,
    2028         .remove = vpfe_remove,
    2029 };
  • 你好,我理解这样做可以关闭该设备内存操作,但是有两个问题,首先这类内存操作有很多,我如何一一实现,其次我需要实现的是唤醒后恢复之前状态继续执行,如果我把所有都DISABLE,那我唤醒后可能达不到我的要求。

    还有我发现官方代码提供大多数平台设备关于suspend resume 函数的实现,但是官方未提供pm.c sleep.S 等操作deepsleep代码,3而suspend resume这类代码需要注册电源(PM)管理等相关驱动才被触发,如果没有pm.c sleep.S 不会触发,还有我发现一些suspend 实现函数调用会出错,好像是空指针,还有一些函数挂接了但函数为空,如/driver/media/vedio/davinci/vpfe_capture.c以下代码

    2007 static int vpfe_suspend(struct device *dev)
    2008 {
    2009         return -1;
    2010 }
    2011 
    2012 static int vpfe_resume(struct device *dev)
    2013 {
    2014         return -1;
    2015 }
    2016 
    2017 static const struct dev_pm_ops vpfe_dev_pm_ops = {
    2018         .suspend = vpfe_suspend,
    2019         .resume = vpfe_resume,
    2020 };
    2021 
    2022 static struct platform_driver vpfe_driver = {
    2023         .driver = {
    2024                 .name = CAPTURE_DRV_NAME,
    2025                 .pm = &vpfe_dev_pm_ops,
    2026         },
    2027         .probe = vpfe_probe,
    2028         .remove = vpfe_remove,
    2029 };
    2030 
    2031 module_platform_driver(vpfe_driver);
  • 你好,我理解这样做可以关闭该设备内存操作,但是有两个问题,首先这类内存操作有很多,我如何一一实现,其次我需要实现的是唤醒后恢复之前状态继续执行,如果我把所有都DISABLE,那我唤醒后可能达不到我的要求。

    还有我发现官方代码提供大多数平台设备关于suspend resume 函数的实现,但是官方未提供pm.c sleep.S 等操作deepsleep代码,3而suspend resume这类代码需要注册电源(PM)管理等相关驱动才被触发,如果没有pm.c sleep.S 不会触发,还有我发现一些suspend 实现函数调用会出错,好像是空指针,还有一些函数挂接了但函数为空,如/driver/media/vedio/davinci/vpfe_capture.c以下代码

    2007 static int vpfe_suspend(struct device *dev)
    2008 {
    2009 return -1;
    2010 }
    2011
    2012 static int vpfe_resume(struct device *dev)
    2013 {
    2014 return -1;
    2015 }
    2016
    2017 static const struct dev_pm_ops vpfe_dev_pm_ops = {
    2018 .suspend = vpfe_suspend,
    2019 .resume = vpfe_resume,
    2020 };
    2021
    2022 static struct platform_driver vpfe_driver = {
    2023 .driver = {
    2024 .name = CAPTURE_DRV_NAME,
    2025 .pm = &vpfe_dev_pm_ops,
    2026 },
    2027 .probe = vpfe_probe,
    2028 .remove = vpfe_remove,
    2029 };
    2030
    2031 module_platform_driver(vpfe_driver);

  • Shi Yanlong,

    之前讨论里面我已经提到了,TI官方没有在DM365的Linux软件上实现deep sleep。

    你调到这些函数,都需要你来添加。在关闭显示,采集前,请读取当时的寄存器参数,在恢复的时候,再填回去。

  • 嗯,就是说dm368提供deepsleep的硬件接口,并未提供官方代码,内核里面关于deepsleep前的suspend操作,一些未写,一些直接返回零,一些写了但需要自己去验证可用性,也就是所有这些suspend函数接口都需要我们去写一下。

      还有,请问其他用户或ti官方是否实现过deepsleep。我想先验证一下功能实现可行性,模块实现周期预测。谢谢!

  • 你好,请问您知道官方或其他人有人实现过dm368的deepsleep吗,实现周期

    还有请问ccs560仿真器可以实现dm368的SRAM控制吗,可以实现将程序或函数放在sram执行吗,如何实现,谢谢!

  • yanlong shi 说:
    还有请问ccs560仿真器可以实现dm368的SRAM控制吗,可以实现将程序或函数放在sram执行吗

    如果你写一个CCS的工程,指定代码和数据都在SRAM是可以实现的。

  • 你好,我知道类似单片机或keil是可以指定程序或函数在sram执行,但是ccs560仿真器我未这样用过,也没有找到类似指定方法,请问如何将制定代码和数据放在SRAM,谢谢!

  • Shi Yanlong,

    找个ccs工程,例如nand write,ubl,看看里面的cmd文件。