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.

CC2650 Write to Internal (128kb) Flash

Other Parts Discussed in Thread: CC2650

Hello,

I am currently using Contiki on the CC2650.  It's a great combo!  I'm currently trying to implement an OTA feature, following the architecture advised by Adam Dunkels:

Basically, I aim to have the internal 128KB flash space be divided between a bootloader and then 2 more partitions of equal size.  When the device receives an upgrade, the older of the 2 equally sized slots is overwritten with this new image.  Finally, the bootloader is responsible for choosing the most recent image, and booting from it.

I have run in to one major roadblock:  I am not entirely sure how write/erase data to the internal (128KB) flash space.

I have seen a forum post indicating that TI was coming out with some sort of NVS module for exactly this type of access.  Is that accurate?  I didn't see anything in TI-RTOS 2.16 that seemed to fit the bill.

I did, however, see flash.h / flash.c, which featured an API with such promising functions as FlashProgram(uint8_t *pui8DataBuffer, uint32_t ui32Address, uint32_t ui32Count).

But is this really the API that will accomplish what I want?  Are these methods work on the 128KB flash?  If so, are there any examples/successful implementations that I can learn from?

Thank you for your time,

Mark Solters

  • Using Contiki, here is an example of how I write to the internal flash using the CC2650:

      #include "driverlib/flash.h"
      
      //  (1) Construct one whole flash page (4096 bytes) of the number "42"
      uint8_t example_data[0x1000];
      for (uint32_t i=0; i<0x1000; i++) {
        example_data[i] = 42;
      }
    
      //  (2)  Write that data to page 1 of internal flash
      FlashProgram(example_data, 0x1000, 0x1000);

    And to read from internal flash, I first define this function myself:

    /**
     *    A helper function to read from the CC26xx Internal Flash.
     *      pui8DataBuffer: Pointer to uint8_t array to store flash data in.
     *      ui32Address: Flash address to begin reading from.
     *      ui32Count: Number of bytes to read from flash, starting at ui32Address.
     */
    void
    FlashRead(uint8_t *pui8DataBuffer, uint32_t ui32Address, uint32_t ui32Count) {
      uint8_t *pui8ReadAddress = (uint8_t *)ui32Address;
      while (ui32Count--) {
        *pui8DataBuffer++ = *pui8ReadAddress++;
      }
    }

    To use it, let's read 20 bytes from address 0x1000:

      //  (1) Construct a buffer to hold 20 bytes
      int read_len = 20;
      uint8_t read_buffer[read_len];
    
      //  (2) Read 20 bytes starting at 0x1000 (flash page 1)
      FlashRead(read_buffer, 0x1000, read_len);
    
      //  (3) Print our buffer out byte by byte!
      printf("Internal flash data read: ");
      for (int i=0; i<read_len; i++) {
        printf("%u ", read_buffer[i]); // Print out each byte as an uint
      }
      printf("\n");

    If you run those one after the other, you should get back 20 "42"s in your console window.  Examining with memory browser, you should see that from 0x1000 - 0x1FFF in flash, every byte is 42 (0x2A) due to our FlashProgram().  But we only read the first 20 bytes from flash in this example.

  • There is little fine point, that if you're reading, and then change the value in flash, you should disable the VIMS Cache(CC13xx-CC26xx Technical Reference Manual, 549), otherwise the following calls read function will return you to the first value. This will continue until you restart or displacing the old data from the cache.

    uint8_t buffer [1];
    FlashRead (buffer, 0x1DA01, 1);
    buffer [0] = 0x55;
    FlashProgram (buffer, 0x1DA01, 1);
    FlashRead (buffer, 0x1DA01, 1);
    printf ( "FLASH TEST READ:% 02X \ n", buffer [0]); 

    FLASH TEST READ: FF, rather than 55, as one would expect.

    It is necessary to modify the reading function this way (if you do not have to read only static data):

    void FlashReadNonCache(uint8_t * pui8DataBuffer, uint32_t ui32Address, uint32_t ui32Count) {
      uint32_t OldVIMSState = VIMSModeGet();
      VIMSModeSet(VIMS_BASE, VIMS_CTL_MODE_GPRAM)
      uint8_t* pui8ReadAddress = (uint8_t *)ui32Address;
      while (ui32Count--) {
        *Pui8DataBuffer++ = * pui8ReadAddress++;
      }
      VIMSModeSet(VIMS_BASE, OldVIMSState)
    }

    You should realize that you can overwrite the bytes flash only lower bytes. It is simple, yet flash after flashing filled FF (any other value will be less), but in the future you may encounter difficulties if you want to overwrite value 0x44 the new value 0x87. Use FlashSectorErase function for cleaning, which receives an address of flash memory sector. The bad news is that the sector size 4Kb, and you can not erase the sector is less than 4KB. The sector address is obtained from the address byte by rounding: 0x1D0AF (byte address) -> 0x1D000 (sector address). When performing FlashSectorErase(0x1D000) will be cleared (set to FF) sector 0x1D000-0x1DFFF.

  • Hi,could you tell me "VIMSModeSet" in which C file?

  • It's in vims.c.