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.

[参考译文] LP-CC2652RB:无法读取然后写入 NVS

Guru**** 2538950 points
Other Parts Discussed in Thread: CC2652RB

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

https://e2e.ti.com/support/wireless-connectivity/bluetooth-group/bluetooth/f/bluetooth-forum/1116204/lp-cc2652rb-unable-to-read-then-write-to-nvs

器件型号:LP-CC2652RB
主题中讨论的其他器件:CC2652RB

处理器:CC2652RB

CCS:v11.2.0.00007

SDK:06.10.00.29

编译器:TI Clang

我正在使用 NVS API 在我的器件上存储一些信息。 我发现、如果我先读取存储器、更改一个或多个值、然后尝试写回该同一位置、我会得到一个 NVS_STATUS_ERROR。 我尝试进行一些调试、但出于任何原因、CCS 无法找到 NVSCC26XX_WRITE 的源。  

我还注意到、如果我先写入该区域、然后尝试读取该区域、则读取的调用会永远挂起。 这`我能够引脚向下到`Sμ s emaphoreP_pend (writeSem、SemaphoreP_WAIT_FOREVE);`μ s in `NVSCC26XX_read ()。 如果发生读取或写入、则信标可能未被正确释放、因此可以执行以下操作。 我可以连续进行两次相同的读取调用、而不会出现任何问题。

我不会擦除写入调用、如果可能、我会希望出现一个空的情况。 无论如何、我认为这不是问题所在。

