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.

CC2541: Incorrect values read from flash (device specific)

Part Number: CC2541


We've been building small batches (10 to 50 at a time) of a CC2541-based device, and I've encountered a problem with reading values from flash on 2 devices after successfully building hundreds of units.

Here's the background: we store a small struct starting at flash address 0x86.  It sits on top of the interrupt vector table, and is 44 bytes long.  It's used for controlling various intervals and features of the device.  These settings get programed along side the firmware code as part of our programming processes.  We modify the .hex file before it's flashed with the correct settings.

Here's the problem: one value is not getting read correctly from flash on the 2 problematic devices.  All of the other settings (as far as I can tell) are read correctly.  But there's a catch.  The problematic devices will read the correct value from flash as long as the device stays powered after programming.  Cycling power will cause some other (random) value to be used.  And it's just the one setting.  All of the other settings load correctly.  And it takes a power cycle after programming to cause the setting to be corrupted.

This is the struct that gets located at flash address 0x86.

typedef struct
{
  uint16_t setting1,
  uint16_t setting2,
  uint16_t setting3,
  uint16_t setting4,
  uint16_t setting5,
  uint16_t setting6,
  uint16_t setting7,
  uint32_t setting8,
  uint16_t setting9,
  uint16_t setting10,
  uint16_t setting11,
  uint16_t setting12,
  uint16_t setting13,
  uint16_t setting14,
  uint16_t setting15,
  uint16_t setting16,
  uint32_t setting17,
  uint32_t setting18
} SettingsT;

setting8 is the problematic one.  It starts at flash address 0x102 and is 4 bytes long.  I even read back the flash contents through TI's Flash Programmer, and what's stored in flash matches what was downloaded to the CC2541.  It's not a problem with the value stored in flash.  I tried disabling caching (setting FCTL = 0x00) , but that did not fix the problem.

To reiterate, we have built hundreds of these devices, all running identical firmware, but 2 do not correctly load values from flash.

  • Hi Curtis,

    That is a peculiar problem. Can you try building a simple program that does nothing else than reading back the specific address from Flash? No BLE Stack, etc. Do you still see the problem?

    Regards,
    Fredrik
  • Hi CurtisHx,

    Do you use osal_snv_write and osal_snv_read ? or use HalFlashWrite and HalFlashRead?
  • We're not using any TI libraries (bare metal programming). The firmware directly reads the values from flash. The values are written as part of the .hex file. The firmware does NOT write to flash. Only reads.
  • Fredrik,

    We're not using any TI libraries (no OS, no BLE stack).  Just bare-metal programming.  I could try creating some firmware that just reads from flash, but getting the values out is going to be interesting because one of the steps to reproduce includes power cycling.

    I'm pretty sure it's not a firmware problem.  We have 40+ devices all running the same firmware, but it's only 2 that exhibit this behavior.

    Here's how the settings struct is stored in flash.

    #pragma constseg=__code CONFIGURATION
     __code volatile const SettingsT Settings =
       {
         1, 
         1, 
         1, 
         0, 
         1, 
         60, 
         60, 
         10, 
         86400,
         1, 
         4, 
         300,
         30,
         30,
         30,
         60,
         10 
       };
    #pragma constseg=default

    We're using the IAR compiler.  Here's the part of the linker script that place the CONFIGURATION block in flash.

    //    Top of memory
    //    -------------
    -Z(CODE)INTVEC=0
    -Z(CODE)CONFIGURATION
    -Z(CODE)SLEEP_CODE
    -Z(CODE)CSTART=_CODE0_START-_CODE0_END

    All we're doing in code is reading the various fields from the struct.  For example, to get the first setting, we do

    uint16_t setting = Settings.setting1;

  • Any ideas on what's going wrong? Data is getting corrupted somewhere in between flash and RAM, and that's making me really uncomfortable.
  • Hi Curtis,

    No, I am not sure what is going on here. Are you sure you are mapping the right flash area into XDATA memory space (MEMCTRL.XBANK)? Here is part of our BLE Stack init:

    __low_level_init(void)
    {
      /*==================================*/
      /*  Initialize hardware.            */
      /*==================================*/
      // Map flash bank with constants into XDATA for access to "ROM mapped as data".
    #if defined HAL_IMAGE_A
      MEMCTR = (MEMCTR & 0xF8) | 0x05;
    #elif defined HAL_IMAGE_B
      MEMCTR = (MEMCTR & 0xF8) | 0x04;
    #else
      MEMCTR = (MEMCTR & 0xF8) | 0x01; // Bank 1
    #endif
    
      /*==================================*/
      /* Choose if segment initialization */
      /* should be done or not.           */
      /* Return: 0 to omit seg_init       */
      /*         1 to run seg_init        */
      /*==================================*/
      return 1;
    }
    

    This is how we set up the linker:

    // Define segments for const data in flash.
    // First the segment with addresses as used by the program (flash mapped as XDATA)
    -P(CONST)XDATA_ROM_C=0x8000-0xFFFF
    //
    // Then the segment with addresses as put in the hex file (flash bank 1)
    -P(CODE)XDATA_ROM_C_FLASH=0x18000-0x1FFFF
    //
    // Finally link these segments (XDATA_ROM_C_FLASH is the initializer segment for XDATA_ROM_C,
    // we map the flash in the XDATA address range instead of copying the data to RAM)
    -QXDATA_ROM_C=XDATA_ROM_C_FLASH
    

    Regards,
    Fredrik