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.

Library for setting the PMM (hal_pmm.* files) Power Management Module

Other Parts Discussed in Thread: MSP430F5438A

Hi everyone,

I'm working with the MSP430F5438A. I have the following issue: When i'm using the attached Libary, the device resets every time I'm switching the Vcore-Level from a higher one to a lower one.  So i compared the Library with the User guide. Thus i found following difference.

 

TI provides the "hal_pmm library" for users of this device.In this files the Funciton "SetVCoreDown" shifts the SVS highside and SVS lowside after setting Vcore.

But in the  MSP430x5xx Family User Guide (page 69):

Steps 5 through 6 show the procedure to decrease VCORE:
• Step 5: Program the SVML and SVSL to the new level and wait for (SVSMLDLYIFG) to be set.
• Step 6: Program PMMCOREV to the new VCORE level. Wait for the voltage level reached
(SVMLVLRIFG) interrupt.

 

Logically the user guide should be the right way. Or am i wrong? But if I implement the User Guide procedure, a reset occures also.

Is anyone aware of this or have any ideas? Thanks in advance!

 

Attachment SetVCoreDown - Funktion:

//****************************************************************************//
// Function Library for setting the PMM
//    File: hal_pmm.c
//
//    Texas Instruments
//
//    Version 1.2
//    11/24/09
//
//    V1.0  Initial Version
//    V1.1  Adjustment to UG
//    V1.2  Added return values
//****************************************************************************////====================================================================

#include "msp430.h"
#include "hal_pmm.h"

#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 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
}

  • Christian,

    what is the exact part number and revision of your MSP430F5438A? Is it an XMS430... or MSP430... device? What specific revision? It seems like that the issues could be caused by the power-on default value for the PMMRIE register. Could you try the following modification to see if this helps? 

    //****************************************************************************//

    // Set VCore down (Independent from the enabled Interrupts in PMMRIE)

    //****************************************************************************//

    static uint16_t SetVCoreDown (uint8_t level)

    {

      uint16_t 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 | SVSHPE | SVSLPE);

     

    Thanks and Regards,
    Andreas

     

  • Thanks a lot,

     

    your suggestion fixed the problem. The revision is: Rev. C and the part number is 02C0ZZTG4 (if it is the first row on the MSP430F5438A chip).

    Furthermore was the code generally wrong? Or only for this device?

     

    Thanks and best regards

    Christian

  • Hi Christian,

    I've since done some more research on this and it turns out that what you have encountered is an issue with the actual library. It incorrectly assumes those two bits to be cleared which is OK for some of the earlier prototype devices but not for official production-qualified MSP430F5438A silicon. Will push out an update of the official SLAA448 code.

    Regards,
    Andreas

  • Hi,

    I'm working with EM430F6137RF900 and i have a similar problem. In the samy library i had an infinite loop in this line

     

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

     

    I already changed my code like Andreas wrote, but it still not working, any solution??? I'm following SLAA465 Application Report

    Thanks,

    Víctor

  • SVSMHDLYIFG is set at the moment of delay expiration. It is not set or cleared by the delay status. So if the delay is not started, the IFG won't be set anew. It is cleared by readign the IV register or by manually clearing the bit.
    It is clear after a reset and if you son't do any change to the PMM configuration that causes the delay to start, it won't be set ever. This may happen if your new configuration is the same as it was before. This won't trigger the delay.

    If you don't require an interrupt for executing an ISR, you can check the SVSMHDLYST bit instead. It is set during the delay and reset once the delay expired (or is not running at all). So you can see the current status of the delay here. Note that you have to invert your while logic for this bit.

**Attention** This is a public forum