(对蓝牙论坛表示歉意、但我唯一选择的论坛是无线技术、其中没有一项与我的问题相关。 我真的不明白为什么我无法选择与 SDK 或处理器相关的论坛。)

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

    您好!

    您正处于该问题的正确论坛中!

    基本上、您希望在以下方面实现什么、对吧?

    _ NVS_READ ()
    _修改从闪存中读取的任何值

    _ NVS_write()您修改的值

    您在 NVS_READ 和 WRITE 调用中使用了哪些参数?

    此致、

    Arthur

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

    此外、您尝试读取/写入多少数据?

    我已尝试以下代码、但未能重现问题。

    /*
     * Copyright (c) 2017-2020, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     */
    /*
     *  ======== nvsinternal.c ========
     */
    
    #include <string.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    /* Driver Header files */
    #include <ti/display/Display.h>
    #include <ti/drivers/NVS.h>
    
    /* Driver configuration */
    #include "ti_drivers_config.h"
    
    #define FOOTER "=================================================="
    
    /* Buffer placed in RAM to hold bytes read from non-volatile storage. */
    static char buffer[64];
    
    /*
     * Some devices have a minimum FLASH write size of 4-bytes (1 word). Trying
     * to write a non-multiple of 4 amount of data will fail. This array is
     * rounded up (to next multiple of 4) to meet this requirement. Refer to NVS
     * driver documentation for more details.
     */
    static const char signature[52] =
        {"SimpleLink SDK Non-Volatile Storage (NVS) Example."};
    
    /*
     *  ======== mainThread ========
     */
    void *mainThread(void *arg0)
    {
        NVS_Handle nvsHandle;
        NVS_Attrs regionAttrs;
        NVS_Params nvsParams;
        int_fast16_t nvsStatus;
    
        Display_Handle displayHandle;
    
        Display_init();
        NVS_init();
    
        displayHandle = Display_open(Display_Type_UART, NULL);
        if (displayHandle == NULL) {
            /* Display_open() failed */
            while (1);
        }
    
        NVS_Params_init(&nvsParams);
        nvsHandle = NVS_open(CONFIG_NVSINTERNAL, &nvsParams);
    
        if (nvsHandle == NULL) {
            Display_printf(displayHandle, 0, 0, "NVS_open() failed.");
    
            return (NULL);
        }
    
        Display_printf(displayHandle, 0, 0, "\n");
    
        /*
         * This will populate a NVS_Attrs structure with properties specific
         * to a NVS_Handle such as region base address, region size,
         * and sector size.
         */
        NVS_getAttrs(nvsHandle, &regionAttrs);
    
        /* Display the NVS region attributes */
        Display_printf(displayHandle, 0, 0, "Region Base Address: 0x%x",
                regionAttrs.regionBase);
        Display_printf(displayHandle, 0, 0, "Sector Size: 0x%x",
                regionAttrs.sectorSize);
        Display_printf(displayHandle, 0, 0, "Region Size: 0x%x\n",
                regionAttrs.regionSize);
    
    
        /*
         * Copy "sizeof(signature)" bytes from the NVS region base address into
         * buffer. An offset of 0 specifies the offset from region base address.
         * Therefore, the bytes are copied from regionAttrs.regionBase.
         */
        Display_printf(displayHandle, 0, 0, "Reading buffer");
        nvsStatus = NVS_read(nvsHandle, 0, (void *) buffer, sizeof(buffer));
        Display_printf(displayHandle, 0, 0, "read status: %d", nvsStatus);
    
        /* Modifying the buffer in order to replicate the issue */
        Display_printf(displayHandle, 0, 0, "Modifying buffer");
        buffer[13] = 'Z';
        buffer[0] = 'i';
    
        Display_printf(displayHandle, 0, 0, "Writing buffer");
    
        /* Write back the modified value to the flash */
        nvsStatus = NVS_write(nvsHandle, 0, (void *) signature, sizeof(signature),
                    NVS_WRITE_ERASE | NVS_WRITE_POST_VERIFY);
    
        Display_printf(displayHandle, 0, 0, "write status: %d", nvsStatus);
    
    
        NVS_close(nvsHandle);
    
        Display_printf(displayHandle, 0, 0, "Reset the device.");
        Display_printf(displayHandle, 0, 0, FOOTER);
    
        return (NULL);
    }
    

    您能告诉我我有什么不同的做法、或者以上代码是否对您有效?

    此致、

    Arthur

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

    是的、这就是我要实现的目标。 这是初始化代码。

            NVS_init();
            NVS_Params_init(&nvsParams);
            nvsHandle = NVS_open(CONFIG_NVSINTERNAL, &nvsParams);
            if(!nvsHandle)
            {
                DBG_log(LOG_ERROR, "Failed to initialize device info NVS");
                return false;
            }
    
            NVS_getAttrs(nvsHandle, &regionAttrs);

    读取调用、其中`Current`是 INFO_DeviceInfo:

    int16_t read = NVS_read(nvsHandle, 0, (void*)&current, sizeof(INFO_DeviceInfo));

    以及写入调用、整个函数:

    static bool save(const INFO_DeviceInfo * info)
    {
        NVS_unlock(nvsHandle);
    
        int16_t result = NVS_write(nvsHandle, 0, (void*)info, sizeof(INFO_DeviceInfo), 0);
        if(result != NVS_STATUS_SUCCESS)
        {
            DBG_log(LOG_ERROR, "Failed to save device info: %i", result);
            NVS_lock(nvsHandle, NVS_LOCK_NO_WAIT);
            return false;
        }
    
        NVS_lock(nvsHandle, NVS_LOCK_NO_WAIT);
        return true;
    }

    调试过程中不会出现锁定和解锁调用问题。

    我正在读取和写入的 INFO_DeviceInfo 为91字节。

    除了写入时的擦除和 POST_VERIFY 标志之外、我没有看到任何其他东西。  我在编写代码时遵循了此示例。

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

    将这些标志添加到写入调用可解决此问题。 也许我误解了文档、但我的理解是擦除会擦除闪存中的整个页面。 这不是我想做的事情。 擦除标志是否仅擦除要写入的区域?

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

    您好!

    根据源代码、它会首先擦除闪存扇区。 您可以尝试保持扇区或 RAM 中重要的数据、然后将其写回。

    此致

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

    谢谢 Arthur。 这必须是我的解决方案。

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

    我实际上有一个有关这方面的后续问题。 我的闪存写入失败、如果我不包含擦除标志、则返回-1。 是否需要擦除标志来覆盖闪存中的数据? 我本来希望 NVS_write()能够覆盖闪存中该地址存在的任何数据,而无需首先擦除整个扇区。