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.

MSP430BT5190: MSP430 crash

Part Number: MSP430BT5190

Hi all.

this issue is random, I do not know the reason.

the mcu erase internal flash, it has a very low probability of crash.

please refer my code.

erase_NumberOfBank(0x10000,3);

P.S. code memory address 0x10000h - 03FFFFh unused.

void erase_NumberOfBank(unsigned long int start_address,unsigned char numberofbank)
{
  unsigned long int *Flash_Ptr; // Flash pointer
  unsigned int j;
  // __disable_interrupt(); // 5xx Workaround: Disable global
  // interrupt while erasing. Re-Enable
  // GIE if needed
  for (j=0;j<numberofbank;j++)
  {
    Flash_Ptr = (unsigned long int *)(start_address + 0x10000*j); // Initialize Flash pointer
    //while(BUSY & FCTL3); // Check if Flash being used
    FCTL3 = FWKEY; // Clear Lock bit
    FCTL1 = FWKEY + MERAS; // Set Erase bit
    *Flash_Ptr = 0; // Dummy write to erase Flash segment
    //while(BUSY & FCTL3); // Check if Erase is done
    FCTL1 = FWKEY; // Clear Erase bit
    FCTL3 = FWKEY + LOCK; // Reset LOCK bit 
    while(BUSY & FCTL3); // Check if Erase is done
  }
  // __enable_interrupt();
}

