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.
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