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.

CC2538 Cannot write Multiple Words in Flash using ROM function

Other Parts Discussed in Thread: CC2538, CC2538-SW

Hi TI,


We are currently developing a small filesystem using the available flash in the CC2538, but there seems to be an issue with the ROM function used by the DriverLib to write multiple 32-bit words in flash.

When using the provided API interface:

int32_t FlashMainPageProgram(uint32_t *pui32Data, uint32_t ui32Address, uint32_t ui32Count)

With a ui32Count > 4 (more than 1 word), the data fails to be written in its entirety. (Address and Count are both multiples of four).


I've tried to write 32 bytes (8 words) of data sequentially, but when debugging, it shown that sometimes one word get properly written, sometimes it's two... But it never get to more than that. It was not possible to write the whole 8 words. However, the function did return a Success value.

As a workaround, I wrapped the call into a function that feed the data one word at a time. This worked without any issues. But, performance is most likely to take a hit using this method.

I've tried using different cache mode, but this doesn't change anything. (On that note, is there other information available about the flash cache modes other than what's written in the User Guide?)

So, is there any special considerations regarding the ROM functions (that are called by the flash utility in the driverlib) that could cause this issue?
 Is there another requirements to be able to write an array of word in flash? (data was in SRAM)

Actions are performed using the CPU. Would the same issue arise using the uDMA?

Thanks!

Simon

  • Hi Simon, 

    You can download the driverLib Source code from http://www.ti.com/tool/cc2538-sw

    The function FlashMainPageProgram() you are using has following description. Similarly you can look at the entire implementation and also use the examples to with the source code to test/verify your implementation.Please let me know if the conditions below, or descriptions from the driverlib helped to resolve the issue.  

    //! Programs the flash main pages by use of ROM function
    //!
    //! \param pui32Data is a pointer to the data to be programmed.
    //! \param ui32Address is the starting address in flash to be programmed. Must
    //! be a multiple of four and within the flash main pages.
    //! \param ui32Count is the number of bytes to be programmed. Must be a multiple
    //! of four.
    //!
    //! This function programs a sequence of words into the on-chip flash.
    //! Programming each location consists of the result of an AND operation
    //! of the new data and the existing data; in other words, bits that contain
    //! 1 can remain 1 or be changed to 0, but bits that are 0 cannot be changed
    //! to 1. Therefore, a word can be programmed multiple times as long as these
    //! rules are followed; if a program operation attempts to change a 0 bit to
    //! a 1 bit, that bit will not have its value changed.
    //!
    //! Because the flash is programmed one word at a time, the starting address and
    //! byte count must both be multiples of four. The caller must
    //! verify the programmed contents, if verification is required.
    //!
    //! This function does not return until the data is programmed or an
    //! error encountered. Locked flash pages cannot be programmed.
    //!
    //! \return Returns 0 on success, -1 if a programming error is encountered
    //! or, -2 in case of illegal parameter use.
    //
    //*****************************************************************************
    int32_t
    FlashMainPageProgram(uint32_t *pui32Data, uint32_t ui32Address,
    uint32_t ui32Count) ..

    ..

    ..

    Regards

  • Hi Suyash,


    Yes this is exactly what we are already using.


    In the description, it says " //! This function programs a sequence of words into the on-chip flash."

    This is the part that does not seems to work. When a sequence of words is provided to this utility function, only a portion of the sequence is written to flash.


    Example:

    uint8 something[16];

    CopyString(something, "YayGoingInFlash\0"); // something is now the string

    FlashMainPageProgram((uint32_t*)something, 0x023F000, 32); // Pushing 16 bytes (4 words) somewhere in flash

    The expected output would be:

    @0x0023F000 59 61 79 47 6F 69 6E 67 49 6E 46 6C 61 73 68 00    YayGoingInFlash.

    But instead, only got:

    @0x0023F000 59 61 79 47 6F 69 6e 67 FF FF FF FF FF FF FF FF   YayGoing........

    The function does return a success ("0"), but only 2 words have been written instead of four!

    *Flash was erased prior to write in all cases

    Is there something else required to write a sequence of words in flash?


    Thanks,

    Sim

  • UPDATE:

    It seems that the issue can occur also using a single-word write!

    We have made some unit tests that we run to test the flash filesystem we developed, and it detects a systematic fail when trying to write a "big" file (100kB).

    Indeed, when inspecting the memory, we found that some words are not written. This occur in a random pattern. Very roughly, 1 in 500 word is not written and kept to "0xFF FF FF FF".

    Hence, it is the same behavior as when the write was performed using the ROM function with more than a word, except that it occurs less frequently.

    Also, I've tried adding a small delay between each word write to see if that could help a little, but it does not seem to make a difference.

    Could there be something in the flash configuration that can cause that? Or a bug in the ROM function?

    Anyhow, for the moment, we have a workaround where if the CRC of the data written in flash is not the same as the one used in input, then a retry is performed to make sure to catch the unwritten word and write it back to the proper value.

    But from a performance point of view, given that the sequential write is also worked around, it is not very optimal.

    Thank you very much,
    Sim
  • Hi Sim,

    To understand the issue better I want to ask you some may be basic questions -
    1. Have you ensured that the writes to memory are always at 4 byte aligned addresses. 2. Have you ensured that the data passed to the API is always a multiple of 4.
    Also, please refer to the section 8.3.2 of the CC2538 User Guide, please see the excerpt below. Can you also check if you are not violating any of the limitations.

    "8.3.2 Writing Multiple Times to a Word
    The following rules apply when writing multiple times to a 32-bit word between erase:
    • The same address cannot be programmed (either '0' or '1') more than eight times before the next
    erase.
    • The same bit-cell can be programmed '0' more than two times before the next erase.
    • Writing a '1' to a bit does not change the state of the bit
    The state of any bit of a 32-bit flash word is nondeterministic if these limitations are violated."

    In addition, is it possible for you to share the code you are using to implement this functionality ?

    Regards
  • Hello Suyash,

    For your first two questions, these considerations are already taken care of by you (TI) when using the function FlashMainPageProgram()  (CC2538 driverlib 1.0.1.0). Namely, the following statements are performed to ensure the respect of those conditions:

    ASSERT(!(ui32Address & 3));
    ASSERT(!(ui32Count   & 3));

    As for the limitations, all writes are performed on previously-erased pages. So all bits are set to "1", and once they are written, nothing is ever re-written without performing a full page erasure.

    Here's the code of the wrapper written to circumvent the issue raised in this post.

    /*!********************************************************************
     * @fn        SequentiallyWrite
     *
     * @brief   Write words in flash word by word
     *             This function is used to wrap around the driverlib
     *             flash utility has it seems that writting a sequence
     *             of words is not working properly.
     *             TODO Allow for sequential write
     *               in ROM function if source of problem is found.
     *
     * @param   uint32* - ptr to data
     *          uint32  - address where to put data in flash
     *          uint16  - length of data to write in bytes
     *                      (Must be a multiple of four)
     *
     * @return  bool - FALSE on error
     *
     *********************************************************************/
    bool SequentiallyWrite(const uint32* data, uint32 address, uint16 length)
    {
       
       uint16 crc16;
       
       // Verify input
       if (length & 3)
       {
          REPORT_ERROR(ERROR_CODE_CATEGORY_ARRAY_SIZE,
                       ERROR_CODE_FLASH_FILE_SYSTEM);
          return FALSE;
       }
       
       // Transfer word by word
       for (uint16 itr = 0; itr < length; itr += 4u)
       {
          
          // Write source to destination
          if(FlashMainPageProgram((uint32_t*)&data[itr >> 2u], address + itr, 4) != 0)
          {
             // Unable to restore, system failure
             REPORT_ERROR(ERROR_CODE_CATEGORY_MEMORY,
                          ERROR_CODE_FLASH_FILE_SYSTEM);
             return FALSE;
          }
          
       }
       
       // Verify data integrity
       crc16 = Crc16(0, (uint8*)data, length);
       if (crc16 != Crc16(0, (uint8*)address, length))
       {
          
          // If could not recover, report error
          if (mRetryWrite > MAXIMUM_WRITE_RETRY)
          {
             REPORT_ERROR(ERROR_CODE_CATEGORY_MEMORY_BAD_CRC,
                       ERROR_CODE_FLASH_FILE_SYSTEM);
             return FALSE;
          }
          
          // Attempt to recover by re-writing the data
          mRetryWrite++;
          SequentiallyWrite(data, address, length);
       }
       else
       {
          // Clear retry count on write success
          mRetryWrite = 0;
       }
        
       return TRUE;
    }
    

    Using that wrapper, we actually never experienced any other errors (which also validate that we are not writing over already written data, as this function would never be able to recover from this).

    But, that is a serious hit to performance! 1. We need to write word by word through a loop 2. The CRC check takes  a lot of overhead computation to be performed.

    I would be interested in seeing the code used in the underlying ROM function that is used to actually write the data to flash. Could there be a flaw somewhere in there? Something with the Flash peripheral itself?


    Thanks!

    Sim

  • Hi Sim,
    I am working on this will get back to you as soon as I have an update. thanks
    Regards
  • Wrapping the flash programming section with IntMasterDisable(); IntMasterEnable(); appears have solved this same issue for me.