工具/软件:
您好!
MCU 数据表中提到它具有低功耗(睡眠模式)功能、但我找不到相关文档。
是否有任何关于如何实现深度睡眠功能的示例?
谢谢您、
Eduardo。
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.
工具/软件:
您好!
MCU 数据表中提到它具有低功耗(睡眠模式)功能、但我找不到相关文档。
是否有任何关于如何实现深度睡眠功能的示例?
谢谢您、
Eduardo。
尊敬的 Theo:
我希望能够在将数据发送到网络后将芯片置于睡眠或关机状态。 主要思路是等到它连接到网络并发送数据、然后使其处于睡眠状态、直到下一次再次发送数据。
能够配置我希望它睡眠的时间是最好的选择。 我找到了 Power_shutdown (uint_fast16_t shutdownState、uint_fast32_t shutdownTime) 函数、但我尝试配置了 shutdownTime 参数、但在指定的时间后没有唤醒。
您是否有关于如何处理此问题的建议?
此致、
Eduardo。
尊敬的 Eduardo:
在这种情况下、需要停止所有正在运行的任务、关闭所有需要器件像 UART 等保持活动状态的打开驱动程序、然后在信标上将 由计时器解锁(使用慢时钟)进入待机状态。 然后、电源驱动器将处理转换。
由于没有可用的时钟、您无法进入 SHUTDOWN 模式。

此致、
Theo
尊敬的 Theo:
我尝试使用软重置来实现它、但我面临一个问题:我希望消耗尽可能少的能量、因此我不能初始化网状系统。 如果我重置了 CPU、我需要知道何时必须初始化以及何时不必须初始化、因此我需要将时间存储在一个变量中、并将这些值保存在外部 NVS 上
据我所知、要能够使用 TI 驱动程序读取外部 NVS、必须在 RTOS 运行时完成、对吗?
我试图将 mesh_system_init () 函数从 main() 移动到 mainThread、然后我注意到设备没有连接、所以我想我需要在 bios_start () 之前调用这个函数、但我不明白原因...
我有几个问题:
1.是否可以在 BIOS 已在运行时以某种方式初始化网状系统?
2.如果没有,是否有办法阻止它?
3.在初始化 RTOS 系统之前、您是否看到任何其他可能的方法来读取外部 NVS 存储器? 如果我使用内部 NVS、这种情况是否会有所不同?
我感谢你到目前为止提供的支持。
此致、
Eduardo。
尊敬的 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
尊敬的 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。
尊敬的 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:
下面是一个使用 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