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.

[参考译文] CC2340R5-Q1:调整 NVS 导致上电顺序存在差异。

Guru**** 2322270 points
Other Parts Discussed in Thread: CC2340R5, UNIFLASH
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1475173/cc2340r5-q1-adjusting-nvs-has-caused-differences-in-the-power-on-sequence

器件型号:CC2340R5-Q1
主题中讨论的其他器件:CC2340R5UNIFLASH

工具/软件:

您好、

我们的应用使用 mcuboot +双映像和 SimpleLink 低功耗 F3 SDK 8.20.00.119。
在生产测试期间、我们遇到了以下问题:

使用默认的 NVS 设置时、一切正常工作。
在第二次引导时、执行会在大约2秒内到达程序区域。
但是、如果修改了 NVS、则系统需要三次引导才能在2秒内稳定下来。
此问题仅在首次编程全新 CC2340R5时发生。
对 CC2340R5进行编程并至少运行一次后、问题不会再次发生。
问题:
这种行为是否可以避免?
是否有办法在不拆焊芯片的情况下通过软件将 CC2340R5复位为出厂模式?
我在 UniFlash 中尝试了"芯片擦除"、但没有成功。
基于软件的复位将极大地简化未来测试。
以下是我所做的 NVS 修改:

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

    补充第二次上电执行期间的功耗监控。

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

    您好、

    出于好奇心、您是否尝试过升级到最新的 SDK 来看看这是否仍然存在?  

    Unknown 说:
    是否有办法通过软件将 CC2340R5复位为出厂模式而无需拆焊芯片?
    我在 UniFlash 中尝试了芯片擦除、但它不起作用。

    批量擦除操作应擦除器件上的所有内容。 澄清一下、在芯片上完成批量擦除后、数据仍在闪存中?

    Unknown 说:
    基于软件的重置将大大简化将来的测试。

    这确实存在。 请参阅此处: https://dev.ti.com/tirex/content/simplelink_lowpower_f3_sdk_8_40_00_61/docs/drivers/doxygen/html/_power_8h.html#a1db423246eb4407154df05d8fedbf746

    Unknown 说:
    在第二次启动时、执行将在大约2秒内到达程序区域。
    但是、如果修改了 NVS、则系统需要三次引导才能在2秒内稳定。

    我有点困惑、您是否想详细说明 系统需要三个靴子才能在2秒内稳定下来

    此致、

    Nima Behmanesh

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

    您好、

    由于我们已经进入产品验证阶段、因此目前不适合切换到不同的 SDK。

    对我之前的简短描述表示歉意。 最近、我进行了进一步测试、发现当使用修改后的 NVS 设置将固件刷写到空白 IC 时、首次上电始终会受到影响。 但是、如果重新刷新了固件、则不会再次出现此问题。

    器件引导过程:

    观察到的行为:
    我使用电流表捕获了功耗数据、在第一次引导时 NVS 写入和 SPI 传输似乎都受到影响。 这会使正确的 NVS 读取/写入操作和 SPI 控制仅在第二次引导时运行。

    问题:
    修改 NVS 地址区域是否要求系统重写相应的信息?
    我们如何防止此重叠导致首次引导期间的控制失败?

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

    您好、

    是的、NVS 写入之前通常会出现失效、然后写入下一个可用的 NVS 存储器部分:

    https://dev.ti.com/tirex/content/simplelink_lowpower_f3_sdk_8_40_00_61/docs/ble5stack/ble_user_guide/html/ble-stack-common/flash_memory-cc23xx.html?highlight=non%20volatile#non-volatile-storage-architecture

    此外、NVS 将禁用中断并在闪存中执行代码: NVSLPF3.h 文件参考

    因此、如果 NVS 向器件写入信息、为什么 SPI 可能无法工作、这是合理的。  

    对我之前的简短描述表示歉意。 最近、我进行了进一步测试、发现当使用修改后的 NVS 设置将固件刷写到空白 IC 时、首次上电始终会受到影响。 但是、如果重新刷新了固件、则不会再次出现此问题。

    由于 首次上电始终受到影响、 您意味着需要更长的时间才能执行?  

    此致、

    Nima Behmanesh

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

    您好、

    首次上电时始终会受到影响、这不仅是因为执行时间较长、而且还因为未能将默认值写入 NVS。
    仅当使用修改后的 NVS 地址区域刷写固件时、才会出现此问题。 (我们测试了相同的项目代码、只更改了 NVS 配置。)
    我们不确定在首次引导过程中、使用修改后的 NVS 地址将固件刷写到空白 IC 后会发生哪些特定过程、从而导致 NVS 写入失败。
    此外、我们还需要有关如何防止该问题发生的指导。
    此问题已在我们的 ATE 程序中造成错误检测、因此、我们非常感谢您对解决此问题的支持。

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

    您好:

    我很抱歉耽误时间,我上周生病了。

    我想我现在更好地理解了问题。 如果它是空白芯片并且未使用我们项目中包含的默认 NVS 设置、则在首次启动时写入该设置时会出现问题。 在第二次引导之后、除写入之外、第三次引导通常会发生。

    如果我的理解不正确、请告诉我。 我需要联系驾驶员团队、了解流程。 同时、我自己试一下。  

    下面是我要尝试重现的步骤:

    获取空白 CC2340R5并使用修改后的 NVS 设置对其进行刷写

    2.阅读 NVS,

    3.如果它是空的,写一些东西

    如果问题再次出现、则在首次引导时写入应失败。

    是这样吗?

    此致、

    Nima Behmanesh

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

    您好、

    没问题、请注意。
    是的、您的理解是正确的、您计划进行的测试与我当前的流程保持一致。
    期待您的更新。 谢谢!

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

    尊敬的 Ian:

    在我开始之前的几个问题、今天尝试重现该问题:

    1.您使用的是 NVS 和外部闪存吗?

    2.您使用的编译器是什么?

    这些将帮助我排除可能导致此问题的一些变量。

    此致、

    Nima Behmanesh

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

    您好、

    1.我们使用 basic_ble_oad_dual_image 示例并将默认的16KB 内部 NVS 修改为两个单独的8KB 块、地址配置如上一个比较图像所示。
    编译器版本:TI Clang v3.2.1.LTS。

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

    您好:

    感谢您提供的信息、我将在今天或明天回复我的结果。

    感谢您的耐心。

    此致、

    Nima Behmanesh

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

    您好、

    是否有任何更新? 您是否需要我们的进一步支持?

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

    您好:

    很抱歉耽误时间、我们仍在处理这个问题。 我会尽快回复您。

    此致、

    Nima Behmanesh

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

    您好:

    我已经在一个空项目上测试了 NVS、但我没有看到任何问题。 这让我想到的可能是涉及 BLE 栈的问题。 您是在堆栈初始化之前还是之后调用 NVS API? 您在应用程序中的哪个函数中调用 NVS API?

    我将自行尝试、但知道您在哪里调用这些 API (根据您之前提供的图表)、我将能够更快地重现此问题。

    此致、

    Nima Behmanesh

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

    您好、

    我认为你的推理是正确的。 在我的程序流中、广播和其他运行参数存储在 NVS 中、因此我需要在初始化 BLE 栈之前检索这些参数。 因此、NVS API 调用发生在 BLE 栈初始化之前。
    但是、我注意到 osal_SNV_init 仅在 iCall 初始化后执行。 即使我提前手动调用它、它也不会生效。
    是否有办法在 BLE 栈初始化之前初始化 NVS、从而确保我可以访问存储的参数?

    这是我的代码片段。

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

    您好、

    抱歉、我似乎误解了该代码。 App_StackInitDoneHandler照射行程 之后 BLE 栈初始化、因此我的 NVS API 调用确实已被执行 之后 BLE 栈已初始化。

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

    您好:

    我在 basic_ble 上尝试了相同的测试、但在初始化堆栈之前读取/写入 NVS、并且没有看到任何问题。 我通过修改    app_main.c 中的 appMain 函数来实现此目的

    NVS_Handle region1;
    NVS_Params nvsParams;
    uint8_t buf[32] = {0};
    
    void appMain(void)
    {
        NVS_init();
        GPIO_init();
    
        NVS_Params_init(&nvsParams);
        region1 = NVS_open(CONFIG_NVS_0, &nvsParams);
    
        int_fast16_t status = 0;
        status = NVS_read(region1, 0, buf, 1);
        if (status != NVS_STATUS_SUCCESS)
        {
            GPIO_write(CONFIG_GPIO_LED_RED, 1);
            while(1);
        }
    
        if (buf[0] == 0xFF)
        {
            status = NVS_write(region1, 0, 0, 1, NVS_WRITE_POST_VERIFY);
            if (status != NVS_STATUS_SUCCESS)
            {
                GPIO_write(CONFIG_GPIO_LED_GREEN, 1);
                while(1);
            }
        }
    
        // Call the BLEAppUtil module init function
        BLEAppUtil_init(&criticalErrorHandler, &App_StackInitDoneHandler,
                        &appMainParams, &appMainPeriCentParams);
    }

    请注意、我正在初始化堆栈之前进行读取和写入。

    此致、

    Nima Behmanesh

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

    您好、

    由于文档中建议使用 OSAL 来访问 NV、因此我们使用 osal_SNV_READ ()和 osal_SNV_WRITE ()来直接访问 BLE_NVID_CUST_START 位置。
    您是否介意根据该方法再次使用 OSAL 进行测试?

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

    您好:

    是的、我明天会尝试此操作、然后再联系您。

    此致、

    Nima Behmanesh

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

    您好:

    我在尝试重现此问题时注意到了一些问题:

    最初、我运行以下代码:

    uint8_t buf[32] = {0};
    void App_StackInitDoneHandler(gapDeviceInitDoneEvent_t *deviceInitDoneData)
    {
        bStatus_t status = SUCCESS;
    
        status = osal_snv_read(BLE_NVID_CUST_START, 4, buf);
    
        if (status != SUCCESS)
        {
            MenuModule_printf(10, 0, "FAILED READING!");
        }
    
        status = osal_snv_write(BLE_NVID_CUST_START, 4, buf);
    
        if (status != SUCCESS)
        {
            MenuModule_printf(10, 0, "FAILED WRITING!");
        }

    我相信此代码重现了您所看到的内容、即在空白器件上、第一次读取失败、然后在第二次复位时成功读取。

    但是,如果我们添加一个  while (1); 在   osal_SNV_read ()调用的错误处理中, 当芯片最初为空时,它将始终失败。

    如果我们切换调用,  在 osal_SNV_read  ()之前调用 osal_SNV_write :

    uint8_t buf[32] = {0};
    void App_StackInitDoneHandler(gapDeviceInitDoneEvent_t *deviceInitDoneData)
    {
        bStatus_t status = SUCCESS;
    
        status = osal_snv_write(BLE_NVID_CUST_START, 4, buf);
    
        if (status != SUCCESS)
        {
            MenuModule_printf(10, 0, "FAILED WRITING!");
        }
    
        status = osal_snv_read(BLE_NVID_CUST_START, 4, buf);
    
        if (status != SUCCESS)
        {
            MenuModule_printf(10, 0, "FAILED READING!");
            while(1);
        }
    

    它将取得成功而不会有任何问题。

    这使我得出以下结论:
    如果 BLE_NVID_CUST_START 处的存储器为空(或这种情况下的任何 ID)、则  osal_SNV_READ () 将返回失败。 但是,如果有东西被写入 BLE_NVID_CUST_START  (或任何其他 ID ),那么 osal_SNV_READ () 将会成功。  

    在您的程序中,您首先阅读,如果它是空的,您写。 问题在于、 如果 osal_SNV_read 的读数为空、则它将返回失败结果。 批量擦除后、所有内容都是空白的、因此读取任何内容都将始终失败。 我还在做假设,在读取失败,你不阻止程序执行并继续写入(请告诉我,如果我的理解是不正确的,如果是,那么我们需要某种示例项目来重现它)。 这意味着在第二次引导时、该 ID 有写入的内容。 在 文档中 有以下引言:

    无需事先初始化 NV 商品 ID; OSAL SNV 管理器在首次被成功的 osal_SNV_write ()调用访问时初始化 NV ID

    此外、如果我们查看文档中给出的示例代码:

        status = osal_snv_read(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
        if(status != SUCCESS)
        {
            Display_printf(dispHandle, dispIndex, 0, "#%5d    SNV READ FAIL: %d", dispIndex, status); dispIndex++;
          //Write first time to initialize SNV ID
          
          // Because the osal_snv_read failed, we assume it's empty so we write something
          // to it, to initialize the ID.
          osal_snv_write(SNV_ID_APP, BUF_LEN, (uint8 *)buf);
        }

    我们可以看到、如果  osal_SNV_read  失败、则假设 ID 没有写入任何内容。 这是合理的、因为一旦成功  调用 osal_SNV_write、就会初始化 ID。

    以下 是几个解决方案:

    1.如果  osal_SNV_read  失败,则可以假定它为空。

    2.您可以定义自己的 NVS 区域并使用 NVS 驱动程序。 在 NVS 中存储任何所需内容后、可以使用 osal_SNV_write/Read  将该信息加载到 BLE NVS 区域中。 如果是绑定信息、则可以使用 gapbondmgr API 导入该绑定。

    我希望这对您有所帮助!

    此致、

    Nima Behmanesh

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

    您好、

    对延迟的更新深表歉意、我们最近正忙于执行量产工作。
    我已经遵循了您的第一条建议、计划于下周进行验证。
    我会随时向您发布任何新进展。

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

    您好:

    不用担心、请让我知道它是如何实现的!

    此致、

    Nima Behmanesh

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

    您好、

    该问题在上周的验证过程中未再次出现。 非常感谢您的技术支持。