Part Number: MSP430F5438A
Hello!
We use the MSP430 to perform house keeping functions for our custom device. The MSP430 communicates with an external processor using SPI and receives code upgrade. We use the DCO as MCLK at ~22MHz, to support this, we step Vcore to level 3.
We've always disabled the SVSM for both high side and lowside(DVcc and Vcore ) to save power and we've noticed the MSP would occasionally hang. Interrupts doesn't work in this state. We also enabled the watchdog timer but it also wouldn't reset. This has been hard to replicate but we think it could happen in two ways:
- We speculate that when the WDT issues a PUC, it could hang the MSP as mentioned here : https://e2e.ti.com/support/microcontrollers/msp-low-power-microcontrollers-group/msp430/f/msp-low-power-microcontroller-forum/353287/msp430-hangs-up-even-when-wdt-timer-is-enabled. We currently don't have a handler for NMI/SNMI so not sure if OFIFG is happening. We're thinking of using the WDT as a timer and issue a soft BOR in the WDT interrupt handler, this way it won't issue PUCs. Would this work around prevent WDT from hanging the MSP and is it safe?
- We may have MSP supply voltage drops, although without confirmation. Since we disable the SVSMs, we have no protection so I assume the MSP could hang if supply is unstable. Enabling the SVSMs cause a bunch of unexpected issues:
- If we enable the SVSM low side, it breaks the SPI communication. I thought this was because of a SVSM triggered POR/NMI so I set the entire register of PMMRIE to 0 and this still happens. Why would low side SVSM affect UCAx? Communication is fine if I connect the debugger, suggesting there's a supply issue. When I probed the external Vcore pin, I saw a steady 1.92V(level 3) when communication is failing, regardless of whether I have the debugger connected. Why would SVSM low side do anything if Vcore is stable?
- If we enable the SVSM high side, it breaks the MSP upgrade(through SPI comm, lots of flash writes). Again, I don't believe it's caused by a SVSM triggered POR/NMI since I set PMMRIE to 0. Why would high side SVSM affect UCAx? If I perform an upgrade while the debugger is connected, it works fine. I probed DVcc during an upgrade and I saw a steady 3.3V, regardless of whether I have the debugger connected. Why would SVSM high side do anything if DVcc is stable?
I've provided relevant code snippet below, this is essentially the same code as the MSPWARE PMM driver lib.
/// sets the PMM core to a specific voltage
/// @param[in] level the voltage level to set
/// @return success of the call
bool SystemClock::configVCore(uint16_t level)
{
uint16_t actual;
bool status = true;
// set mask for maximum level
level &= PMMCOREV_3;
// get actual
actual = (PMMCTL0 & PMMCOREV_3);
// increase or decrease step-by-step
while (((level != actual) && status) || (level < actual))
{
if (level > actual)
status = incVCore(++actual);
else
status = decVCore(--actual);
}
return true;
}
/// increments the vcore to a specified value
/// @param[in] level the level to set the vcore to
/// @return success of the call
bool SystemClock::incVCore(uint16_t level)
{
uint16_t PMMRIE_backup, SVSMHCTL_backup, SVSMLCTL_backup;
bool ret = true;
// the code flow for increasing the vcore has been altered to work
// around the erratum FLASH37.
// open PMM registers for write access
PMMCTL0_H = 0xA5;
// disable dedicated interrupts and backup all registers
PMMRIE_backup = U16(PMMRIE);
PMMRIE &= N16((SVMHVLRPE | SVSHPE | SVMLVLRPE | SVSLPE | SVMHVLRIE | SVMHIE | SVSMHDLYIE | SVMLVLRIE | SVMLIE | SVSMLDLYIE));
SVSMHCTL_backup = U16(SVSMHCTL);
SVSMLCTL_backup = U16(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
safeWait(&PMMIFG, SVSMHDLYIFG, false);
// clear flag
PMMIFG &= N16(SVSMHDLYIFG);
// check if a vcore increase is possible
if ((PMMIFG & SVMHIFG) == SVMHIFG)
{
// vcc is too low for a vcore increase so we will recover the previous settings
PMMIFG &= N16(SVSMHDLYIFG);
SVSMHCTL = SVSMHCTL_backup;
// wait until SVM highside is settled
safeWait(&PMMIFG, SVSMHDLYIFG, false);
ret = false;
}
else
{
// set also SVS highside to new level Vcc is high enough for a vcore increase
SVSMHCTL |= (SVSHRVL0 * level);
// wait until SVM highside is settled
safeWait(&PMMIFG, SVSMHDLYIFG, false);
// clear flags
PMMIFG &= N16(SVSMHDLYIFG);
// set vcore to new level
PMMCTL0_L = U8((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
safeWait(&PMMIFG, SVSMLDLYIFG, false);
// clear flag
PMMIFG &= N16(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 &= N16((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 &= N16((SVSHRVL0 | SVSHRVL1 | SVSMHRRL0 | SVSMHRRL1 | SVSMHRRL2));
// restore backup
SVSMHCTL |= SVSMHCTL_backup;
// wait until high/low side settled
safeWait(&PMMIFG, SVSMHDLYIFG, false);
safeWait(&PMMIFG, SVSMLDLYIFG, false);
}
// clear all flags
PMMIFG &= N16((SVMHVLRIFG | SVMHIFG | SVSMHDLYIFG | SVMLVLRIFG | SVMLIFG | SVSMLDLYIFG));
// restore PMM interrupt enable register
PMMRIE = PMMRIE_backup;
// disable SVSMs to prevent hanging during upgrade
//SVSMHCTL &= N16((SVMHE | SVSHE));
//SVSMLCTL &= N16((SVMLE | SVSLE));
// lock PMM registers for write access
PMMCTL0_H = 0x00;
return ret;
}
Any guidance would be greatly appreciated!
Thanks,
Tian


