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.

Save data on power loss

Other Parts Discussed in Thread: MSP430F5438

Hey folks,
     We are developing a project using the MSP430F5438 chip that will be used on delivery trailers. Between deliveries, the unit will be powered off.  In the instance that the driver may fail to save the delivery data before turning off the power, or a power failure occurrs during a delivery, I need to save the delivery data in flash and recover it on subsequent powerup. We have a capacitor to alow some time for shutdown.  Also, since we need to maintain power to the RTC, I go into LMP3 after writing data to flash.  We have a watch battery to run the processor in LPM3.  It has been going fairly smoothly so far.  My save and recover routines work, and I detect powerup using DIO and cause a reset.  The reset procedure tests a flag in flash and restores delivery data if flag is set. We have done some timing tests with oscope and it takes < 1ms to save data to flash.

     The problem is that as long as jtag is connected when supply voltage is turned off the data is saved, but if I turn off power with jtag removed, the data is not saved.  If I turn off supply voltage with jtag attached, allowing the data to be saved, then remove jtag, wait, then turn on supply voltage, the saved data is restored correctly.

     We know that our current problem is that I am detecting supply voltage problem using A/D which I am reading at 2Hz.  This is too slow.  Before we go to adding hardware to monitor the supply voltage and cause a DIO interrupt to signal time to save data to flash, I wanted to get the group's opinions on this.  Is this the best way to do this?

     It has also been proposed to try to use the supply voltage monitor in the power management module to detect supply voltage loss but I wonder if there would be time to then save data to flash.  Also moving the battery to the vcore side of the PMM regulator...  I'm basically a software weinie who knows just enough about hardware to get into trouble.  What are your high level thoughts on this?  How do you handle this?

