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.

[参考译文] CC1352P7:如何启用睡眠模式?

Guru**** 2460850 points


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

https://e2e.ti.com/support/wireless-connectivity/sub-1-ghz-group/sub-1-ghz/f/sub-1-ghz-forum/1500789/cc1352p7-how-to-enable-sleep-mode

器件型号:CC1352P7


工具/软件:

您好!

MCU 数据表中提到它具有低功耗(睡眠模式)功能、但我找不到相关文档。

是否有任何关于如何实现深度睡眠功能的示例?

谢谢您、
Eduardo。

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

    如果您使用电源驱动程序(建议,不要尝试自己做),芯片将进入待机,如果没有计划。   

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

    尊敬的 Eduardo:

    您能给我提供更多详细信息吗?您希望芯片在哪种情况下进入睡眠或关机状态?

    通常、它将通过 RTOS 电源策略使用电源驱动器进入不同的状态。 如果某些电源域通电、则器件无法转换为睡眠或关断模式。

    此致、
    Theo

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

    尊敬的 Theo:

    我希望能够在将数据发送到网络后将芯片置于睡眠或关机状态。 主要思路是等到它连接到网络并发送数据、然后使其处于睡眠状态、直到下一次再次发送数据。

    能够配置我希望它睡眠的时间是最好的选择。 我找到了 Power_shutdown (uint_fast16_t shutdownState、uint_fast32_t shutdownTime) 函数、但我尝试配置了 shutdownTime 参数、但在指定的时间后没有唤醒。

    您是否有关于如何处理此问题的建议?

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    在这种情况下、需要停止所有正在运行的任务、关闭所有需要器件像 UART 等保持活动状态的打开驱动程序、然后在信标上将  由计时器解锁(使用慢时钟)进入待机状态。 然后、电源驱动器将处理转换。

    由于没有可用的时钟、您无法进入 SHUTDOWN 模式。

    https://www.ti.com/lit/ds/symlink/cc1352p7.pdf?ts = 1744722957724&ref_url=https%253A%252F%252Fwww.ti.com%252Fproduct%252Fde-de%252FCC1352P7 

    此致、
    Theo

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

    尊敬的 Theo:

    感谢您的解释。

    是否可以通过某种方法来检查器件是否可以进入待机模式? 我的意思是、是否有任何函数会返回 MCU 的当前状态、以便我知道是否需要禁用我忘记的任何其他运行功能、例如关闭外设或类似功能?

    谢谢您、

    此致、
    Eduardo。

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

    编号 使用完驱动程序后、您必须记住将其关闭。 进行开发时、应使用电流迹线或类似方法来验证电流消耗与时间的关系是否符合预期。  

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

    尊敬的 Eduardo:

    您可以考虑自己检查打开的所有句柄来实现这样一个功能。
    但最简单的过程是如上所述检查能源跟踪器件的行为、这将向您展示器件处于哪种模式。

    此致、
    Theo

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

    尊敬的 Theo:

    谢谢、我会尝试遵循您给我的这些建议。

    更具体的一点是、我尝试将 Wi-SUN CoAP 节点置于睡眠状态。 在 main.c 函数中有以下代码片段:

    似乎使用此代码我无法将节点设置为睡眠功能。 我可以评论这一部分吗?

    对于如何正确地将 Wi-SUN 节点置于睡眠状态、您是否有任何建议?

    谢谢你。

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    您不能将 Wi-SUN 节点置于睡眠状态、因为这样会断开连接。

    您需要做的是:

    -停止 Wi-SUN 堆栈并进入睡眠或关机状态

    -唤醒并重新启动 Wi-SUN 堆栈->如果网络凭据仍然有效、则会导致重新加入

    此致、
    Theo

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

    尊敬的 Theo:

    停止 Wi-SUN 堆栈和禁用天线的正确过程是什么?

    我看到有一些初始化函数、但我不知道如何在不中断任何内容的情况下禁用它们。

    是否有函数可停止堆栈?

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    要停止所有操作并获得干净设置、最简单的方法是软复位。

    此致、
    Theo

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

    尊敬的 Theo:

    我尝试使用软重置来实现它、但我面临一个问题:我希望消耗尽可能少的能量、因此我不能初始化网状系统。 如果我重置了 CPU、我需要知道何时必须初始化以及何时不必须初始化、因此我需要将时间存储在一个变量中、并将这些值保存在外部 NVS 上

    据我所知、要能够使用 TI 驱动程序读取外部 NVS、必须在 RTOS 运行时完成、对吗?

    我试图将 mesh_system_init () 函数从 main() 移动到 mainThread、然后我注意到设备没有连接、所以我想我需要在 bios_start () 之前调用这个函数、但我不明白原因...

    我有几个问题:

    1.是否可以在 BIOS 已在运行时以某种方式初始化网状系统?

    2.如果没有,是否有办法阻止它?

    3.在初始化 RTOS 系统之前、您是否看到任何其他可能的方法来读取外部 NVS 存储器? 如果我使用内部 NVS、这种情况是否会有所不同?

    我感谢你到目前为止提供的支持。

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    这是正确的,你需要 在 bios_start () 之前调用 mesh_system_init (),如 main() 所示。

    您能用一个简短片段来帮助我了解您如何进入待机模式和如何唤醒吗? 我不明白您试图存储和恢复哪些信息。

    此致、
    Theo

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

    尊敬的 Theo:

    此时、我仍没有进入睡眠模式。 我刚刚做了几个测试来查看功耗,为此我刚刚使用了 sleep() 函数。 要执行此测试、我从 main() 函数注释了以下部分:

    #if !defined(WISUN_NCP_ENABLE) || !defined(EXCLUDE_TRACE) || defined(COAP_SERVICE_ENABLE)
        /* Disable power idle mode to prevent known issue with ITM
           output garbage. */
        Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
        Power_setConstraint(PowerCC26XX_SB_DISALLOW);
    #endif

    然后,在 mainThread 上,我使用 sleep () 插入任何延迟,并检查电流消耗是否降低,这确实是。 执行相同的步骤我注意到当 mesh_system_init () 被调用时,电流消耗比在调用 sleep () 之前不调用它时要高得多,这就是为什么我要关闭它。

    从根本上说、该工程是一种每 X 次发送数据的设备、由电池供电、因此我需要它进入睡眠状态。 假设我需要每 30 分钟发送一次、因此我需要休眠、唤醒、发送数据和再次睡眠。 我需要存储和恢复的最重要的信息是 Timestamp Unix 我们用于同步我们的设备,以便能够在正确的时间发送数据。 因此、正如您所说的、最好的方法是重置器件以获得干净的设置、我需要执行以下操作:

    1 — 设备首次连接并从网关获取时间戳,假设它已经发送了一个数据,那么它需要休眠。 所以我需要将当前时间戳保存到 NVS;

    2 — 保存到 NVS 后、我重置器件、想法是我可以读取保存的时间戳以估计我需要休眠多少时间、然后我不会初始化任何内容、只需保持待机模式 X 次、直到下一次发送。

    3 — 在这 X 次过去后、我保存器件的估计时间戳(基于接收到的值+ CPU 时钟)并再次复位 CPU。 复位后、我读取了已保存的时间戳、便知道是时候再连接并发送、它会一直保持在这个循环中。

    因此、如果我需要复位 MCU 以能够进入待机模式、我需要保存当前时间戳、以了解我何时需要初始化网状网络系统和所有其他功能、以及何时只需要睡眠。

    我希望这可以更好地阐明我正在尝试实施的内容、如果您需要更多信息或希望我尝试一些内容、请告诉我。

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    如果我正确理解您、那么您的唯一问题是在第 2 点、您希望在不初始化所有外设的情况下读取 NVS。

    在这种情况下、您可以选择直接使用 driverlib、它是我们驱动程序的底层。 这通常不是建议的过程、因为您需要自己处理所有相关设置、这通常由我们的驾驶员处理。 但在这种情况下、我认为这是获得最直接控制的唯一选项。

    要使用该存储器、您需要为 NVS 电源域上电、然后应该能够访问该存储器: https://dev.ti.com/tirex/explore/content/simplelink_cc13xx_cc26xx_sdk_8_30_01_01/docs/driverlib/cc13x2x7_cc26x2x7/driverlib/group__flash__api.html

    此致、
    Theo

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

    尊敬的 Theo:

    但 driverlib 是否支持外部 NVS?

    如果没有、我需要改用内部 NVS、对吧? CoAP 项目已经在 SYSCFG (CONFIG_NVSINTERNAL) 上初始化了它、它有什么用途? 我应该创建另一个仍未使用的分区?

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    让我再次总结一下选项。

    定义的 NVS 区域用于存储来自 Wi-SUN 栈的网络信息、我建议您在任何情况下定义自定义区域。

    对于访问、您有两个选项:
    1.使用 NVS 驱动程序:为此,您需要在调用驱动程序 init 函数部分的 main 中用 NVS_init () 初始化驱动程序: https://software-dl.ti.com/simplelink/esd/simplelink_cc2640r2_sdk/5.30.00.03/exports/docs/tidrivers/doxygen/html/_n_v_s_8h.html 之后您可以直接使用它来访问您的自定义部分。

    2.如果要直接访问已定义的区域而不使用驱动程序、可以使用 driverlib。 然后您需要包含 flash.h、但我们通常不建议这样做、因为您需要处理驱动程序通常会处理的所有事务。

    您是否已经在仅初始化 NVS 驱动程序并访问自定义的区域时检查了功耗?

    此致、
    Theo

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

    尊敬的 Theo:

    好的、我有这 2 个选项(使用 NVS 驱动程序或 driverlib)。 使用 NVS 驱动程序、我知道可以从内部/外部 NVS 读取/写入。 driverlib 是否也支持这两个选项?

    在功耗方面、我认为初始化 NVS 驱动程序没有太大的区别。 在 main() 函数中、我注释掉了以下代码:

    // #if !defined(WISUN_NCP_ENABLE) || !defined(EXCLUDE_TRACE) || defined(COAP_SERVICE_ENABLE)
    //     /* Disable power idle mode to prevent known issue with ITM
    //        output garbage. */
    //     Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    //     Power_setConstraint(PowerCC26XX_SB_DISALLOW);
    // #endif

    在这种配置下,我能够测量大约 280 uA(因为 mesh_system_init() 是在 main() 调用的)。

    如果我可以在调用 mesh_system_init() 之前读取 NVS、我将能够决定是否需要调用此函数、它将帮助我降低功耗。 但为了实现这一点、我需要能够使用 driverlib 读取外部 NVS、一旦 NVS 驱动程序看起来必须与 RTOS 一起运行。 是这样吗? 我可以使用 driverlib 读取外部 NVS 吗?

    您是否发现任何其他可能的方法? 我不知道是否可以停止网状网络系统、或者如何关闭导致测量电流消耗的外围设备/任务。

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    请在 main 中初始化 NVS 驱动程序、然后在执行任何其他操作之前立即使用它来读取相关的值。

    我认为你不需要调用 mesh_system_init() 或者你需要先启动主线程。  

    如果您在这种方法中遇到错误、请告诉我。

    善良的餐馆
    Theo

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

    尊敬的 Theo:

    我尝试读取 NVS Inside main() 函数、但它不起作用。 我就是这样做的:

    int main(void)
    {
    // #if !defined(WISUN_NCP_ENABLE) || !defined(EXCLUDE_TRACE) || defined(COAP_SERVICE_ENABLE)
    //     /* Disable power idle mode to prevent known issue with ITM
    //        output garbage. */
    //     Power_setConstraint(PowerCC26XX_IDLE_PD_DISALLOW);
    //     Power_setConstraint(PowerCC26XX_SB_DISALLOW);
    // #endif
    
        /* Call driver init functions */
        Board_init();
        GPIO_init();
    
        init_oeeDebug(); // This is some function to initialize UART2 API
        oeeDebug("================================");
        oeeDebug("Device on");
    
    #if defined(MBEDTLS_AES_ALT)
        AESECB_init();
        AESCBC_init();
    #endif
    
    #ifdef FEATURE_TIMAC_SUPPORT
    #ifndef USE_DEFAULT_USER_CFG
        macUser0Cfg[0].pAssertFP = assertHandler;
    #endif //USE_DEFAULT_USER_CFG
        timacTaskId = macTaskInit(macUser0Cfg);
    #endif //FEATURE_TIMAC_SUPPORT
    
    #ifndef WISUN_NCP_ENABLE
        /* Let's first read NVS and see if it has previous configurations */
        minDevice_NVSData_t nvs_data;
        NVS_Handle nvsHandle;
        NVS_Attrs regionAttrs;
        NVS_Params nvsParams;
        NVS_init();
        NVS_Params_init(&nvsParams);
        nvsHandle = NVS_open(CONFIG_NVS_UTILS, &nvsParams);
        if (nvsHandle == NULL) {
            while (1) {}
        }
        NVS_read(nvsHandle, 0, &nvs_data, sizeof(minDevice_NVSData_t));
        
        /* code continues .... */

    我用 CCS 调试该工程、当它到达 NVS_read () 函数时、它会进入 void SysCallback_defaultAbort (const char * str)。 我不知道为什么。

    如果我在线程中使用相同的代码、则可以正常工作。 在 main() 上使用它是否需要执行任何不同的操作?

    此致、
    Eduardo。

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

    尊敬的 Eduardo:

    请为延迟和我的最后一个帖子道歉。

    NVS 驱动程序调用仅适用于主线程、因为它依赖于 RTOS。 这意味着如果要避免启动功耗、您确实需要像在非 RTOS 工程中一样使用 driverlib 直接访问 NVS。

    此致、
    Theo

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

    尊敬的 Theo:

    没问题。

    是否有有关如何使用 driverlib 访问 NVS 的示例? SDK 中的 nvsexternal 示例即使使用 NoRTOS 也会使用 NVS API。

    此致、
    Eduardo。

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

    尊敬的 Theo:

    是否有任何更新?

    此致。

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

    尊敬的 Eduardo:

    下面是一个使用 driverlib 闪存方法的示例:

    #include <flash.h>
    
    #define FLASH_ERASE_PAGE_SIZE   (0x4000)
    #define FLASH_ADDRESS_START     (0x00004000)
    #define FLASH_ADDRESS_END       (0x0004E000)
    
    void TestFunc(void)
    {
        uint8_t numPages = (FLASH_ADDRESS_END - FLASH_ADDRESS_START)/FLASH_ERASE_PAGE_SIZE;
    
        for(uint8_t j=0; j<100; j++)
        {
            for (uint32_t i = FLASH_ADDRESS_START; i < FLASH_ADDRESS_END; i += FLASH_ERASE_PAGE_SIZE) {
                FlashSectorErase(i);
            }
    
            //------------
            uint8_t tmpBuf[FLASH_ERASE_PAGE_SIZE];
            for(uint16_t i=0; i<FLASH_ERASE_PAGE_SIZE; i++) {
                tmpBuf[i] = i % 256;
            }
    
            for (uint32_t i = FLASH_ADDRESS_START; i < FLASH_ADDRESS_END; i += FLASH_ERASE_PAGE_SIZE) {
    
                FlashProgram(tmpBuf, i, FLASH_ERASE_PAGE_SIZE);
                if (memcmp(tmpBuf, (uint32_t*)i, FLASH_ERASE_PAGE_SIZE)) {
                    /* Data is different than what was written */
                }
            }
    
            //------------
    
            for (uint32_t i = FLASH_ADDRESS_START; i < FLASH_ADDRESS_END; i += FLASH_ERASE_PAGE_SIZE) {
                FlashSectorErase(i);
            }
        }
    }

    它将首先擦除一个指定的内存区域、写入它并检查该值是否实际写入、然后再次擦除它。

    此致、

    Arthur

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

    尊敬的 Arthur 和 Theo:

    我认为我已经有足够的信息、我需要遵循我的实施。 如果有任何其他疑问发生,我可以打开一个新的线,如果需要,我认为这已经很长了。

    非常感谢您提供的所有信息和支持。 我在此处的一些答案中标记为“这解决了我的问题“、这些答案提供了我获得的最重要的信息。

    感谢您花时间与我在一起。

    此致、
    Eduardo。