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.

MSP430 - Internal Flash Memory Read/Write Problem (MSP430G2955)

Other Parts Discussed in Thread: MSP430G2955

Memory Write :

_DINT(); // Disable Interrupt while (BUSY & FCTL3) ; // Check if Flash being used FCTL2 = FWKEY + FSSEL_1 + FN3; // Clk = SMCLK/4 FCTL1 = FWKEY + ERASE; // Set Erase bit FCTL3 = FWKEY; // Clear Lock bit *mem_address = 0; // Dummy write to erase Flash segment while (BUSY & FCTL3) ; // Check if Flash being used FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Set LOCK bit FCTL2 = FWKEY + FSSEL_1 + FN3; // Clk = SMCLK/4 FCTL3 = FWKEY; // Clear Lock bit FCTL1 = FWKEY + WRT; // Set WRT bit for write operation mem_address = (char *) 0x0E00A; *mem_address = 55; mem_address = (char *) 0x0E00B; *mem_address = temp; // copy value to flash FCTL1 = FWKEY; // Clear WRT bit FCTL3 = FWKEY + LOCK; // Set LOCK bit _EINT(); // Enable Interrupt

Hello,

I am working on a project, which uses the internal memory storage of the Microcontroller - MSP430G2955. The Main purpose is to store two variable into memory locations. So that If the power failure occurs, the previous status can be retrieved from the memory. For that 55D(37H) is stored in the memory location 0x0E00A & temp variable is stored in memory location 0x0E00B.

The problem is, When I use debugger, It works well but when I use external power supply, it does not work. 

For the said problem one can think to review the power supply section, but with the same power supply section and with the same program code the other project works well. 

So please suggest me the possible solutions for the said problem.

The memory read program is also shown here. 

main()
{
        ......
        ......
	mem_address = (char *) 0x0E00A;
	new_var = eeprom_read();
	mem_address = (char *) 0x0E00B;
	temp_var = eeprom_read();
        ......
        ......
}


unsigned char eeprom_read(void)
{
	unsigned char mem_read;
	FCTL2 = FWKEY;
	FCTL3 = FWKEY;
	FCTL1 = FWKEY;
	mem_read = *mem_address;
	return mem_read;
}

  • Hi Mohit!

    What is the clock frequency you are using for the flash controller? Is it inside the specified range of 257 to 476kHz?

    And remember you can only write once to a specified address. When you are flashing the program onto the MSP all memory will get erased. So you can write your data to it. But after that you cannot change the data at the address. At least those bits that are already zero. You can change only from '1' to '0', not the other way. You have to do a segment erase first. Beware of not using a segment where code is located, too. Your addresses aren't in the info-segments. Why don't you use them?

    #define FLASH_INFO_SEG_A_START     0x10C0 // Do not write to segment A
    #define FLASH_INFO_SEG_A_END       0x10FF // Calibration-data stored here
    
    #define FLASH_INFO_SEG_B_START     0x1080
    #define FLASH_INFO_SEG_B_END       0x10BF
    
    #define FLASH_INFO_SEG_C_START     0x1040
    #define FLASH_INFO_SEG_C_END       0x107F
    
    #define FLASH_INFO_SEG_D_START     0x1000
    #define FLASH_INFO_SEG_D_END       0x103F


    Dennis

  • Yes, Thank You very much.... Problem Solved.

    Assigned the proper frequency and runs perfectly.

    Still have a doubt, The memory location is in code memory and code is not there in the specified memory location 0xE000 and so on.
    Can I use the memory location 0xE000 for the storage ? and is it the proper method to use the empty code memory for the status storage ?
  • Yes, of course you can use it. But remember that deleting one byte means deleting a whole segment. So let's say your segment x has 512 bytes (don't know the segment size of that processor now) and your code just reaches slightly inside this segment - the first two bytes for example. If you now store your user data in the last two bytes of that segment and erase it, you will erase code, too.

    So you should specify space for that in the linker command file so that there isn't put code in there or just use the info segments of the processor. These are seperated segments of 64 bytes - I don't know if it is 64 bytes on every processor, but on your one it is. I've posted the addresses of the segments. These are only erased if you want the IDE to to it, otherwise the content is kept in there. Info A contains the calibration data for the 1, 8, 12 and 16MHz settings, for example. Don't use info A if you use those constants and don't need the space. That's why info A has a seperate lock bit.

    Dennis
  • Main code memory has 512 byte segment size on all MSPs (well, except the FR devices, of course, where segment size is 1).
    The info memory, which should be the first choice for dynamically storing non-volatile data, has a segment size of 64 to 256 bytes, depending on total size of 256 to 1024 bytes.
    Writing to code memory should only be done if the info memory isn't large enough. Also, the debugger can be instructed to not erase the info memory when uplaoding a new firmware, so data can remain persistent during an update.

    If code memory is required, then the linker should be told to exclude part of main memory from use (by increasing the start address and decreasing the size of the TEXT segment in the linker script in steps of 512 bytes).
    Another option (without altering the linker script) is to declare an array that is 511 bytes larger than the required space. This ensures that the required space can be found inside the array area with no code reaching in. It does require some runtime pointer calculations. And the location may change on the next build.

**Attention** This is a public forum