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.

LAUNCHXL-CC26X2R1: NVS_erase() erases all regions on external flash

Part Number: LAUNCHXL-CC26X2R1
Other Parts Discussed in Thread: SYSCONFIG, SIMPLELINK-CC13X2-26X2-SDK

Hi everybody,

After spending hours finding out why my OAD external images are being deleted, I have noticed that the function:

NVS_erase(nvsHandle, 0, 0x100000) 

erases beyond the selected Region in the handle (nvsHandle). It deletes all regions on the external flash.

Here some information about the regions I created in sysconfig:

1. Region CONFIG_NVS_OAD:

Region Base: 0x0

Region Size: 0x100000

Sector Size: 0x1000

Verify Buffer Size: 64

 

2. Region CONFIG_NVS_EXTERNAL_CUSTOM:

Region Base: 0x200000

Region Size: 0x100000

Sector Size: 0x1000

Verify Buffer Size: 64

 

This is how I create the handle:

nvsHandle= NVS_open(CONFIG_NVS_EXTERNAL_CUSTOM, &nvsParams);

For some reason the nvsHandle deletes data in the CONFIG_NVS_OAD region too.

I'm currently using the standard CC26X2 Launchpad with the SIMPLELINK-CC13X2-26X2-SDK_5.20.00.52 SDK. Do you guys have any idea how I can prevent this

Any help is appreciated.

Thanks in advance and happy Turkey Day!