Thanks,
Mike Raines

  • Here is a different scheme.

    We dedicate part of the Flash to store data. We always erase that part of Flash after the stored data is uploaded to a PC. And we always write the data to that part of the Flash when we are collecting data.

    If power fails or other unforeseen events interrupt upload to PC, we re-start the upload from Flash and only erase it after upload is successful.

    If power fails or other unforeseen events interrupt data collection, we will erase the Flash and re-start the data collection.

  • Folks,

         I had forgotten this thread was here.  We have solved this problem nicely.  Since this application does not need to be battery powered, we decided to scrap the going to sleep part, installed an external RTC.  We use the sppply voltage monitor to detect input voltage interruption.  When this interrupt occurs, our capacitors give us enough time to save lots of data to flash before we die and set a flag that lets us know restorative data exists on restart.  Once we restore the data, we erase this part of flash so it is ready for the next power failure.  We also have an algorithm to keep track of several flash locations so we don't always write to the same location and wear out the flash prematurely.  If anyone has further questions, just ask...

    Mike Raines

  • Hi !
    What you have done is exactly what I need ! I made a program to save the variables into the flash memory, but the variables are lost when I loose the power.

    Here is the code:

    #include <msp430.h>
    #include<intrinsics.h>
    int test; int maj;
    int hHeures;
    int hMinutes;
                         // Flash pointer
    int hSecondes;
    
    char *Flash_ptr1;
    char *Flash_ptr2;
    void write_SegC (char value);
    void write_SegD (char value);
    int main(void) {
    	Flash_ptr1 = (char *) 0x1040;
    	Flash_ptr2 = (char *) 0x512;
    	P1DIR = 0x41;
    	// Port P1.2 (entrée 3v dispo) entrée  Port P1.3(reset) Entrée   //POUR TESTER ON MET la led 1 en sortie
    	P2DIR = 0x0F;							//Ports P2.0 (vert)P2.1(orange) et P2.2(rouge) P2.3 sortie 3v Sorties
    	P1OUT=0x00;
    	hHeures=0;
    	hMinutes=0;
    	//CONSTANTES
    	int xHeures1=0;  //limite LED VERTE
    	int xMinutes1=1;
    	int xHeures2=0;  //limite LED ORANGE
    	int xMinutes2=30;
    	int xHeures3=0;  //limite LED ROUGE
    	int xMinutes3=40;
     hMinutes=*Flash_ptr1;
     hHeures=*Flash_ptr2;
    
    	hSecondes=0;
    	// Stop watchdog timer
    	WDTCTL = WDTPW + WDTHOLD ; //Stop watchdog
    	BCSCTL2 = SELS; // SMCLK = LFXT1CLK (quartz)
    	TA0CTL = MC_1 + TASSEL_2 + TACLR; // Up_mode / SMCLK
    	CCTL0 = CCIE; // CCR0 interrupt enabled
    	CCR0 = 32768;
    	_BIS_SR(GIE); // Active les interruptions globales
    	maj=0;
    	while(1){
    		if (maj==1){
    			write_SegC(hMinutes);
    			write_SegD(hHeures);
    			maj=0;
    		}
    		if ((P1IN & 0x80) == 0) {
    			P1OUT = 0x40;
    			if (hHeures<=xHeures1 && hMinutes<xMinutes1){
    				P2OUT=0x01;
    				test=1;
    			}
    			else if (hHeures<=xHeures2 && hMinutes<xMinutes2){
    				P2OUT=0x02;
    				test=2;
    			}
    			else if(hHeures<=xHeures3 && hMinutes<xMinutes3){
    				P2OUT=0x04;
    				test=3;
    			}
    			else {
    				P2OUT=0x0C;
    				test=4;
    			}
    		}
    		else {
    			hMinutes=0;
    			hHeures=0;
    			hSecondes=0;
    			write_SegC(0);
    			write_SegD(0);
    			P1OUT = 0x01;
    		}
    	}
    }
    
    #pragma vector = TIMER0_A0_VECTOR
    __interrupt void Timer_A(void){
    	hSecondes=hSecondes+1;
    	if (hSecondes==10){
    		hMinutes=hMinutes+1;
    		if(hMinutes==1){
    			maj=1;
    		}
    		hSecondes=0;
    		if (hMinutes==60){
    			hMinutes=0;
    			hHeures=hHeures+1;
    			maj=1;
    		}
    	}
    	return;
    }
    void write_SegC (char value)
    {
                                // Flash pointer
    
    
      //Flash_ptr1 = (char *) 0x1040;              // Initialize Flash pointer
      FCTL1 = FWKEY + ERASE;                    // Set Erase bit
      FCTL3 = FWKEY;                            // Clear Lock bit
      *Flash_ptr1 = 0;                           // Dummy write to erase Flash segment
    
      FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
    
     // for (i=0; i<64; i++)
      //{
        *Flash_ptr1 = value;                   // Write value to flash
      //}
    
      FCTL1 = FWKEY;                            // Clear WRT bit
      FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
    }
    void write_SegD (char value)
    {
                                // Flash pointer
    
    
      //Flash_ptr2 = (char *) 0x512;              // Initialize Flash pointer
      FCTL1 = FWKEY + ERASE;                    // Set Erase bit
      FCTL3 = FWKEY;                            // Clear Lock bit
      *Flash_ptr2 = 0;                           // Dummy write to erase Flash segment
    
      FCTL1 = FWKEY + WRT;                      // Set WRT bit for write operation
    
     // for (i=0; i<64; i++)
      //{
        *Flash_ptr2 = value;                   // Write value to flash
      //}
    
      FCTL1 = FWKEY;                            // Clear WRT bit
      FCTL3 = FWKEY + LOCK;                     // Set LOCK bit
    }
    
    

    I don't understand why it doesn't work, can you explain me that please ? :)
    Many thanks !

  • ha ha 2009 thread is revoked again :)

  • Doan Khai HO said:
    I don't understand why it doesn't work,

    You don't write which MSP you are using. Are you sure that on 0x512 and 0x1040 is flash memory? (weird addresses anyway, two so far apart and lonely addresses)

    Remember, those are hexadecimal values, thus 2862 bytes apart and definitely not both in INFO segments, as the function names seem to imply.

    It makes no sense to initialize hMinutes and hHeures to 0 just to assign them a new value a few lines later.

**Attention** This is a public forum