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.

[FAQ] MSP430f6779 Supply monitor intrrupt service routine SVSH and SVSL

Other Parts Discussed in Thread: MSP430F6779A, MSP-FET

Hello All,

I want to detect power supply fall and write data to Internal Flash memory.

Actually problem is my code is going in ISR at power ON instead power OFF.

Here is my code 

#include <msp430.h> 

/*
 * main.c
 */
void write_SegC(void);
void copy_from_FlashC(void);
void PMM_config(void);
void UCS_config(void);

char Flash_Data[20] = {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3};
char Flash_Data1[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

int main(void) {
	 WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
	 P1DIR |= BIT0;
	 P1REN |= BIT6;
	 UCS_config();
	PMM_config();
	UCS_config();
while(1)
{

    copy_from_FlashC();
}
return 0;
}
void copy_from_FlashC(void)
    {
        unsigned int i;
        char *Flash_ptrC;
    //    char *Flash_ptrD;

        Flash_ptrC = (char *) 0x1880;           // Initialize Flash segment C ptr


       // Flash_ptrD = (char *) 0x1800;           // Initialize Flash segment D ptr
     //   Flash_ptrD = (char*) Flash_Data[0];

        FCTL3 = FWKEY;                          // Clear Lock bit
     //  FCTL1 = FWKEY | ERASE;                  // Set Erase bit
     //   *Flash_ptrD = 0;                        // Dummy write to erase Flash seg D
      //  FCTL1 = FWKEY | WRT;                    // Set WRT bit for write operation
        FCTL1 = FWKEY;
       FCTL4 = FWKEY | MGR0 ;

        for (i = 0; i < 20; i++)
        {
       //     *Flash_ptrD++ = *Flash_ptrC++;      // copy value segment C to seg D
        		Flash_Data1[i] = *Flash_ptrC++;
        }

        FCTL1 = FWKEY;                          // Clear WRT bit
        FCTL3 = FWKEY | LOCK;                   // Set LOCK bit
    }


    void write_SegC(void)
    {
    	P1OUT |= BIT0;

        unsigned int i;
        char *Flash_ptr;                        // Initialize Flash pointer

        Flash_ptr = (char *)0x1880;

        FCTL3 = FWKEY;                          // Clear Lock bit
        FCTL1 = FWKEY | ERASE;                  // Set Erase bit
        *Flash_ptr = 0;                         // Dummy write to erase Flash seg
        FCTL1 = FWKEY | WRT;                    // Set WRT bit for write operation


        for (i = 0; i < 20; i++)
        {
            *Flash_ptr++ = Flash_Data[i];             // Write value to flash
        }

        FCTL1 = FWKEY;                          // Clear WRT bit
        FCTL3 = FWKEY | LOCK;                   // Set LOCK bit
        P1OUT &= ~BIT0;
    }
    void PMM_config(void)
    {
    	//unlock PMM
          PMMCTL0_H=PMMPW_H;
          PMMCTL0_L|=PMMCOREV_3;
          //check voltage level
          switch(PMMCTL0&PMMCOREV_3)
          {
            //settings for highest core voltage settings
            case PMMCOREV_3:
              //setup high side supervisor and monitor
              SVSMHCTL=SVMHE|SVSHE|SVSHRVL_3|SVSMHRRL_7;
            break;
          }
          //clear interrupt flags
          PMMIFG&=~(SVMLIFG|SVMHIFG|SVMHVLRIFG|SVMLVLRIFG);
          //setup interrupts
          PMMRIE|=SVMLIE|SVMHIE|SVMHVLRIE|SVMLVLRIE;
          //lock PMM
          PMMCTL0_H=0;
    }
#pragma vector = SYSNMI_VECTOR
__interrupt void SYS_NMI(void)
{
  switch(SYSSNIV)
  	  {
		//core supply voltage monitor interrupt
		case SYSSNIV_SVMLIFG:
		  //event to report error
		  //set flag
		break;
		//input supply voltage monitor interrupt
		case SYSSNIV_SVMHIFG:
			 write_SegC();
		//	 Clear_SegC(value);		// For testing only
			//event to report error
		  //set flag
		break;
		//core supply voltage monitor delay interrupt
		case SYSSNIV_DLYLIFG:
		break;
		//interrupt supply voltage monitor delay interrupt
		case SYSSNIV_DLYHIFG:
		break;
		//Vacant memory access interrupt
		case SYSSNIV_VMAIFG:
		break;
		//JTAG mailbox in interrupt
		case SYSSNIV_JMBINIFG:
		break;
		//JTAG mailbox out interrupt
		case SYSSNIV_JMBOUTIFG:
		break;
		//SVMLVLRIFGSVMHVLRIFG
		case SYSSNIV_VLRLIFG:
		  //clear interrupt flag bits
		  //unlock PMM
		  PMMCTL0_H=PMMPW_H;
		  //clear interrupt flags
		  PMMIFG&=~(SVMLIFG|SVMLVLRIFG);
		  //lock PMM
		  PMMCTL0_H=0;
		break;
		//SVMHVLRIFGSVMHVLRIFG
		case SYSSNIV_VLRHIFG:
		  //clear interrupt flag bits
		  //unlock PMM
		  PMMCTL0_H=PMMPW_H;
		  //clear interrupt flags
		  PMMIFG&=~(SVMHIFG|SVMHVLRIFG);
		  //lock PMM
		  PMMCTL0_H=0;
		break;
  	  }
}

void UCS_config(void)
{
		PMMCTL0_H = 0xA5;
		PMMCTL0_L = 0x03;
		UCSCTL0 = UCSCTL0 | 0x1F00;
		UCSCTL1 = UCSCTL1 & 0x0000;
		UCSCTL1 = UCSCTL1 | 0x0040;
		UCSCTL2 = UCSCTL2 & 0x0000 ; // FLL Divider
		UCSCTL2 = UCSCTL2 | 0x304F ; // for 20 MHz MCLK and 2.6 MHz SMCLK
		UCSCTL3 = 0x0000;

		UCSCTL4 = UCSCTL4 & 0X0000;
		UCSCTL4 = UCSCTL4 | 0X0043;
}

Thanks in Advance
Regards
Abhishek Parikh

  • Hi Abishek,

    After debugging through your code and consulting the PMM section of the user's guide, it seems you are enabling both SVM high side interrupt enable and SVM low side interrupt enable in line 99; PMMRIE|=SVMLIE|SVMHIE|SVMHVLRIE|SVMLVLRIE. Additionally, information about how you are entering the interrupt would be helpful for me to debug, from your description, it sounds like the ISR is entering case SYSSNIV_VLRHIFG. A description of your setup and the circumstances that triggers the ISR in debugging would be beneficial.
    From my side, the program doesn't enter ISR when debugging and stays in the copy_from_FlashC(void) function as intended.

    Consulting section 2.2.2 of the user's guide is helpful in determining the register values and functions.
    www.ti.com/.../slau208o.pdf

    Sincerely,
    Sean
  • Hello ,

    Thank you for your reply.

    When I am switching on supply it goes into SYSSNIV_SVMHIFG interrupt.

    I want to monitor DVCC and it should go into ISR when it switching from On to Off. So now only I have enabled SVMHIE by
    PMMRIE|=SVMHIE|SVMHVLRIE.

    Still it is going into ISR when it is powered On.

    While in running mode I have changed the value of my

    Flash_Data[20] = {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3}; to Flash_Data[20] = {11,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3};

    So from that when it switch it on my Flash_Data1[20] should be {11,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3}; but it is same as before {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3}

    Please let me know if I am doing it wrongly.

    Thanks
    Regards

    Abhishek
  • Hello &

    Your code is going into ISR of SYSSNIV_VLRHIFG, when it is power up instead of power down.

    Pl. let me know if there are any other options/method to do so.


    Thanks.
    Regards.

    Dhara
  • Hello ,

    I have tried with PMMRIE|=SVMHIE and PMMRIE |= SVMHVLRIE in both of the cases it is going into ISR while it is OFF->ON instead of ON->OFF.

    Also I have tried detection of CORE voltage by SVSL but in this case it is not going into any ISR.

    Please help

    Thanks

    Regards
    Abhishek
  • Hi Abhishek,

    After some additional testing, here's what I've replicated so far. Sourcing from external supply at initially 3.3V for debug via FET and setting a breakpoint at case SYSSNIV_SVMHIFG: your program continues to run the while(1) loop executing copy_from_FlashC(); and does not enter any interrupts.
    When I start to lower the external voltage from 3.3V in .1V increments, the program will enter the ISR case SYSSNIV_SVMHIFG: write_SegC(); around 2.8V, which can be interpreted as device powering down. Just to clarify, how are you initially debugging the device via FET? What's the supply voltage, and I'm assuming it's an external source?

    Additionally, there seems to be no manipulation/modification of Flash_Data array upon execution in the code, so where are you changing the value of {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3} to {11,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3} in your code, unless the original posted code is now modified slightly.

    Sincerely,
    Sean
  • Hello  ,

    Thanks for your continuous support

    Clicking the value in watch expression window we are changing its value. 

    We have tested it with DC power supply also it is going into ISR when Supply is down to 2.8V but while running in continuous mode with SMPS as MSP430 power supply when I switch off it and switch it On again it goes into ISR write_SegC(). 

    We have checked that while it is going from off to on state it once again goes into  write_SegC(). We have checked this using led at P1.0.

        void write_SegC(void)
        {
        	P1OUT |= BIT0;                           //LED ON
    
            unsigned int i;
            char *Flash_ptr;                        // Initialize Flash pointer
    
            Flash_ptr = (char *)0x1880;
    
    
            FCTL3 = FWKEY;                          // Clear Lock bit
    //        FCTL1 = FWKEY | ERASE;                  // Set Erase bit
    
    
    //        *Flash_ptr = 0;                         // Dummy write to erase Flash seg
    
    
            FCTL1 = FWKEY | WRT;                    // Set WRT bit for write operation
    
    
            for (i = 0; i < 20; i++)
            {
                *Flash_ptr++ = Flash_Data[i];             // Write value to flash
            }
            
            FCTL1 = FWKEY;                          // Clear WRT bit
            FCTL3 = FWKEY | LOCK;                   // Set LOCK bit
           P1OUT &= ~BIT0;                          // LED Off
        }
        }

    Once when I switch off the power my LED blinks and after turning it on back it stays On. I have not used P1OUT anywhere else though.

    Now Here is my full code

    #include <msp430.h> 
    
    /*
     * main.c
     */
    void write_SegC(void);
    void copy_from_FlashC(void);
    void PMM_config(void);
    void UCS_config(void);
    char Flash_Data[20] = {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3};
    char Flash_Data1[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    
    int main(void) {
    	 WDTCTL = WDTPW | WDTHOLD;	// Stop watchdog timer
    	 P1DIR |= BIT0;
    	 P1REN |= BIT6;
    	 PMM_config();
    	 UCS_config();
    	 __delay_cycles(0x3600);
    
    	while(1)
    {
    
        copy_from_FlashC();
    }
    return 0;
    }
    void copy_from_FlashC(void)
        {
            unsigned int i;
            char *Flash_ptrC;
        //    char *Flash_ptrD;
    
            Flash_ptrC = (char *) 0x1880;           // Initialize Flash segment C ptr
    
    
           // Flash_ptrD = (char *) 0x1800;           // Initialize Flash segment D ptr
         //   Flash_ptrD = (char*) Flash_Data[0];
    
        //    FCTL3 = FWKEY;                          // Clear Lock bit
         //  FCTL1 = FWKEY | ERASE;                  // Set Erase bit
         //   *Flash_ptrD = 0;                        // Dummy write to erase Flash seg D
          //  FCTL1 = FWKEY | WRT;                    // Set WRT bit for write operation
        //    FCTL1 = FWKEY;
           FCTL4 = FWKEY | MGR0 ;
    
            for (i = 0; i < 20; i++)
            {
    
            	Flash_Data1[i] = *Flash_ptrC++;
            }
    
       //     FCTL1 = FWKEY;                          // Clear WRT bit
         //   FCTL3 = FWKEY | LOCK;                   // Set LOCK bit
        }
    
    
        void write_SegC(void)
        {
        	
        	P1OUT |= BIT0;
    
            unsigned int i;
            char *Flash_ptr;                        // Initialize Flash pointer
    
            Flash_ptr = (char *)0x1880;
    
    
            FCTL3 = FWKEY;                          // Clear Lock bit
    //        FCTL1 = FWKEY | ERASE;                  // Set Erase bit
    
    
    //        *Flash_ptr = 0;                         // Dummy write to erase Flash seg
    
    
            FCTL1 = FWKEY | WRT;                    // Set WRT bit for write operation
    
    
            for (i = 0; i < 20; i++)
            {
                *Flash_ptr++ = Flash_Data[i];             // Write value to flash
            }
            FCTL1 = FWKEY;                          // Clear WRT bit
            FCTL3 = FWKEY | LOCK;                   // Set LOCK bit
            P1OUT &= ~BIT0;
        }
        
        void PMM_config(void)
        {
        	//unlock PMM
              PMMCTL0_H=PMMPW_H;
              PMMCTL0_L|=PMMCOREV_3;
              //check voltage level
              switch(PMMCTL0&PMMCOREV_3)
              {
                //settings for highest core voltage settings
                case PMMCOREV_3:
                  //setup high side supervisor and monitor
                  SVSMHCTL=SVMHE|SVSHE|SVSHRVL_3|SVSMHRRL_7;
                break;
              }
              //clear interrupt flags
              PMMIFG&=~(SVMLIFG|SVMHIFG|SVMHVLRIFG|SVMLVLRIFG);
              //setup interrupts
             // PMMRIE|=SVMHIE|SVMHVLRIE;
              PMMRIE|=SVMLIE|SVMHIE|SVMHVLRIE|SVMLVLRIE;
              //lock PMM
              PMMCTL0_H=0;
        }
    #pragma vector = SYSNMI_VECTOR
    __interrupt void SYS_NMI(void)
    {
      switch(SYSSNIV)
      	  {
    		//core supply voltage monitor interrupt
    		case SYSSNIV_SVMLIFG:
    		  //event to report error
    		  //set flag
    		break;
    		//input supply voltage monitor interrupt
    		case SYSSNIV_SVMHIFG:
    			 write_SegC();
    		//	 PMM_config();
    		//	 Clear_SegC(value);		// For testing only
    			//event to report error
    		  //set flag
    		break;
    		//core supply voltage monitor delay interrupt
    		case SYSSNIV_DLYLIFG:
    		break;
    		//interrupt supply voltage monitor delay interrupt
    		case SYSSNIV_DLYHIFG:
    		break;
    		//Vacant memory access interrupt
    		case SYSSNIV_VMAIFG:
    		break;
    		//JTAG mailbox in interrupt
    		case SYSSNIV_JMBINIFG:
    		break;
    		//JTAG mailbox out interrupt
    		case SYSSNIV_JMBOUTIFG:
    		break;
    		//SVMLVLRIFGSVMHVLRIFG
    		case SYSSNIV_VLRLIFG:
    		  //clear interrupt flag bits
    		  //unlock PMM
    			//write_SegC();
    		  PMMCTL0_H=PMMPW_H;
    		  //clear interrupt flags
    		  PMMIFG&=~(SVMLIFG|SVMLVLRIFG);
    		  //lock PMM
    		  PMMCTL0_H=0;
    		break;
    		//SVMHVLRIFGSVMHVLRIFG
    		case SYSSNIV_VLRHIFG:
    		  //clear interrupt flag bits
    		  //unlock PMM
    //			 write_SegC();
    			PMMCTL0_H=PMMPW_H;
    		  //clear interrupt flags
    		  PMMIFG&=~(SVMHIFG|SVMHVLRIFG);
    		  //lock PMM
    		  PMMCTL0_H=0;
    		 PMM_config();
    
    		  break;
      	  }
    }
    
    void UCS_config(void)
    {
    		PMMCTL0_H = 0xA5;
    		PMMCTL0_L = 0x03;
    		UCSCTL0 = UCSCTL0 | 0x1F00;
    		UCSCTL1 = UCSCTL1 & 0x0000;
    		UCSCTL1 = UCSCTL1 | 0x0040;
    		UCSCTL2 = UCSCTL2 & 0x0000 ; // FLL Divider
    		UCSCTL2 = UCSCTL2 | 0x304F ; // for 20 MHz MCLK and 2.6 MHz SMCLK
    		UCSCTL3 = 0x0000;
    
    		UCSCTL4 = UCSCTL4 & 0X0000;
    		UCSCTL4 = UCSCTL4 | 0X0043;
    
    		//   UCSCTL5 = UCSCTL5 | 0x0040;
    		//   UCSCTL6 =;
    		//   UCSCTL7 =;
    		//   UCSCTL8 =;
    		//   PMMCTL0 = PMMCTL0 | 0x0003;
    		//   UCSCTL2 = UCSCTL2 | 0X001F;
    		//   UCSCTL6 = UCSCTL6 | 0X00B0;
    
    		// Setup LFXT1
    /*
    			UCSCTL6 &= ~(XT1OFF);                   // XT1 On
    
    			UCSCTL6 |= XCAP_3;                      // Internal load cap
    
    
    		// Loop until XT1 fault flag is cleared
    
    
    		do
    			{
    				UCSCTL6 &= ~(XT2OFFG | XT1LFOFFG | DCOFFG);
    				// Clear XT2,XT1,DCO fault flags
    
    				SFRIFG1 &= ~OFIFG;                  // Clear fault flags
    
    			}
    		while (SFRIFG1 & OFIFG);              // Test oscillator fault flag
    		*/
    
    //		P1SEL0 =  P1SEL0 | 0X34;
    	//    P1SEL1 =  P1SEL1  & 0XCB;
    //		P1DIR  = P1DIR | 0X34;
    	 //   CPBD = 0X00;
    }
    
    

    Thanks In Advance

    Regards

    Dhara

  • Hello

    In my case When I have powered MSP with its debugger and starting from 3.3V changing its value gradually using variable resistor after a 2.3V MSP goes from Running to No Power mode.

    When I have given another power supply from USB/Battery and I am changing it from 3.3V to down at 2.8V nothing happens, and at 1.4 V my program is going in its ISR write_SegC().

    I am making Flash_Data [20] = {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3} to {11,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3} during runtime as shown in above screenshot expression value has been changed from watch window.

    Thanks
    Regards
    Abhishek
  • Hello &

    I came across one more thing regarding the above code..

    In the PMM_config(), can we directly set the PMM core level (line 91-92)..??

    PMMCTL0_H=PMMPW_H;
    PMMCTL0_L|=PMMCOREV_3;




    Thanks.
    Regards.

    Dhara
  • Hello,

    I will look into the issues described above, but just to quickly reference the PMM registers and Flash_Data questions. The registers can be modified and I've attached a graph from the datasheet describing the specific PMMCOREV_X values and supply voltage relations. As for the array, after changing it in the watch expression, did the program execute to write_SegC(void) first before copying over to Flash_Data1 in the copy_from_FlashC(void) function?

     Sincerely,

    Sean

  • Hello

    In continuous mode we have just powered off the MSP430 after setting the watch expressions

    Thanks

    Regards
    Abhishek
  • And about the PMMCOREVx levels actually we are aware of it but the question is as mentioned in Userguide section 2.4.4 can we directly write PMMCOREV to level 3 or we have to increase it step wise.
  • The User's Guide is quite clear how this is to be done. Don't do it differently.
  • Hello

    Can I configure PMM directly by writing following?

    PMMCTL0_H=PMMPW_H;
    PMMCTL0_L|=PMMCOREV_3;
  • Hi,

    Yes, those register values are valid for configuring the PMM.

    Sincerely,
    Sean
  • Hello

    I have changed values in watch expressions and than lowered my voltage and got the updated values but at 1.4V.
    So according to It may be problem for writing PMMCORE value as it goes at very lower voltage.

    I'll try once and let you know the results after placing PMMCORE register loop

    Thanks and
  • Hello  

    I have added another function for Vcoreup

    void SetVCoreUp (unsigned int level)
        {
        // Open PMM registers for write access
        PMMCTL0_H = 0xA5;
        // Make sure no flags are set for iterative sequences
        while ((PMMIFG & SVSMHDLYIFG) == 0);
        while ((PMMIFG & SVSMLDLYIFG) == 0);
        // Set SVS/SVM high side new level
        SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
        // Set SVM low side to new level
        SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
        // Wait till SVM is settled
        while ((PMMIFG & SVSMLDLYIFG) == 0);
        // Clear already set flags
        PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
        // Set VCore to new level
        PMMCTL0_L = PMMCOREV0 * level;
        // Wait till new level reached
        if ((PMMIFG & SVMLIFG))
        while ((PMMIFG & SVMLVLRIFG) == 0);
        // Set SVS/SVM low side to new level
        SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
        // Lock PMM registers for write access
        PMMCTL0_H = 0x00;
        }

    But my program stuck at second line

    while ((PMMIFG & SVSMHDLYIFG) == 0);

     

    Thanks

    Regards

    Abhishek

  • Hello

    Monitoring PMMIFG register gives value of 0x0050 which means SVSMHDLYIFG and SVMHVLRIFG.
    Now I am continuously checking as in while loop.
    So May I change SYSSNIV_DLYHIFG?

    And if yes than change to what.

    Thanks
    Regards
    Abhishek
  • The order of these operations appears to be wrong; the SVM delay interrupt flag will be set only after a change.

    This is how it's done in TI's example code:

    void SetVcoreUp (unsigned int level)
    {
      // Open PMM registers for write
      PMMCTL0_H = PMMPW_H;              
      // Set SVS/SVM high side new level
      SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
      // Set SVM low side to new level
      SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
      // Wait till SVM is settled
      while ((PMMIFG & SVSMLDLYIFG) == 0);
      // Clear already set flags
      PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
      // Wait till new level reached
      if ((PMMIFG & SVMLIFG))
        while ((PMMIFG & SVMLVLRIFG) == 0);
      // Set SVS/SVM low side to new level
      SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
    }
  • Hi Sean Huang15 (4399189) , Clemens Ladisch (508254)  and ABHISHEK PARIKH (4398096)

    Thank you for your constant guidance and support..

    I tried to set the VCore level with the above TI's example code but its not going to any of the ISR even when the supply is down to 1.4V..

    Please suggest me way to do so..

    Here is my code

    #include <msp430.h> 
    
    void write_SegC(void);
    void copy_from_FlashC(void);
    void PMM_config(void);
    void UCS_config(void);
    void SetVCoreUp(unsigned int);
    //void SetVCoreUp(void);
    
    char Flash_Data[20] = {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3};
    char Flash_Data1[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    
    
    void main(void) {
         WDTCTL = WDTPW | WDTHOLD;  // Stop watchdog timer
         P1DIR |= BIT0;
         P1REN |= BIT6;
    
        SetVCoreUp(3);
        PMM_config();
        UCS_config();
    while(1)
    {
        copy_from_FlashC();
    }
    }
    
    void PMM_config(void)
     {
            //check voltage level
           switch(PMMCTL0&PMMCOREV_3)
           {
             //settings for highest core voltage settings
             case PMMCOREV_3:
               //setup high side supervisor and monitor
               SVSMHCTL=SVMHE|SVSHE|SVSHRVL_3|SVSMHRRL_7;
             break;
           }
           //clear interrupt flags
           PMMIFG&=~(SVMLIFG|SVMHIFG|SVMHVLRIFG|SVMLVLRIFG|SVSMHDLYIFG);
           //setup interrupts
           PMMRIE|=SVMLIE|SVMHIE|SVMHVLRIE|SVMLVLRIE;
           //lock PMM
           PMMCTL0_H=0;
     }
    
    void SetVCoreUp (unsigned int level)
    {
      // Open PMM registers for write
      PMMCTL0_H = PMMPW_H;
      // Set SVS/SVM high side new level
      SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
      // Set SVM low side to new level
      SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
      // Wait till SVM is settled
      while ((PMMIFG & SVSMLDLYIFG) == 0);
      // Clear already set flags
      PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
      // Wait till new level reached
      if ((PMMIFG & SVMLIFG))
        while ((PMMIFG & SVMLVLRIFG) == 0);
      // Set SVS/SVM low side to new level
      SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
    }
    
    
    
    void copy_from_FlashC(void)
        {
            unsigned int i;
            char *Flash_ptrC;
        //    char *Flash_ptrD;
    
            Flash_ptrC = (char *) 0x1880;           // Initialize Flash segment C ptr
    
    
           // Flash_ptrD = (char *) 0x1800;           // Initialize Flash segment D ptr
         //   Flash_ptrD = (char*) Flash_Data[0];
    
            FCTL3 = FWKEY;                          // Clear Lock bit
         //  FCTL1 = FWKEY | ERASE;                  // Set Erase bit
         //   *Flash_ptrD = 0;                        // Dummy write to erase Flash seg D
          //  FCTL1 = FWKEY | WRT;                    // Set WRT bit for write operation
            FCTL1 = FWKEY;
           FCTL4 = FWKEY | MGR0 ;
    
            for (i = 0; i < 20; i++)
            {
           //     *Flash_ptrD++ = *Flash_ptrC++;      // copy value segment C to seg D
                    Flash_Data1[i] = *Flash_ptrC++;
            }
    
            FCTL1 = FWKEY;                          // Clear WRT bit
            FCTL3 = FWKEY | LOCK;                   // Set LOCK bit
        }
    
    
        void write_SegC(void)
        {
            P1OUT |= BIT0;
    
            unsigned int i;
            char *Flash_ptr;                        // Initialize Flash pointer
    
            Flash_ptr = (char *)0x1880;
    
            FCTL3 = FWKEY;                          // Clear Lock bit
            FCTL1 = FWKEY | ERASE;                  // Set Erase bit
            *Flash_ptr = 0;                         // Dummy write to erase Flash seg
            FCTL1 = FWKEY | WRT;                    // Set WRT bit for write operation
    
    
            for (i = 0; i < 20; i++)
            {
                *Flash_ptr++ = Flash_Data[i];             // Write value to flash
            }
    
            FCTL1 = FWKEY;                          // Clear WRT bit
            FCTL3 = FWKEY | LOCK;                   // Set LOCK bit
            P1OUT &= ~BIT0;
        }
    
    #pragma vector = SYSNMI_VECTOR
    __interrupt void SYS_NMI(void)
    {
      switch(SYSSNIV)
          {
            //core supply voltage monitor interrupt
            case SYSSNIV_SVMLIFG:
              //event to report error
              //set flag
            break;
            //input supply voltage monitor interrupt
            case SYSSNIV_SVMHIFG:
                 write_SegC();
            //   Clear_SegC(value);     // For testing only
                //event to report error
              //set flag
            break;
            //core supply voltage monitor delay interrupt
            case SYSSNIV_DLYLIFG:
            	PMMIFG=0;
            	break;
            //interrupt supply voltage monitor delay interrupt
            case SYSSNIV_DLYHIFG:
            	PMMIFG=0;
            break;
            //Vacant memory access interrupt
            case SYSSNIV_VMAIFG:
            break;
            //JTAG mailbox in interrupt
            case SYSSNIV_JMBINIFG:
            break;
            //JTAG mailbox out interrupt
            case SYSSNIV_JMBOUTIFG:
            break;
            //SVMLVLRIFGSVMHVLRIFG
            case SYSSNIV_VLRLIFG:
              //clear interrupt flag bits
              //unlock PMM
              PMMCTL0_H=PMMPW_H;
              //clear interrupt flags
              PMMIFG&=~(SVMLIFG|SVMLVLRIFG);
              //lock PMM
              PMMCTL0_H=0;
            break;
            //SVMHVLRIFGSVMHVLRIFG
            case SYSSNIV_VLRHIFG:
              //clear interrupt flag bits
              //unlock PMM
              PMMCTL0_H=PMMPW_H;
              //clear interrupt flags
              PMMIFG&=~(SVMHIFG|SVMHVLRIFG);
              //lock PMM
              PMMCTL0_H=0;
            break;
          }
    }
    
    void UCS_config(void)
    {
    		//PMMCTL0_H = 0xA5;
    		//PMMCTL0_L = 0x03;
    		UCSCTL0 = UCSCTL0 | 0x1F00;
    		UCSCTL1 = UCSCTL1 & 0x0000;
    		UCSCTL1 = UCSCTL1 | 0x0040;
    		UCSCTL2 = UCSCTL2 & 0x0000 ; // FLL Divider
    		UCSCTL2 = UCSCTL2 | 0x304F ; // for 20 MHz MCLK and 2.6 MHz SMCLK
    		UCSCTL3 = 0x0000;
    
    		UCSCTL4 = UCSCTL4 & 0X0000;
    		UCSCTL4 = UCSCTL4 | 0X0043;
    }
    
    

    Thanks in advance.

    Dhara

  • The core voltage must be increased in steps of one.

    This PMM_config function does not unlock the PMM.
  • Hi Dhara,

    Just to provide additional info, your code runs into an error when modifying the SVSMHCTL register in the PMM_config() function when I try to step by step debug. Adding PMMCTL0_H=PMMPW_H; at the beginning of the function fixes that problem.

    Sincerely,
    Sean

  • Hi and ,

    Thanks for your reply...

    I added PMMCTL0_H=PMMPW_H in the function PMM_config() and now the code is going in ISR but at 0.8V drop..

    I need ISR to be called at the drop level of 2.4V so that there is sufficient time to write data in flash.

    Pls let me know the way how I can achieve this..


    Thanks & Regards,

    Dhara.
  • Hi Dhara,

    I think adjusting it to be 2.4V would be in your PMM_config and PMMCOREV_X values. Referring back to the supply voltage graph on page 1, it seems only levels 0,1,2 are bounded by 2.4V.

    Sincerely,
    Sean
  • Hi Dhara,

    First, let's make sure that Vcore has been set up properly, since it's critical that Vcore level be increased by only one level at a time (like  pointed out in a previous post). In your code shown below, I see you're using the SetVCoreUp code example from the User's Guide.

    #include <msp430.h> 
    
    void write_SegC(void);
    void copy_from_FlashC(void);
    void PMM_config(void);
    void UCS_config(void);
    void SetVCoreUp(unsigned int);
    //void SetVCoreUp(void);
    
    char Flash_Data[20] = {0,0,3,4,5,6,7,8,0,0,0,5,5,5,0,8,8,9,2,3};
    char Flash_Data1[20] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
    
    
    void main(void) {
         WDTCTL = WDTPW | WDTHOLD;  // Stop watchdog timer
         P1DIR |= BIT0;
         P1REN |= BIT6;
    
        SetVCoreUp(3);
        PMM_config();
        UCS_config();
    while(1)
    {
        copy_from_FlashC();
    }
    }
    
    void PMM_config(void)
     {
            //check voltage level
           switch(PMMCTL0&PMMCOREV_3)
           {
             //settings for highest core voltage settings
             case PMMCOREV_3:
               //setup high side supervisor and monitor
               SVSMHCTL=SVMHE|SVSHE|SVSHRVL_3|SVSMHRRL_7;
             break;
           }
           //clear interrupt flags
           PMMIFG&=~(SVMLIFG|SVMHIFG|SVMHVLRIFG|SVMLVLRIFG|SVSMHDLYIFG);
           //setup interrupts
           PMMRIE|=SVMLIE|SVMHIE|SVMHVLRIE|SVMLVLRIE;
           //lock PMM
           PMMCTL0_H=0;
     }
    
    void SetVCoreUp (unsigned int level)
    {
      // Open PMM registers for write
      PMMCTL0_H = PMMPW_H;
      // Set SVS/SVM high side new level
      SVSMHCTL = SVSHE + SVSHRVL0 * level + SVMHE + SVSMHRRL0 * level;
      // Set SVM low side to new level
      SVSMLCTL = SVSLE + SVMLE + SVSMLRRL0 * level;
      // Wait till SVM is settled
      while ((PMMIFG & SVSMLDLYIFG) == 0);
      // Clear already set flags
      PMMIFG &= ~(SVMLVLRIFG + SVMLIFG);
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
      // Wait till new level reached
      if ((PMMIFG & SVMLIFG))
        while ((PMMIFG & SVMLVLRIFG) == 0);
      // Set SVS/SVM low side to new level
      SVSMLCTL = SVSLE + SVSLRVL0 * level + SVMLE + SVSMLRRL0 * level;
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
    }

    Can you try using the SetVCore functions (found in the 'HAL_PMM.c' code example) instead?

    This file and its related header file can be found in the following location after downloading and installing MSPWare: C:\ti\msp\MSPWare_3_30_00_18\examples\boards\MSP-EXP430F5529\MSP-EXP430F5529_UE_Demo_Software\Firmware\Source\F5xx_F6xx_Core_Lib

    HAL_PMM.c
    /*******************************************************************************
     *
     * HAL_PMM.c
     * Power Management Module Library for MSP430F5xx/6xx family
     *
     *
     * Copyright (C) 2010 Texas Instruments Incorporated - http://www.ti.com/
     *
     *
     *  Redistribution and use in source and binary forms, with or without
     *  modification, are permitted provided that the following conditions
     *  are met:
     *
     *    Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     *    Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the
     *    distribution.
     *
     *    Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     *  THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
     *  "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
     *  LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
     *  A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
     *  OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
     *  SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
     *  LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
     *  DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
     *  THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
     *  (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
     *  OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     *
     ******************************************************************************/
    
    #include "msp430.h"
    #include "HAL_PMM.h"
    
    /*******************************************************************************
     * \brief   Increase Vcore by one level
     *
     * \param level     Level to which Vcore needs to be increased
     * \return status   Success/failure
     ******************************************************************************/
    
    static uint16_t SetVCoreUp(uint8_t level)
    {
        uint16_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
    
        // The code flow for increasing the Vcore has been altered to work around
        // the erratum FLASH37.
        // Please refer to the Errata sheet to know if a specific device is affected
        // DO NOT ALTER THIS FUNCTION
    
        // Open PMM registers for write access
        PMMCTL0_H = 0xA5;
    
        // Disable dedicated Interrupts
        // Backup all registers
        PMMRIE_backup = PMMRIE;
        PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE | SVSLPE | SVMHVLRIE |
                    SVMHIE | SVSMHDLYIE | SVMLVLRIE | SVMLIE | SVSMLDLYIE);
        SVSMHCTL_backup = SVSMHCTL;
        SVSMLCTL_backup = SVSMLCTL;
    
        // Clear flags
        PMMIFG = 0;
    
        // Set SVM highside to new level and check if a VCore increase is possible
        SVSMHCTL = SVMHE | SVSHE | (SVSMHRRL0 * level);
    
        // Wait until SVM highside is settled
        while ((PMMIFG & SVSMHDLYIFG) == 0) ;
    
        // Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        // Check if a VCore increase is possible
        if ((PMMIFG & SVMHIFG) == SVMHIFG){     // -> Vcc is too low for a Vcore increase
            // recover the previous settings
            PMMIFG &= ~SVSMHDLYIFG;
            SVSMHCTL = SVSMHCTL_backup;
    
            // Wait until SVM highside is settled
            while ((PMMIFG & SVSMHDLYIFG) == 0) ;
    
            // Clear all Flags
            PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
    
            PMMRIE = PMMRIE_backup;             // Restore PMM interrupt enable register
            PMMCTL0_H = 0x00;                   // Lock PMM registers for write access
            return PMM_STATUS_ERROR;            // return: voltage not set
        }
    
        // Set also SVS highside to new level
        // Vcc is high enough for a Vcore increase
        SVSMHCTL |= (SVSHRVL0 * level);
    
        // Wait until SVM highside is settled
        while ((PMMIFG & SVSMHDLYIFG) == 0) ;
    
        // Clear flag
        PMMIFG &= ~SVSMHDLYIFG;
    
        // Set VCore to new level
        PMMCTL0_L = PMMCOREV0 * level;
    
        // Set SVM, SVS low side to new level
        SVSMLCTL = SVMLE | (SVSMLRRL0 * level) | SVSLE | (SVSLRVL0 * level);
    
        // Wait until SVM, SVS low side is settled
        while ((PMMIFG & SVSMLDLYIFG) == 0) ;
    
        // Clear flag
        PMMIFG &= ~SVSMLDLYIFG;
        // SVS, SVM core and high side are now set to protect for the new core level
    
        // Restore Low side settings
        // Clear all other bits _except_ level settings
        SVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
    
        // Clear level settings in the backup register,keep all other bits
        SVSMLCTL_backup &= ~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
    
        // Restore low-side SVS monitor settings
        SVSMLCTL |= SVSMLCTL_backup;
    
        // Restore High side settings
        // Clear all other bits except level settings
        SVSMHCTL &= (SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
    
        // Clear level settings in the backup register,keep all other bits
        SVSMHCTL_backup &= ~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
    
        // Restore backup
        SVSMHCTL |= SVSMHCTL_backup;
    
        // Wait until high side, low side settled
        while (((PMMIFG & SVSMLDLYIFG) == 0) && ((PMMIFG & SVSMHDLYIFG) == 0)) ;
    
        // Clear all Flags
        PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
    
        PMMRIE = PMMRIE_backup;                 // Restore PMM interrupt enable register
        PMMCTL0_H = 0x00;                       // Lock PMM registers for write access
    
        return PMM_STATUS_OK;
    }
    
    /*******************************************************************************
     * \brief  Decrease Vcore by one level
     *
     * \param  level    Level to which Vcore needs to be decreased
     * \return status   Success/failure
     ******************************************************************************/
    
    static uint16_t SetVCoreDown(uint8_t level)
    {
        uint16_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
    
        // The code flow for decreasing the Vcore has been altered to work around
        // the erratum FLASH37.
        // Please refer to the Errata sheet to know if a specific device is affected
        // DO NOT ALTER THIS FUNCTION
    
        // Open PMM registers for write access
        PMMCTL0_H = 0xA5;
    
        // Disable dedicated Interrupts
        // Backup all registers
        PMMRIE_backup = PMMRIE;
        PMMRIE &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE | SVSLPE | SVMHVLRIE |
                    SVMHIE | SVSMHDLYIE | SVMLVLRIE | SVMLIE | SVSMLDLYIE);
        SVSMHCTL_backup = SVSMHCTL;
        SVSMLCTL_backup = SVSMLCTL;
    
        // Clear flags
        PMMIFG &= ~(SVMHIFG | SVSMHDLYIFG | SVMLIFG | SVSMLDLYIFG);
    
        // Set SVM, SVS high & low side to new settings in normal mode
        SVSMHCTL = SVMHE | (SVSMHRRL0 * level) | SVSHE | (SVSHRVL0 * level);
        SVSMLCTL = SVMLE | (SVSMLRRL0 * level) | SVSLE | (SVSLRVL0 * level);
    
        // Wait until SVM high side and SVM low side is settled
        while ((PMMIFG & SVSMHDLYIFG) == 0 || (PMMIFG & SVSMLDLYIFG) == 0) ;
    
        // Clear flags
        PMMIFG &= ~(SVSMHDLYIFG + SVSMLDLYIFG);
        // SVS, SVM core and high side are now set to protect for the new core level
    
        // Set VCore to new level
        PMMCTL0_L = PMMCOREV0 * level;
    
        // Restore Low side settings
        // Clear all other bits _except_ level settings
        SVSMLCTL &= (SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
    
        // Clear level settings in the backup register,keep all other bits
        SVSMLCTL_backup &= ~(SVSLRVL0 + SVSLRVL1 + SVSMLRRL0 + SVSMLRRL1 + SVSMLRRL2);
    
        // Restore low-side SVS monitor settings
        SVSMLCTL |= SVSMLCTL_backup;
    
        // Restore High side settings
        // Clear all other bits except level settings
        SVSMHCTL &= (SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
    
        // Clear level settings in the backup register, keep all other bits
        SVSMHCTL_backup &= ~(SVSHRVL0 + SVSHRVL1 + SVSMHRRL0 + SVSMHRRL1 + SVSMHRRL2);
    
        // Restore backup
        SVSMHCTL |= SVSMHCTL_backup;
    
        // Wait until high side, low side settled
        while (((PMMIFG & SVSMLDLYIFG) == 0) && ((PMMIFG & SVSMHDLYIFG) == 0)) ;
    
        // Clear all Flags
        PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
    
        PMMRIE = PMMRIE_backup;                // Restore PMM interrupt enable register
        PMMCTL0_H = 0x00;                      // Lock PMM registers for write access
        return PMM_STATUS_OK;                  // Return: OK
    }
    
    uint16_t SetVCore(uint8_t level)
    {
        uint16_t actlevel;
        uint16_t status = 0;
    
        level &= PMMCOREV_3;                   // Set Mask for Max. level
        actlevel = (PMMCTL0 & PMMCOREV_3);     // Get actual VCore
                                               // step by step increase or decrease
        while ((level != actlevel) && (status == 0)) {
            if (level > actlevel){
                status = SetVCoreUp(++actlevel);
            }
            else {
                status = SetVCoreDown(--actlevel);
            }
        }
    
        return status;
    }
    
    

    HAL_PMM.h

    Next, you'll want to increment Vcore using these new SetVCore functions. The SetVCore function takes care of increasing the Vcore increments using the SetVCoreUp function. According to the User's Guide, a reset defaults Vcore and all the PMM thresholds to their lowest possible levels.

    Using the MSP430F6779A and its target development board, I used the following code to verify that these SetVCore functions worked and verified that PMMCOREV=3. Please note that I added the following two paths to my Includes in CCS:

    • "C:\ti\msp\MSPWare_3_30_00_18\examples\boards\MSP-EXP430F5529\MSP-EXP430F5529_UE_Demo_Software\Firmware\Source\F5xx_F6xx_Core_Lib"
    • "C:\ti\msp\MSPWare_3_30_00_18\examples\boards\MSP-EXP430F5529\MSP-EXP430F5529_UE_Demo_Software\Firmware\Source\UserExperienceDemo"
    #include <stdint.h>
    #include "msp430.h"
    #include "HAL_PMM.h"
    #include "HAL_UCS.h"
    #include "PMM.h"
    
    void PMM_config(void);
    void UCS_config(void);
    
    void main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;  	// Stop watchdog timer
    	P1DIR |= 0x01;				// Set P1.0 to output direction
    	
    	SetVCore(3);
    	//PMM_config();
    	UCS_config();
    	while(1)
    	{
    		for(;;) {
    			volatile unsigned int i;	// volatile to prevent optimization
    
    			P1OUT ^= 0x01;				// Toggle P1.0 using exclusive-OR
    
    			i = 10000;					// SW Delay
    			do i--;
    			while(i != 0);
    		}
    	}
    }
    
    void PMM_config(void)
    {
        //check voltage level
    	switch(PMMCTL0&PMMCOREV_3)
    	{
    	 //settings for highest core voltage settings
    	 case PMMCOREV_3:
    	   //setup high side supervisor and monitor
    	   SVSMHCTL=SVMHE|SVSHE|SVSHRVL_3|SVSMHRRL_7;
    	 break;
    	}
    	//clear interrupt flags
    	PMMIFG&=~(SVMLIFG|SVMHIFG|SVMHVLRIFG|SVMLVLRIFG|SVSMHDLYIFG);
    	//setup interrupts
    	PMMRIE|=SVMLIE|SVMHIE|SVMHVLRIE|SVMLVLRIE;
    	//lock PMM
    	PMMCTL0_H=0;
     }
    
    void UCS_config(void)
    {
    	//PMMCTL0_H = 0xA5;
    	//PMMCTL0_L = 0x03;
    	UCSCTL0 = UCSCTL0 | 0x1F00;
    	UCSCTL1 = UCSCTL1 & 0x0000;
    	UCSCTL1 = UCSCTL1 | 0x0040;
    	UCSCTL2 = UCSCTL2 & 0x0000 ; // FLL Divider
    	UCSCTL2 = UCSCTL2 | 0x304F ; // for 20 MHz MCLK and 2.6 MHz SMCLK
    	UCSCTL3 = 0x0000;
    
    	UCSCTL4 = UCSCTL4 & 0X0000;
    	UCSCTL4 = UCSCTL4 | 0X0043;
    }

    Next, I'll take a look at your PMM_config() function.

    Regards,

    James

    MSP Customer Applications

  • Thanks

    Actually the supply to my controller board is 3.05 V.. Is it possible to get in PMM ISR at the voltage drop of 2.4V level..??


    Regards,
    Dhara
  • Hi Dhara,

    Dhara Pandya said:
    Actually the supply to my controller board is 3.05 V..

    That's fine. The DVCC supply voltage is internally regulated down to VCore. Since VCore has been specified as Level 3, DVCC can be between 2.4V and 3.6V to support a maximum MCLK frequency of 25MHz. For more information, see page 59 in the Datasheet and Figure 2-1 in the User's Guide.

    Dhara Pandya said:
    Is it possible to get in PMM ISR at the voltage drop of 2.4V level..??

    Yes, this should be possible. Using the high side monitor, SVMH (not SVSH), I've been able to successfully enter the PMM ISR and turn off an LED when the VDCC supply voltage dropped to 2.7V (set by using SVSMHRRL = 5, see page 71 in the Datasheet). The PMM ISR is not entered during board startup. I'm using an external bench power supply.

    However, the code (see attached) only works when the MSP-FET debugger is connected. When the MSP-FET is disconnected and DVCC is adjusted to 2.7V, the PMM ISR is not entered. The debugger seems to introduce some debugging limitations.

    • Accessing the SYSSNIV register with the debugger may clear it (described in this E2E thread).
    • According to Section 2.2.9.3 Wake-up Times in Debug Mode in the User's Guide, when the TEST/SBWTCK pin is high (debugger connected), wake-up times from LPM2, LPM3, and LPM4 may be different compared to when TEST/SBWTCK is low (debugger disconnected).
    • Perhaps the TEST pin being high with the debugger connected doesn't allow the DCO to stop. I'm not using any LPMx modes in my code, so this shouldn't matter when the debugger is disconnected.

    I'm currently looking into why this behavior is different, and I'll let you know what I find.

    /* --COPYRIGHT--,BSD
     * Copyright (c) 2016, Texas Instruments Incorporated
     * All rights reserved.
     *
     * Redistribution and use in source and binary forms, with or without
     * modification, are permitted provided that the following conditions
     * are met:
     *
     * *  Redistributions of source code must retain the above copyright
     *    notice, this list of conditions and the following disclaimer.
     *
     * *  Redistributions in binary form must reproduce the above copyright
     *    notice, this list of conditions and the following disclaimer in the
     *    documentation and/or other materials provided with the distribution.
     *
     * *  Neither the name of Texas Instruments Incorporated nor the names of
     *    its contributors may be used to endorse or promote products derived
     *    from this software without specific prior written permission.
     *
     * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
     * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
     * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
     * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
     * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
     * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
     * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
     * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
     * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
     * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
     * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
     * --/COPYRIGHT--*/
    //****************************************************************************/
    //! The device is set to core level 3. The PMM_setVcore function
    //! also sets the SVS and SVM  (high & low side) modules as required for a
    //! core setting of 3.
    //!
    //!
    //!                MSP430F54xA
    //!             -----------------
    //!         /|\|                 |
    //!          | |                 |
    //!          --|RST              |
    //!            |            Vcore|--> Monitor voltage on Vcore pin
    //!            |             P1.0|-->LED
    //!
    //!
    //! This example uses the following peripherals and I/O signals.  You must
    //! review these and change as needed for your own board:
    //! - PMM peripheral
    //! - GPIO Port peripheral
    //!
    //! This example uses the following interrupt handlers.  To use this example
    //! in your own application you must add these interrupt handlers to your
    //! vector table.
    //! - NONE.
    //****************************************************************************/
    
    #include "driverlib.h"
    
    uint16_t status = STATUS_SUCCESS;
    
    void UCS_config(void);
    void PMM_config(void);
    
    void main(void)
    {
        //Stop WDT
        WDT_A_hold(WDT_A_BASE);
    
        //Change VCore to Level 3, this function takes care of the incremental steps
        status = PMM_setVCore(PMMCOREV_3);
    
    	//Setup UCS
        UCS_config();
    
        //Configure PMM SVM to detect drop in DVCC
        PMM_config();
    
        // Set P1.0 (LED) to output direction
        P1OUT |= 0x01;
    
        //Turn on the LED
        P1DIR |= 0x01;
    
        //Continuous loop
        while(1)
        {
            //Delay
            //__delay_cycles(500000);
        }
    }
    
    void PMM_config(void)
    {
    	uint16_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
    
    	//Check VCore level
    	switch(PMMCTL0&PMMCOREV_3)
    	{
    
    	//Settings for highest VCore voltage
    	case PMMCOREV_3:
    		//The code flow for increasing the Vcore has been altered to work around
    		//the erratum FLASH37.
    		//Please refer to the Errata sheet to know if a specific device is affected
    		//DO NOT ALTER THIS FUNCTION
    
    		//Open PMM registers for write access
    		HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0xA5;
    
    		//Backup original register settings and disable interrupts
    		PMMRIE_backup = HWREG16(PMM_BASE + OFS_PMMRIE);
    		HWREG16(PMM_BASE + OFS_PMMRIE) &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
    											SVSLPE | SVMHVLRIE | SVMHIE |
    											SVSMHDLYIE | SVMLVLRIE | SVMLIE |
    											SVSMLDLYIE
    											);
    		SVSMHCTL_backup = HWREG16(PMM_BASE + OFS_SVSMHCTL);
    		SVSMLCTL_backup = HWREG16(PMM_BASE + OFS_SVSMLCTL);
    
    		//Clear interrupt flags
    		HWREG16(PMM_BASE + OFS_PMMIFG) = 0;
    
    		//Set SVM highside to new level based on VCore, SVSMRRL_5 = 2.7V (typ)
    		//See page 71 in the MSP430F6779 Datasheet for more information
    		HWREG16(PMM_BASE + OFS_SVSMHCTL) = SVMHE | SVSHE | SVSMHRRL_5;
    
    		//Wait until SVM highside is settled
    		while((HWREG16(PMM_BASE + OFS_PMMIFG) & SVSMHDLYIFG) == 0)
    		{
    			;
    		}
    
    		//Clear all Flags
    		HWREG16(PMM_BASE + OFS_PMMIFG) &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
    											SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
    											);
    
    		//Restore PMM interrupt enable register and enable the SVM high side interrupt
    		HWREG16(PMM_BASE + OFS_PMMRIE) = PMMRIE_backup | SVMHIE;
    
    		//Lock PMM registers for write access
    		HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0x00;
    
    	 break;
    	}
    }
    
    void UCS_config(void)
    {
    	UCSCTL0 = UCSCTL0 | 0x1F00;
    	UCSCTL1 = UCSCTL1 & 0x0000;
    	UCSCTL1 = UCSCTL1 | 0x0040;
    	UCSCTL2 = UCSCTL2 & 0x0000 ; //FLL Divider
    	UCSCTL2 = UCSCTL2 | 0x304F ; //for 20 MHz MCLK and 2.6 MHz SMCLK
    	UCSCTL3 = 0x0000;
    	UCSCTL4 = UCSCTL4 & 0X0000;
    	UCSCTL4 = UCSCTL4 | 0X0043;
    }
    
    #pragma vector = SYSNMI_VECTOR
    __interrupt void SYSNMI_ISR(void)
    {
    	switch(SYSSNIV)
      	{
    
      	//Open PMM registers for write access
      	//HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0xA5;
    
    	/*//core supply voltage monitor interrupt
    	case SYSSNIV_SVMLIFG:
    		//event to report error
    		//set flag
    	break;*/
    
    	//input supply voltage monitor interrupt
    	case SYSSNIV_SVMHIFG:
    		//event to report error
    
    		//Turn on LED on target development board
    		//P1DIR |= 0x01;
    
    		//Turn off LED on target development board
    		P1DIR &= ~(0x01);
    
    	break;
    
    	/*//core supply voltage monitor delay interrupt
    	case SYSSNIV_DLYLIFG:
    	break;
    
    	//interrupt supply voltage monitor delay interrupt
    	case SYSSNIV_DLYHIFG:
    	break;
    
    	//Vacant memory access interrupt
    	case SYSSNIV_VMAIFG:
    	break;
    
    	//JTAG mailbox in interrupt
    	case SYSSNIV_JMBINIFG:
    	break;
    
    	//JTAG mailbox out interrupt
    	case SYSSNIV_JMBOUTIFG:
    	break;
    
    	//SVMLVLRIFGSVMHVLRIFG
    	case SYSSNIV_VLRLIFG:
    		//clear interrupt flag bits
    		//unlock PMM
    		PMMCTL0_H=PMMPW_H;
    		//clear interrupt flags
    		PMMIFG&=~(SVMLIFG|SVMLVLRIFG);
    		//lock PMM
    		PMMCTL0_H=0;
    	break;
    
    	//SVMHVLRIFGSVMHVLRIFG
    	case SYSSNIV_VLRHIFG:
    		//clear interrupt flag bits
    		//unlock PMM
    		PMMCTL0_H=PMMPW_H;
    		//clear interrupt flags
    		PMMIFG&=~(SVMHIFG|SVMHVLRIFG);
    		//lock PMM
    		PMMCTL0_H=0;
    	break;*/
    
    	//Lock PMM registers for write access
    	HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0x00;
      	}
    }
    

    Regards,

    James

    MSP Customer Applications

  • Hi Dhara,

    I apologize for the delayed response. I've gotten my code to successfully detect a drop in supply voltage using SVMH.

    In my code (see below), an LED is blinked when DVCC reaches 2.7V or below. Otherwise, the LED stays lit. Next, I'll walk through how the code works.

    When the board is powered-up initially, DVCC is set to 3.0V. Then, using the external bench power supply, I lower DVCC to 2.7V (or slightly below, but above the 2.4V limit). When SVMHIFG is triggered high (level specified by SVSMHRRL), the ISR is entered and a flag is manually set. This flag tells main() to start blinking the LED. For your design, you could use this flag to prepare for power failure. Please note that SVMHIE is disabled when the interrupt vector SYSSNIV is read in the ISR, as mentioned in Table 2-22 in the User's Guide. Before I realized this, my code would only detect the first drop in supply voltage. As you can see in Figure 2-5, the disabled SVMHIE was preventing the SVMH interrupt from occurring, which prevented the ISR from being entered! SVMHIE will be re-enabled later.

    Next, I increase DVCC from 2.7V back up to 3.0V. This triggers SVMHVLRIFG and the ISR is re-entered. Here, the PMM registers are opened for write access, SVMHIFG and SVMHVLRIFG are cleared, SVMHIE and SVMHVLRIE are re-enabled, the PMM register are closed, and a flag is manually set to show that SVMH has been reset. Now, the LED quits blinking and just stays lit. This behavior can be repeated consistently.

    Also, this code works with or without the MSP-FET connected. Please let me know if you have any questions and I hope this helps get you started.

    #include "driverlib.h"
    
    uint16_t status = STATUS_SUCCESS;
    static volatile int isr_was_entered = 0;
    
    void UCS_config(void);
    void PMM_config(void);
    
    void main(void) {
    	//Stop WDT
        WDT_A_hold(WDT_A_BASE);
    
        //Change VCore to Level 3, this function takes care of the incremental steps
        status = PMM_setVCore(PMMCOREV_3);
    
        //Setup UCS
        UCS_config();
    
        //Configure PMM SVMH to detect drop in DVCC, SVMH triggered at 2.7V
        PMM_config();
    
        //Set P1.0 (LED) to output direction
        P1DIR |= 0x01;
    
        while(1) {
    
        	//If SVMH was triggered at 2.7V, start blinking LED
        	if(isr_was_entered == 4) {
    
        		//Toggle the LED
        		P1OUT ^= 0x01;
        		__delay_cycles(800000);
        	}
    
        	//If not, just keep LED on
        	else {
    
        		//Turn on the LED when DVCC is above SVMH
        		P1OUT |= 0x01;
        	}
        }
    }
    
    void UCS_config(void) {
    
    	UCSCTL0 = UCSCTL0 | 0x1F00;
    	UCSCTL1 = UCSCTL1 & 0x0000;
    	UCSCTL1 = UCSCTL1 | 0x0040;
    	UCSCTL2 = UCSCTL2 & 0x0000 ; //FLL Divider
    	UCSCTL2 = UCSCTL2 | 0x304F ; //for 20 MHz MCLK and 2.6 MHz SMCLK
    	UCSCTL3 = 0x0000;
    	UCSCTL4 = UCSCTL4 & 0X0000;
    	UCSCTL4 = UCSCTL4 | 0X0043;
    }
    
    void PMM_config(void) {
    	uint16_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
    
    	//Check VCore level
    	switch(PMMCTL0&PMMCOREV_3) {
    
    		//Settings for highest VCore voltage
    		case PMMCOREV_3:
    
    			//The code flow for increasing the Vcore has been altered to work around
    			//the erratum FLASH37.
    			//Please refer to the Errata sheet to know if a specific device is affected
    			//DO NOT ALTER THIS FUNCTION
    
    			//Open PMM registers for write access
    			HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0xA5;
    
    			//Backup original register settings and disable interrupts
    			PMMRIE_backup = HWREG16(PMM_BASE + OFS_PMMRIE);
    			HWREG16(PMM_BASE + OFS_PMMRIE) &= ~(SVMHVLRPE | SVSHPE | SVMLVLRPE |
    												SVSLPE | SVMHVLRIE | SVMHIE |
    												SVSMHDLYIE | SVMLVLRIE | SVMLIE |
    												SVSMLDLYIE
    												);
    			SVSMHCTL_backup = HWREG16(PMM_BASE + OFS_SVSMHCTL);
    			SVSMLCTL_backup = HWREG16(PMM_BASE + OFS_SVSMLCTL);
    
    			//Clear interrupt flags
    			HWREG16(PMM_BASE + OFS_PMMIFG) = 0;
    
    			//Set SVM highside to new level based on VCore, SVSMRRL_5 = 2.7V (typ)
    			//See page 71 in the MSP430F6779 Datasheet for more information
    			//HWREG16(PMM_BASE + OFS_SVSMHCTL) = SVMHE | SVSHE | SVSMHRRL_5;
    			HWREG16(PMM_BASE + OFS_SVSMHCTL) = SVMHE | SVSMHRRL_5;
    
    			//Wait until SVM highside is settled
    			while((HWREG16(PMM_BASE + OFS_PMMIFG) & SVSMHDLYIFG) == 0) {
    				;
    			}
    
    			//Clear all Flags
    			HWREG16(PMM_BASE + OFS_PMMIFG) &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG |
    												SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG
    												);
    
    			//Restore PMM interrupt enable register and enable the SVM high side interrupts
    			HWREG16(PMM_BASE + OFS_PMMRIE) = PMMRIE_backup | SVMHVLRIE | SVMHIE;
    
    			//Lock PMM registers for write access
    			HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0x00;
    
    			break;
    	}
    }
    
    #pragma vector = SYSNMI_VECTOR
    __interrupt void SYSNMI_ISR(void) {
    
    	//Do something based on interrupt
    	switch(SYSSNIV) {
    
    		//core supply voltage monitor interrupt
    		case SYSSNIV_SVMLIFG:
    
    			//event to report error
    			//set flag
    
    		break;
    
    		//input supply voltage monitor interrupt
    		case SYSSNIV_SVMHIFG:
    			//write_SegC();
    			//Clear_SegC(value);		// For testing only
    
    			//Set the flag to show SVMH has been triggered
    			isr_was_entered = 4;
    
    			//event to report error
    			//set flag
    		break;
    
    		//core supply voltage monitor delay interrupt
    		case SYSSNIV_DLYLIFG:
    
    		break;
    
    		//interrupt supply voltage monitor delay interrupt
    		case SYSSNIV_DLYHIFG:
    
    		break;
    
    		//Vacant memory access interrupt
    		case SYSSNIV_VMAIFG:
    
    		break;
    
    		//JTAG mailbox in interrupt
    		case SYSSNIV_JMBINIFG:
    
    		break;
    
    		//JTAG mailbox out interrupt
    		case SYSSNIV_JMBOUTIFG:
    
    		break;
    
    		//SVMLVLRIFG
    		case SYSSNIV_VLRLIFG:
    
    		break;
    
    		//SVMHVLRIFG
    		case SYSSNIV_VLRHIFG:
    
    			//Open PMM registers for write access
    			HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0xA5;
    
    			//clear SVMH interrupt flags
    			HWREG16(PMM_BASE + OFS_PMMIFG) &= ~(SVMHIFG | SVMHVLRIFG);
    
    			//re-enable SVMH interrupt flags (must be done after clearing interrupt)
    			HWREG16(PMM_BASE + OFS_PMMRIE) |= SVMHIE | SVMHVLRIE;
    
    			//Lock PMM registers for write access
    			HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0x00;
    
    			//Set the flag to show SVMH has been reset
    			isr_was_entered = 3;
    
    		break;
      	}
    }
    

    Regards,

    James

    MSP Customer Applications

  • Hello ,

    Thats totally fine... Thanks alot for your constant help.. I will check out your suggestion at my end...

    Also, I want to ask one more thing.. How can we calculate KW..?? Right now I am taking instantaneous current and voltage and multiplying them.. do i need to find phase of V & I (cos (phi) / power factor for KW)..??

    Thanks..

    Regards..


    Dhara
  • Hi Dhara,

    Dhara Pandya said:
    Thats totally fine... Thanks alot for your constant help.. I will check out your suggestion at my end...

    Sounds good!

    Dhara Pandya said:
    Also, I want to ask one more thing.. How can we calculate KW..?? Right now I am taking instantaneous current and voltage and multiplying them.. do i need to find phase of V & I (cos (phi) / power factor for KW)..??

    To get started, I'd recommend taking a look at the following two resources. They discuss key parameters that need to be calculated during energy measurement.

    If you haven't already, I'd also recommend taking a look at the MSP430 Energy Library features. Some featured outputs include reactive, active, and apparent energy and power. If you have any further questions about the Energy Library, I'd recommend opening a new thread to maximize visibility to the community and our experts.

    Regards,

    James

    MSP Customer Applications

  • Hi Dhara,

    Have you been able to check out my SVMH example code yet?

    Regards,

    James
    MSP Customer Applications
  • Hi Dhara,

    I'm closing this thread, but please feel free to reply back if you have further questions about this topic. For questions about other topics, I'd recommend opening a new thread.

    Regards,

    James
    MSP Customer Applications

**Attention** This is a public forum