SPEEDBIRD

  • Hi SPEEDBIRD,

    May i ask to provide the following details?

    • Could you please specify how you create the NVS handle for the region CONFIG_NVS_OAD?
    • Could you also specify how you verify if a specific piece of the memory has been erased?
    • What is the status returned by the function NVS_erase()?

    Best regards,

  • Hey Clement,

    Here are the screenshots from Sysconfig:

    The Region I mentioned above "CONFIG_NVS_EXTERNAL_CUSTOM" I named CONFIG_NVS_EXTERNAL_IMAGES:


    Screen1

    This is the Region OAD uses:

    And here is the code generated by Sysconfig:

    NVSSPI25X_Object nvsSPI25XObjects[2];
    
    static const NVSSPI25X_HWAttrs nvsSPI25XHWAttrs[2] = {
        /* CONFIG_NVS_OAD */
        /* MX25R8035F SPI Flash */
        {
            .regionBaseOffset = 0x0,
            .regionSize = 0x100000,
            .sectorSize = 0x1000,
            .verifyBuf = verifyBuf,
            .verifyBufSize = 64,
            /* NVS opens SPI */
            .spiHandle = NULL,
            /* SPI driver index */
            .spiIndex = CONFIG_SPI_0,
            .spiBitRate = 4000000,
            /* GPIO driver pin index */
            .spiCsnGpioIndex = CONFIG_GPIO_0,
            .statusPollDelayUs = 100
        },
        /* CONFIG_NVS_EXTERNAL_IMAGES */
        /* MX25R8035F SPI Flash */
        {
            .regionBaseOffset = 0x200000,
            .regionSize = 0x100000,
            .sectorSize = 0x1000,
            .verifyBuf = verifyBuf,
            .verifyBufSize = 64,
            /* NVS opens SPI */
            .spiHandle = NULL,
            /* SPI driver index */
            .spiIndex = CONFIG_SPI_0,
            .spiBitRate = 4000000,
            /* GPIO driver pin index */
            .spiCsnGpioIndex = CONFIG_GPIO_0,
            .statusPollDelayUs = 100
        },
    };
    
    #define CONFIG_NVS_COUNT 3
    
    const NVS_Config NVS_config[CONFIG_NVS_COUNT] = {
        /* CONFIG_NVSINTERNAL */
        {
            .fxnTablePtr = &NVSCC26XX_fxnTable,
            .object = &nvsCC26XXObjects[0],
            .hwAttrs = &nvsCC26XXHWAttrs[0],
        },
        /* CONFIG_NVS_OAD */
        /* MX25R8035F SPI Flash */
        {
            .fxnTablePtr = &NVSSPI25X_fxnTable,
            .object = &nvsSPI25XObjects[0],
            .hwAttrs = &nvsSPI25XHWAttrs[0],
        },
        /* CONFIG_NVS_EXTERNAL_IMAGES */
        /* MX25R8035F SPI Flash */
        {
            .fxnTablePtr = &NVSSPI25X_fxnTable,
            .object = &nvsSPI25XObjects[1],
            .hwAttrs = &nvsSPI25XHWAttrs[1],
        },
    };

    This is how I specify that an other region was deleted / corrupted:

    It mainly has to do with the Factory Firmware that is located inside the CONFIG_NVS_OAD region.


    I can always revert to the factory image without any issues, but once I call NVS_erase(nvsHandle, 0, 0x100000) with the nvsHandle based on the other Region named CONFIG_NVS_EXTERNAL_IMAGES, it corrupts my Factory Firmware and I can't revert to it in the future again. If I don't call NVS_erase() of the other region during my application runtime, the factory firmware never gets corrupted.

    This is how I create the handle nvsHandle= NVS_open(CONFIG_NVS_EXTERNAL_CUSTOM, &nvsParams);

    Concerning your last question: NVS_erase() returns 0x00.

    Thanks in advance!

    SPEEDBIRD

  • Hi,

    Thank you for all the details provided. I have managed to reproduce your issue and I have asked the R&D team to look into this.

    I'll come back to you as soon as I have more information or a workaround.

    Appreciate your help and your patience.

    Best regards,

  • Thank you Clément for checking in on this issue. I would be very happy if you could find a workaround.

    Do you know if there are any alternative ways to clear / delete regions on the external flash?

    Best Regards,

  • Hi,

    Of course!

    I am not sure how valuable it is for you, but by reducing the sizes of the flash regions from 0x100000 to 0x10000, the issue disappears. I haven't found the maximum/minimum sizes yet.

    Best regards,

  • Hi,

    I have consulted with the R&D team and they do not support having several NVS regions in the external flash. More specifically, this type of use case is not properly tested.

    I would recommend to rather use a single region.

    Thanks again for taking the time to report this.

    Best regards,

  • Thank you for reaching out to the R&D Team,

    I personally don't have any issues combining both regions. After doings so, I'm actually still facing the same behavior & issues. 

    So first I increased the size of the region from 0x100000 to 0x300000 (just to be safe I'm using a gap of 0x100000).

    The first part from 0x0 to 0x100000 is reserved for OAD. The whole OAD process is limited by EFL_FLASH_SIZE that is 0x100000.

    The second part from 0x100000 to 0x200000 I don't touch at all and use it as a safety gap ;-)

    The third part from 0x200000 to 0x300000 I use as storage for my custom application.

    Here is a screenshot from Sysconfig:

     

    Every time I call

    NVS_erase(nvsRegion, 0x200000, 0x100000);

    it again is corrupting / deleting the area from 0x0 to 0x100000 where my OAD factory image is located.

    I even tried to use NVS_erase in smaller bits:

    int i = 0;
    int rounds = 10;
    
    while(i < rounds) {
        NVS_erase(nvsRegion, 0x200000 + (i*0x10000), 0x10000);
        i++;
    }

    Same result: it deletes the area from 0x0 to 0x100000 where my OAD factory image is located.

    Do you have any Idea how I can solve this issue? I must store about 0x100000 of data (additional to the OAD) on the external flash.

     

    Thanks in advance!

    Regards,

  • Hi,

    Thank you for telling me.

    The current version of the NVS driver has a limit on the offset that can be used. The maximum offset is 0x100000. 

    In addition, we recommend to use the internal flash to store application data (i.e. all except the OAD images). If needed you can review the nvsinternal example provided within the SDK.

    We are working to increase the offset limit usable in a future release.

    Best regards,

  • Hi Clément,

    This is a shock we first must digest.

    But first thank you for helping us solve this issue :-)

    The main issue is, that our application needs to store 1 MB of data - the internal NVS is therefor too small.

    In this case, that NVS can only access 1 MB of 8 MB we are not using our real estate on our external Flash in a useful matter. Is there anyway we can modify the NVS driver to use 2 MB on the external flash?

    TI should add this as a note to their NVS and OAD documentation. On top NVS functions should return some kind of failure if the offset is too large or invalid. We checked through the NVS driver code and saw that checkEraseRange() returns SUCCESS, because it "correctly" checks if the offset etc. is smaller than the available Region Size etc.

        if (offset >= hwAttrs->regionSize) {
            return (NVS_STATUS_INV_OFFSET);   /* offset is past end of region */
        }
    
        if (offset + size > hwAttrs->regionSize) {
            return (NVS_STATUS_INV_SIZE);     /* size is too big */
        }
    
        if (size != (size & sectorBaseMask)) {
            return (NVS_STATUS_INV_SIZE);     /* size is not a multiple of */
                                              /* sector size */
        }

    When would the fix be available? I think all Engineers would be happy if the offset size itself would be increased - We can all work with one region.

    Is it only the offset that is limited to 1 MB or do any other factors play a roll?

    Thanks in advance!

    Best Regards,

  • Hi,

    I am afraid I cannot commit to a resolution date on a public forum.

    I have taken a moment to look into the driver for you. I have not found the solution but you may want to take a look too.

    • the driver itself does not seem to limit the offset
    • using a logic analyzer, and looking at the SPI signals interfacing the external flash, I do not see the issue. I mean, the proper address is sent out.
      You may want to reproduce these observations. By default, on the launchpad the signals are on DIO20 (SPI-Enable), DIO10 (SPI-CLOCK), DIO8 (SPI-MISO), DIO9 (SPI-MOSI).
    • This made me wonder if the expected flash is soldered on the board. The answer seems to be yes (MX25R8035FZUIL0). If you are interested, I have written a small snippet to read the flash identification. This get inspired by §10.3 of this document.
      int_fast16_t doReadIdentification(NVS_Handle handle, void *buffer,
              size_t bufferSize)
      {
          NVSSPI25X_Object *object;
          NVSSPI25X_HWAttrs const *hwAttrs;
          uint8_t wbuf[1];
          int retval = NVS_STATUS_SUCCESS;
      
          hwAttrs = handle->hwAttrs;
          object = handle->object;
      
          /* Set protected global variables */
          spiHandle = object->spiHandle;
          spiCsnGpioIndex = hwAttrs->spiCsnGpioIndex;
      
          /* Wait till previous erase/program operation completes */
          retval = extFlashWaitReady(handle);
          if (retval) {
              return (retval);
          }
      
          /*
           * SPI is driven with very low frequency (1MHz < 33MHz fR spec)
           * in this temporary implementation.
           * and hence it is not necessary to use fast read.
           */
          wbuf[0] = 0x9F; //Read Identification (RDID)
      
          NVSSPI25X_assertSpiCs(handle, spiCsnGpioIndex);
      
          if (extFlashSpiWrite(wbuf, sizeof(wbuf))) {
              NVSSPI25X_deassertSpiCs(handle, spiCsnGpioIndex);
              return (NVS_STATUS_ERROR);
          }
      
          retval = extFlashSpiRead(buffer, bufferSize);
      
          NVSSPI25X_deassertSpiCs(handle, spiCsnGpioIndex);
      
          return (retval);
      }

      The function can be called as following in the nvexternal.c file (example nvsexternal)
          uint8_t nvsIdBuffer[3];
          doReadIdentification(nvsHandle, nvsIdBuffer, sizeof(nvsIdBuffer));

      Both using the content of nvsIdBuffer and the logic traces (see before), I get the value expected (C2:28:14) (see §10.7 of this document.)

    I hope this will help,

    Best regards,

  • Hi, 

    Thank you for the quick reply. I can reproduce the same issue on our custom PCB and there for a fact I know the correct flash is mounted. I will check later today if the Launchpad results with the expected value.

    I did go through the datasheet and found the following point:

    "MX25R8035F is 8Mb bits Serial NOR Flash memory, which is configured as 1,048,576 x 8 internally. When it is in four I/O mode, the structure becomes 2,097,152 bits x 4 or 4,194,304 bits x 2."

    There seem to be the following different I/O modes it can be set to:

    - READ

    -2READ

    -4READ

    But this should not be an issue either. Anyhow, why would the NVS driver have a limit to 0x100000? - Something does not fit at all. 

    Thanks in advance!

    Best Regards,

  • Hi,

    This limitation has been reported and will be addressed in a future release. In the meantime, you'll have to modify the driver on your own if you wish to support a larger memory size.

    We'll be happy to help to tune the driver to your use-case in the limits of the support level we can commit.

    For now, I am closing this thread as the initial question is answered - i.e. "the driver provided is limited on the usable flash size". For additional support, please open a new thread.

    Thank you for your comprehension.

    Best regards,

  • Hey Clement,

    I'll modify the driver and will keep you posted with my results (and code) to enable the usage of the full external flash.

    Best Regards,

  • Hi,

    Actually the behavior observed here is due to the external Flash size. The Flash mounted on the launchpad is 8Mbit (i.e. 1MB).

    I am not sure how I got confused, but the issue does not come from the driver. The limitation comes from the flash itself.

    Hoping this will clear the doubts.

    Best regards,

  • Hi Clement,

    I just saw your answer. We also noticed this two weeks ago. Thankfully we did not get started trying to solve the "issue" in the NVSdriver.

    I had this thought before and checked the Datasheet and was sure that I read 8 MB (8 MByte). I have no clue how we over looked this all. 

    Best Regards,