Thank you

  • Hi Dunk,

    To better understand what you're trying to accomplish and the issue you're experiencing, I'll need more information about your system.

    The code you've posted above is setup to erase the three memory banks B, C, and D starting at addresses 0x10000, 0x20000, and 0x30000 respectively. Is this correct?

    What do you mean by:

    Dunk Wu said:
    the mcu erase internal flash, it has a very low probability of crash.

    1. Does this mean the MCU is resetting when it enters the flash erase routine you've posted?
    2. Can you verify the capacitance present on the DVCC and VCORE pins of the device?
    3. What is your system frequency?
    4. Have you verified you're not violating the system frequency vs supply voltage spec?

    Best regards, 
    Caleb Overbay

  • Hi Sir,

    thank you for your reply.

    I have an application that store the backup code in three memory banks B, C, and D. And the backup code is regularly updated.

    The following reply to your inquiry.

    The code you've posted above is setup to erase the three memory banks B, C, and D starting at addresses 0x10000, 0x20000, and 0x30000 respectively. Is this correct?
    RE: Yes.

    1. Does this mean the MCU is resetting when it enters the flash erase routine you've posted?
      RE: Yes. the MCU is resetting or program counter to unknown address.
    2. Can you verify the capacitance present on the DVCC and VCORE pins of the device?
      RE: Please refer to the attached file. (msp430bt5190.jpg)
    3. What is your system frequency?
      RE: 24Mhz
    4. Have you verified you're not violating the system frequency vs supply voltage spec?
      RE: Yes, please confirm the attached file. DVCC 3.28v (system frequency initial.jpg)

    Thank you

  • Hi Dunk,

    In the above post it looks like you highlighted that you are operating the device at VCORE level 3. Can you provide the code that you use to switch to this core level?

    Best regards,
    Caleb Overbay
  • Hi Sir,

    Please refer to the attached file. (main.c)

    thank you.

    1258.main.c
    #include <msp430.h>				
    
    #define PMM_STATUS_OK     0
    #define PMM_STATUS_ERROR  1
    
    #define _HAL_PMM_DISABLE_SVML_
    #define _HAL_PMM_DISABLE_SVSL_
    #define _HAL_PMM_DISABLE_FULL_PERFORMANCE_
    
    #ifdef _HAL_PMM_DISABLE_SVML_
    #define _HAL_PMM_SVMLE SVMLE
    #else
    #define _HAL_PMM_SVMLE 0
    #endif
    #ifdef _HAL_PMM_DISABLE_SVSL_
    #define _HAL_PMM_SVSLE SVSLE
    #else
    #define _HAL_PMM_SVSLE 0
    #endif
    #ifdef _HAL_PMM_DISABLE_FULL_PERFORMANCE_
    #define _HAL_PMM_SVSFP SVSLFP
    #else
    #define _HAL_PMM_SVSFP 0
    #endif
    
    //====================================================================
    /**
      * Set the VCore to a new level if it is possible and return a
      * error - value.
      *
      * \param      level       PMM level ID
      * \return int     1: error / 0: done
      */
    unsigned int SetVCore (unsigned char level);
    
    //====================================================================
    /**
      * Set the VCore to a higher level, if it is possible.
      * Return a 1 if voltage at highside (Vcc) is to low
      * for the selected Level (level).
      *
      * \param      level       PMM level ID
      * \return int     1: error / 0: done
      */
    extern unsigned int SetVCoreUp (unsigned char level);
    
    //====================================================================
    /**
      * Set the VCore to a lower level.
      * Return a 1 if voltage at highside (Vcc) is still to low
      * for the selected Level (level).
      *
      * \param      level       PMM level ID
      * \return int     1: done with error / 0: done without error
      */
    extern unsigned int SetVCoreDown (unsigned char level);
    
    extern void System_initial(void);
    
    void main(void)
    {
    	WDTCTL = WDTPW | WDTHOLD;		// stop watchdog timer
    	P11DIR |= 0x07;
    	P11SEL |= 0x07;                 // configure P11.x as ACLK, SMCLK, MCLK
    	P1DIR |= 0x01;					// configure P1.0 as output
    
    	volatile unsigned int i;		// volatile to prevent optimization
    
        	while(SetVCore(3));
       	System_initial();
    
    	while(1)
    	{
    		P1OUT ^= 0x01;				// toggle P1.0
    		for(i=10000; i>0; i--);     // delay
    	}
    }
    
    //****************************************************************************//
    // Set VCore
    //****************************************************************************//
    unsigned int SetVCore (unsigned char level)
    {
      unsigned int actlevel;
      unsigned int status = 0;
      level &= PMMCOREV_3;                       // Set Mask for Max. level
      actlevel = (PMMCTL0 & PMMCOREV_3);         // Get actual VCore
    
      while (((level != actlevel) && (status == 0)) || (level < actlevel))      // step by step increase or decrease
      {
        if (level > actlevel)
          status = SetVCoreUp(++actlevel);
        else
          status = SetVCoreDown(--actlevel);
      }
      return status;
    }
    
    //****************************************************************************//
    // Set VCore Up
    //****************************************************************************//
    unsigned int SetVCoreUp (unsigned char level)
    {
      unsigned int PMMRIE_backup,SVSMHCTL_backup;
    
      // Open PMM registers for write access
      PMMCTL0_H = 0xA5;
    
      // Disable dedicated Interrupts to prevent that needed flags will be cleared
      PMMRIE_backup = PMMRIE;
      PMMRIE &= ~(SVSMHDLYIE | SVSMLDLYIE | SVMLVLRIE | SVMHVLRIE | SVMHVLRPE);
      // Set SVM highside to new level and check if a VCore increase is possible
      SVSMHCTL_backup = SVSMHCTL;
      PMMIFG &= ~(SVMHIFG | SVSMHDLYIFG);
      SVSMHCTL = SVMHE | SVMHFP | (SVSMHRRL0 * level);
      // Wait until SVM highside is settled
      while ((PMMIFG & SVSMHDLYIFG) == 0);
      // Disable full-performance mode to save energy
      SVSMHCTL &= ~_HAL_PMM_SVSFP ;
      // Check if a VCore increase is possible
      if ((PMMIFG & SVMHIFG) == SVMHIFG){           //-> Vcc is to 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);
        // backup PMM-Interrupt-Register
        PMMRIE = PMMRIE_backup;
    
        // Lock PMM registers for write access
        PMMCTL0_H = 0x00;
        return PMM_STATUS_ERROR;                       // return: voltage not set
      }
      // Set also SVS highside to new level         //-> Vcc is high enough for a Vcore increase
      SVSMHCTL |= SVSHE | (SVSHRVL0 * level);
      // Set SVM low side to new level
      SVSMLCTL = SVMLE | SVMLFP | (SVSMLRRL0 * level);
      // Wait until SVM low side is settled
      while ((PMMIFG & SVSMLDLYIFG) == 0);
      // Clear already set flags
      PMMIFG &= ~(SVMLVLRIFG | SVMLIFG);
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
      // Wait until new level reached
      if (PMMIFG & SVMLIFG)
      while ((PMMIFG & SVMLVLRIFG) == 0);
      // Set also SVS/SVM low side to new level
      PMMIFG &= ~SVSMLDLYIFG;
      SVSMLCTL |= SVSLE | (SVSLRVL0 * level);
      // wait for lowside delay flags
      while ((PMMIFG & SVSMLDLYIFG) == 0);
    
    // Disable SVS/SVM Low
    // Disable full-performance mode to save energy
      SVSMLCTL &= ~(_HAL_PMM_DISABLE_SVSL_+_HAL_PMM_DISABLE_SVML_+_HAL_PMM_SVSFP );
    
      // Clear all Flags
      PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
      // backup PMM-Interrupt-Register
      PMMRIE = PMMRIE_backup;
    
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
      return PMM_STATUS_OK;                               // return: OK
    }
    
    //****************************************************************************//
    // Set VCore down (Independent from the enabled Interrupts in PMMRIE)
    //****************************************************************************//
    unsigned int SetVCoreDown (unsigned char level)
    {
      unsigned int PMMRIE_backup;
    
      // Open PMM registers for write access
      PMMCTL0_H = 0xA5;
    
      // Disable dedicated Interrupts to prevent that needed flags will be cleared
      PMMRIE_backup = PMMRIE;
      PMMRIE &= ~(SVSMHDLYIE | SVSMLDLYIE | SVMLVLRIE | SVMHVLRIE | SVMHVLRPE);
    
      // Set SVM high side and SVM low side to new level
      PMMIFG &= ~(SVMHIFG | SVSMHDLYIFG | SVMLIFG | SVSMLDLYIFG);
      SVSMHCTL = SVMHE | SVMHFP | (SVSMHRRL0 * level);
      SVSMLCTL = SVMLE | SVMLFP | (SVSMLRRL0 * level);
      // Wait until SVM high side and SVM low side is settled
      while ((PMMIFG & SVSMHDLYIFG) == 0 || (PMMIFG & SVSMLDLYIFG) == 0);
    
      // Set VCore to new level
      PMMCTL0_L = PMMCOREV0 * level;
    
      // Set also SVS highside and SVS low side to new level
      PMMIFG &= ~(SVSHIFG | SVSMHDLYIFG | SVSLIFG | SVSMLDLYIFG);
      SVSMHCTL |= SVSHE | SVSHFP | (SVSHRVL0 * level);
      SVSMLCTL |= SVSLE | SVSLFP | (SVSLRVL0 * level);
      // Wait until SVS high side and SVS low side is settled
      while ((PMMIFG & SVSMHDLYIFG) == 0 || (PMMIFG & SVSMLDLYIFG) == 0);
      // Disable full-performance mode to save energy
      SVSMHCTL &= ~_HAL_PMM_SVSFP;
    // Disable SVS/SVM Low
    // Disable full-performance mode to save energy
      SVSMLCTL &= ~(_HAL_PMM_DISABLE_SVSL_+_HAL_PMM_DISABLE_SVML_+_HAL_PMM_SVSFP );
    
      // Clear all Flags
      PMMIFG &= ~(SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG);
      // backup PMM-Interrupt-Register
      PMMRIE = PMMRIE_backup;
      // Lock PMM registers for write access
      PMMCTL0_H = 0x00;
    
      if ((PMMIFG & SVMHIFG) == SVMHIFG)
        return PMM_STATUS_ERROR;                        // Highside is still to low for the adjusted VCore Level
      else return PMM_STATUS_OK;                        // Return: OK
    }
    
    void System_initial(void)
    {
      UCSCTL3 |= SELREF_2;                      // Set DCO FLL reference = REFO
      UCSCTL4 = SELA__REFOCLK | SELS__DCOCLK | SELM__DCOCLK;
    
      __bis_SR_register(SCG0);                  // Disable the FLL control loop
      UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
      UCSCTL1 = DCORSEL_5;                      // Select DCO range 24MHz operation
      UCSCTL2 = FLLD_1 + 366;                   // Set DCO Multiplier for 24MHz
                                                // (N + 1) * FLLRef = Fdco
                                                // (374 + 1) * 32768 = 12MHz
                                                // Set FLL Div = fDCOCLK/2
      __bic_SR_register(SCG0);                  // Enable the FLL control loop
    
      // Worst-case settling time for the DCO when the DCO range bits have been
      // changed is n x 32 x 32 x f_MCLK / f_FLL_reference. See UCS chapter in 5xx
      // UG for optimization.
      // 32 x 32 x 12 MHz / 32,768 Hz = 375000 = MCLK cycles for DCO to settle
      __delay_cycles(375000);
    
      // Loop until XT1,XT2 & DCO fault flag is cleared
      do
      {
        UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + XT1HFOFFG + DCOFFG);
                                                // Clear XT2,XT1,DCO fault flags
        SFRIFG1 &= ~OFIFG;                      // Clear fault flags
      }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag
    
    }
    

  • Hi Dunk,

    I believe that you are incorrectly setting VCore to level 3 and the core isn't receiving the necessary voltage for 24 MHz operation. When not programming flash, your code seems to run well. When the flash programming begins, the flash module requires a significant amount current. This extra current draw causes the voltage on VCore to drop out of spec and the device resets.

    I see you have the SetVCoreUp and SetVcoreDown methods in your code but you're not using them. There is a very specific order of operations that need to occur in order to properly change the VCore settings and your code isn't following them. Section 2.2.4 of the MSP430x5xx and MSP430x6xx Family User's Guide describes how to properly increase Vcore for higher MCLK frequencies. Also, if you copied the SetVCoreUp and SetVcoreDown methods from TI example code, I recommend using those to change the VCore settings. You should also keep in mind that if VCore needs to be changed from level 1 to level 3 you need to step incrementally to that level. For example, setting to VCore to level 1, then to level 2, and finally, level 3.

    Best regards,

    Caleb Overbay

  • Hi Caleb,

    thank you for your suggestion.

    I will follow your suggestions to redesign, if there has any questions, i will reply to you here,

    thank you