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.

Want to write to Information memory while executing from CPU flash

Other Parts Discussed in Thread: MSP430BT5190, MSP430F5529

Using IAR on MSP430BT5190. I want to write to a location in Information memory segment D while executing in CPU flash. I've tried some examples seen on line but haven't worked. Do I need to erase the segment first before a write?  Do you have working example code of the segment erase followed by a write. I only want to write to the 1st byte of segment D (0x1800).

Thanks

Ralph

  • Erasing changes all bits to one. Writing changes some bits to zero. (See section 7.3 of the User's Guide.)

    It appears there is no example code specifically for the BT5190. However, the flash controller is the same in the family, so have a look at, e.g., the MSP430F5529 example code package.
  • Hi Ralph!

    Ralph Sweitzer said:
    Do I need to erase the segment first before a write?

    As Clemens already said, flash can only be changed from 1 to 0, but not back to 1 again. This can only be done by an erase. And an erase is always for a complete segment. This means, once you erased a segment, you can write your data into the segment, but you cannot overwrite already written data. This needs an erase first. So when planning to change data in a segment, copy the whole content into an array in RAM, change the content in the array, delete the segment and write the array back to the segment.

    Here are a few functions for writing to the flash memory - they were used on the x2xx series MSPs, but I think the flash controller is pretty much identical. You can pick those you need. I normally write the whole segment at once, so I only use three of them:

    • Delete segment
    • Write an array
    • Read an array

    But this depends on your application. Here they are, maybe this helps:

    #FreeSampleCode

    void flash_delete_segment( uint16_t flash_address_in_segment );
    void flash_write_8bit_integer( uint16_t flash_address, uint8_t data );
    uint8_t flash_read_8bit_integer( uint16_t flash_address );
    void flash_write_16bit_integer( uint16_t flash_address, uint16_t data );
    uint16_t flash_read_16bit_integer( uint16_t flash_address );
    void flash_write_32bit_integer( uint16_t flash_address, uint32_t data );
    uint32_t flash_read_32bit_integer( uint16_t flash_address );
    void flash_write_64bit_integer( uint16_t flash_address, uint64_t data );
    uint64_t flash_read_64bit_integer( uint16_t flash_address );
    void flash_write_8bit_integer_array( uint16_t flash_start_address, uint8_t * array, uint8_t array_start_element, uint8_t nr_of_bytes );
    void flash_read_8bit_integer_array( uint16_t flash_start_address, uint8_t * array, uint8_t array_start_element, uint8_t nr_of_bytes );
    void flash_write_16bit_integer_array( uint16_t flash_start_address, uint16_t * array, uint8_t array_start_element, uint8_t nr_of_words );
    void flash_read_16bit_integer_array( uint16_t flash_start_address, uint16_t * array, uint8_t array_start_element, uint8_t nr_of_words );
    
    
    void flash_delete_segment( uint16_t flash_address_in_segment )
    {
      uint8_t * flash_pointer;                                                          // Flash pointer
    
      flash_pointer = (uint8_t *) flash_address_in_segment;                             // Initialize flash pointer
      FCTL3 = FWKEY;                                                                    // Clear lock bit
      FCTL1 = (FWKEY | ERASE);                                                          // Set erase bit - cleared automatically after erase
      *flash_pointer = 0;                                                               // Dummy write to delete segment - CPU hold during erase
      FCTL3 = (FWKEY | LOCK);                                                           // Set lock bit
    }
    
    
    void flash_write_8bit_integer( uint16_t flash_address, uint8_t data )
    {
      uint8_t * flash_pointer;                                                          // Flash pointer
    
      flash_pointer = (uint8_t *) flash_address;                                        // Initialize flash pointer
      FCTL3 = FWKEY;                                                                    // Clear lock bit
      FCTL1 = (FWKEY | WRT);                                                            // Set write bit
      *flash_pointer = data;                                                            // Write data byte - CPU hold during write
      FCTL1 = FWKEY;                                                                    // Clear write bit
      FCTL3 = (FWKEY | LOCK);                                                           // Set lock bit
    }
    
    
    uint8_t flash_read_8bit_integer( uint16_t flash_address )
    {
      uint8_t * flash_pointer;                                                          // Flash pointer
    
      flash_pointer = (uint8_t *) flash_address;                                        // Initialize flash pointer
    
      return *flash_pointer;                                                            // Return data
    }
    
    
    void flash_write_16bit_integer( uint16_t flash_address, uint16_t data )
    {
      uint16_t * flash_pointer;                                                         // Flash pointer
    
      flash_pointer = (uint16_t *) flash_address;                                       // Initialize flash pointer
      FCTL3 = FWKEY;                                                                    // Clear lock bit
      FCTL1 = (FWKEY | WRT);                                                            // Set write bit
      *flash_pointer = data;                                                            // Write data byte - CPU hold during write
      FCTL1 = FWKEY;                                                                    // Clear write bit
      FCTL3 = (FWKEY | LOCK);                                                           // Set lock bit
    }
    
    
    uint16_t flash_read_16bit_integer( uint16_t flash_address )
    {
      uint16_t * flash_pointer;                                                         // Flash pointer
    
      flash_pointer = (uint16_t *) flash_address;                                       // Initialize flash pointer
    
      return *flash_pointer;                                                            // Return data
    }
    
    
    void flash_write_32bit_integer( uint16_t flash_address, uint32_t data )
    {
      flash_write_8bit_integer_array( flash_address, ((uint8_t *) &data), 0, 4 );
    }
    
    
    uint32_t flash_read_32bit_integer( uint16_t flash_address )
    {
      uint32_t data;
    
      flash_read_8bit_integer_array( flash_address, ((uint8_t *) &data), 0, 4 );
    
      return data;
    }
    
    
    void flash_write_64bit_integer( uint16_t flash_address, uint64_t data )
    {
      flash_write_8bit_integer_array( flash_address, ((uint8_t *) &data), 0, 8 );
    }
    
    
    uint64_t flash_read_64bit_integer( uint16_t flash_address )
    {
      uint64_t data;
    
      flash_read_8bit_integer_array( flash_address, ((uint8_t *) &data), 0, 8 );
    
      return data;
    }
    
    
    void flash_write_8bit_integer_array( uint16_t flash_start_address, uint8_t * array, uint8_t array_start_element, uint8_t nr_of_bytes )
    {
      uint8_t counter;                                                                  // Counting variable
      uint8_t * flash_pointer;                                                          // Flash pointer
    
      flash_pointer = (uint8_t *) flash_start_address;                                  // Initialize flash pointer
      FCTL3 = FWKEY;                                                                    // Clear lock bit
      FCTL1 = (FWKEY | WRT);                                                            // Set write bit
    
      for( counter = 0; counter < nr_of_bytes; counter++ )                              // Loop for writing desired number of bytes
      {
        *(flash_pointer + counter) = *(array + array_start_element + counter);          // Copy byte from array to flash
      }
    
      FCTL1 = FWKEY;                                                                    // Clear write bit
      FCTL3 = (FWKEY | LOCK);                                                           // Set lock bit
    }
    
    
    void flash_read_8bit_integer_array( uint16_t flash_start_address, uint8_t * array, uint8_t array_start_element, uint8_t nr_of_bytes )
    {
      uint8_t counter;                                                                  // Counting variable
      uint8_t * flash_pointer;                                                          // Flash pointer
    
      flash_pointer = (uint8_t *) flash_start_address;                                  // Initialize flash pointer
    
      for( counter = 0; counter < nr_of_bytes; counter++ )                              // Loop for reading desired number of bytes
      {
        *(array + array_start_element + counter) = *(flash_pointer + counter);          // Copy byte from flash to array
      }
    }
    
    
    void flash_write_16bit_integer_array( uint16_t flash_start_address, uint16_t * array, uint8_t array_start_element, uint8_t nr_of_words )
    {
      uint8_t counter;                                                                  // Counting variable
      uint16_t * flash_pointer;                                                         // Flash pointer
    
      flash_pointer = (uint16_t *) flash_start_address;                                 // Initialize flash pointer
      FCTL3 = FWKEY;                                                                    // Clear lock bit
      FCTL1 = (FWKEY | WRT);                                                            // Set write bit
    
      for( counter = 0; counter < nr_of_words; counter++ )                              // Loop for writing desired number of words
      {
        *(flash_pointer + counter) = *(array + array_start_element + counter);          // Copy byte from array to flash
      }
    
      FCTL1 = FWKEY;                                                                    // Clear write bit
      FCTL3 = (FWKEY | LOCK);                                                           // Set lock bit
    }
    
    
    void flash_read_16bit_integer_array( uint16_t flash_start_address, uint16_t * array, uint8_t array_start_element, uint8_t nr_of_words )
    {
      uint8_t counter;                                                                  // Counting variable
      uint16_t * flash_pointer;                                                         // Flash pointer
    
      flash_pointer = (uint16_t *) flash_start_address;                                 // Initialize flash pointer
    
      for( counter = 0; counter < nr_of_words; counter++ )                              // Loop for reading desired number of bytes
      {
        *(array + array_start_element + counter) = *(flash_pointer + counter);          // Copy byte from flash to array
      }
    }

    In my applications where I write the whole segment at once, I also use this to load, change and write the array that holds the image of the segment:

    // Note: Values are for a MSP430G2955
    #define FLASH_SEGMENT_BYTE_SIZE                  64
    #define FLASH_START_ADDRESS_INFO_SEGMENT_B       0x1080
    #define FLASH_START_ADDRESS_INFO_SEGMENT_C       0x1040
    #define FLASH_START_ADDRESS_INFO_SEGMENT_D       0x1000
    
    
    void flash_load_segment_to_segment_buffer( uint16_t flash_segment_start_address );
    void flash_extract_data_from_segment_buffer( uint8_t buffer_location, void * target_data_address, uint8_t nr_of_bytes );
    uint8_t flash_add_data_to_segment_buffer( uint8_t buffer_location, void * source_data_address, uint8_t nr_of_bytes );
    void flash_write_segment_buffer_to_segment( uint16_t flash_segment_start_address );
    
    
    uint8_t flash_segment_buffer[FLASH_SEGMENT_BYTE_SIZE];
    
    
    void flash_load_segment_to_segment_buffer( uint16_t flash_segment_start_address )
    {
      flash_read_8bit_integer_array( flash_segment_start_address, flash_segment_buffer, 0, FLASH_SEGMENT_BYTE_SIZE );
    }
    
    
    void flash_extract_data_from_segment_buffer( uint8_t buffer_location, void * target_data_address, uint8_t nr_of_bytes )
    {
      uint8_t counter;
      uint8_t * target_pointer;
    
      target_pointer = (uint8_t *) target_data_address;
    
      for( counter = 0; counter < nr_of_bytes; counter++ )
      {
        *(target_pointer + counter) = flash_segment_buffer[(buffer_location + counter)];
      }
    }
    
    
    uint8_t flash_add_data_to_segment_buffer( uint8_t buffer_location, void * source_data_address, uint8_t nr_of_bytes )
    {
      uint8_t counter;
      uint8_t * source_pointer;
    
      source_pointer = (uint8_t *) source_data_address;
    
      for( counter = 0; counter < nr_of_bytes; counter++ )
      {
        flash_segment_buffer[(buffer_location + counter)] = *(source_pointer + counter);
      }
    
      return counter;
    }
    
    
    void flash_write_segment_buffer_to_segment( uint16_t flash_segment_start_address )
    {
      flash_delete_segment( flash_segment_start_address );
      flash_write_8bit_integer_array( flash_segment_start_address, flash_segment_buffer, 0, FLASH_SEGMENT_BYTE_SIZE );
    }

    And it is never a bad idea to add a checksum at the end of the segment. I often use a simple XOR over all bytes of the segment and store it at the last memory location of that segment. The checksum is of course not included in itself, means it is generated over one byte less than the segment size. Here are two functions for this:

    uint8_t flash_generate_segment_buffer_checksum( void );
    uint8_t flash_test_segment_buffer_checksum( void );
    
    
    uint8_t flash_generate_segment_buffer_checksum( void )
    {
      uint8_t counter;
      uint8_t checksum = 0;
    
      for( counter = 0; counter < (FLASH_SEGMENT_BYTE_SIZE - 1); counter++ )
      {
        checksum ^= flash_segment_buffer[counter];
      }
    
      return checksum;
    }
    
    
    uint8_t flash_test_segment_buffer_checksum( void )
    {
      if( flash_generate_segment_buffer_checksum() == flash_segment_buffer[(FLASH_SEGMENT_BYTE_SIZE - 1)] )
      {
        return 1;
      }
    
      return 0;
    }

    Note: The given code is not for writing to the locked segment A. If you want to write to this one as well, the LOCKA bit must be used, so you would have to add this to the given write procedures.

    Dennis

**Attention** This is a public forum