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.

Micro is resetting when UART interrupt occurs (sometimes)

Other Parts Discussed in Thread: MSP430F5342

I'm troubleshooting a group of boards that contain an MSP430F5342 micro on them. It appears that on some boards (not all), when a UART interrupt occurs, it's possible that the board resets (sometimes, not always).

I've distilled the source down to just enough to show the problem. I configure the clocks (external 32768 crystal), configure the UART, enable interrupts, and enable the receive interrupt for the UART. I then drop into an infinite loop - so, nothing is really happening except the UART interrupt should be triggered when a byte is received.

The receive interrupt just checks to see if UCRXIE and UCRXIFG are set, and if so, read the byte from UCA1RXBUF and discards it.

On some boards, I power them up, then send characters (slowly, by hand using a terminal program) to the UART. The micro will occasionally reset at the same instant a byte is received. On other boards, nothing happens - the byte is received properly.

I have an MSP-FET430UIF and CCS, and I've set a breakpoint on the very first line of my interrupt handler. After sending a character, if the micro resets, the breakpoint is never even hit. If the micro doesn't reset, the breakpoint is hit, and I can continue. I then repeat the process, and eventually get a reset.

Here is my code at the moment (not very clean, though, since it was distilled out from the "real" project):

#include <MSP430F5342.h>

/*lint -save -e957 -e970 */
#pragma CHECK_MISRA("none")
extern "C" int _system_pre_init(void)
{
	WDTCTL = WDTPW | WDTHOLD;
    return 1;
}
#pragma RESET_MISRA("all")
/*lint -restore */

typedef unsigned char uint8_t;
typedef unsigned long int uint32_t;

#define OSC_STABILIZE_WAIT_TIME (170000u)
#define OSC_STABILIZE_CHECK_TIME (5u)
#define OSC_STABILIZE_FAIL_BLINK_TIME (10000u)
#define CLOCK_CYCLES_PER_MICROSECOND    (24ul)
#define CLOCK_DELAY_US(x)               _delay_cycles(((uint32_t) (x)) * CLOCK_CYCLES_PER_MICROSECOND)

void configure_uart()
{
	UCA1CTL1 = UCSWRST; // reset uart
	UCA1CTL0 = 0; // no parity
    /* Select SMCLK as clock source,
       disable Rx error and Rx break interrupts,
       USCI module is not dormant,
       next frame is normal data,
       keep module in reset
    */
	UCA1CTL1 = UCSSEL__SMCLK | UCSWRST;
    /* Disable auto baud rate detection. */
	UCA1ABCTL = 0u;
	// Disable irda mode
	UCA1IRRCTL = 0u;
	UCA1IRTCTL = 0u;
	// set 115200 baud
	UCA1BRW = 11u;
	UCA1MCTL = (0u * UCBRF0) | UCOS16;
}

void open_uart()
{
    /* Reset module */
	UCA1CTL1 = UCA1CTL1 | UCSWRST;

	// Configure pins
	P4DS = P4DS & 0xcf; // drive strength default
	P4OUT = P4OUT & 0xcf; // Output low.
	P4OUT = P4OUT | 0x10; // Output high for the TX pin.
	P4DIR = P4DIR | 0x10; // P4.4 output
	P4DIR = P4DIR & ~(0x20); // P4.5 input
	P4SEL = P4SEL | 0x30; // Both are peripheral function.

	/* Release module from reset */
	UCA1CTL1 = UCA1CTL1 & ((uint8_t) ~(UCSWRST));
}

void enable_receive()
{
    /* Dummy read of receive register to flush any extra bytes received
       previously and to clear receive interrupt.
    */
    uint8_t junkByte = UCA1RXBUF;

    // enable rx interrupt
    UCA1IE = UCA1IE | UCRXIE;
}

void enable_oscillator()
{
	P5DS = P5DS & 0xcf; // Default drive strength on crystal pins.
	P5OUT = P5OUT & 0xcf; // Low or don't care.
	P5DIR = P5DIR | 0x20; // Output on P5.5.
	P5DIR = P5DIR & 0x70; // Input on P5.4.
	P5SEL = P5SEL | 0x30; // Both are peripheral function.
}

#pragma vector=USCI_A1_VECTOR
__interrupt void UartA1Isr_Steve(void)
{
    uint8_t interruptEnabledFlags = UCA1IE;
    uint8_t interruptFlags = UCA1IFG;

    if (((interruptEnabledFlags & UCRXIE) > 0u) && ((interruptFlags & UCRXIFG) > 0u))
    {
    	uint8_t junk_byte = UCA1RXBUF;
    }
    else
    {
    	P6DIR = P6DIR | 0x02; // Set P6.1 as an output.
    	P6SEL = P6SEL & 0xFD; // Select IO function for P6.1.
    	/* infinite loop, blink orange LED */
    	for(;;)
    	{
    		P6OUT = P6OUT | 0x02; // Set P6.1.
    		CLOCK_DELAY_US(100000);
    		P6OUT = P6OUT & 0xFD; // Clear P6.1.
    		CLOCK_DELAY_US(100000);
    		P6OUT = P6OUT | 0x02; // Set P6.1.
    		CLOCK_DELAY_US(100000);
    		P6OUT = P6OUT & 0xFD; // Clear P6.1.
    		CLOCK_DELAY_US(200000);
    	}
    }
}

void configure_clock()
{
	/* Turn off FLL.  Locks DCO at current frequency. */
	_bis_SR_register(SCG0);

	/* Crystal oscillator settings:
	   Turn off XT2.

	   Drive strength level 3 for XT1.
	   Low frequency mode for XT1.
	   No bypass for XT1.
	   Highest capacitance (about 12.0 pF) for XT1.

	   SMCLK on.
	   XT1 on.
	   */
	    UCSCTL6 = XT2OFF | XT1DRIVE_3 | XCAP_3;

	    /* Enable XT1 oscillator pins. */
	    enable_oscillator();

	    // Wait for the oscillator input to stabilize.
	    CLOCK_DELAY_US(OSC_STABILIZE_WAIT_TIME);
        /* Clear oscillator fault flag and wait. */
        UCSCTL7 &= ~(XT1LFOFFG);
        CLOCK_DELAY_US(OSC_STABILIZE_CHECK_TIME);

    	P6DIR = P6DIR | 0x02; // Set P6.1 as an output.
    	P6SEL = P6SEL & 0xFD; // Select IO function for P6.1.
        if ((UCSCTL7 & XT1LFOFFG) > 0u)
        {
            // If the oscillator hasn't stabilized by now, something must be very wrong.
            // Therefore we'll blink the standby light forever to let the operator know.
        	while (true)
        	{
        		P6OUT = P6OUT | 0x02; // Set P6.1.
        		CLOCK_DELAY_US(OSC_STABILIZE_FAIL_BLINK_TIME);
        		P6OUT = P6OUT & 0xFD; // Clear P6.1.
        		CLOCK_DELAY_US(OSC_STABILIZE_FAIL_BLINK_TIME);
        	}
        }
        else
        {
        	// If the clock did stabilize, blink the standby LED once and continue on.
    		P6OUT = P6OUT | 0x02; // Set P6.1.
    		CLOCK_DELAY_US(OSC_STABILIZE_FAIL_BLINK_TIME);
    		P6OUT = P6OUT & 0xFD; // Clear P6.1.
        }

	    /* Set DCO to correct range (2.5-23.7 MHz min, 6.0-54.1 MHx max)
	       and enable modulation.
	    */
	    UCSCTL1 = DCORSEL_5;

	    /* FLL settings:
	       FLL loop divider (D) = 2
	       FLL multiplier (N) = 610
	       Use XT1CLK as reference.
	       FLL reference divider (n) = 2

	       DCOCLK = D * (N+1) * ref / n
	       DCOCLKDIV = (N+1) * ref / n
	    */
	    UCSCTL2 = FLLD__2 | 610u;
	    UCSCTL3 = SELREF__XT1CLK | FLLREFDIV__2;

	    /* Clock source settings:
	       Ext ACLK = XT1CLK / 32
	       ACLK = XT1CLK / 1
	       SMCLK = DCOCLK / 1
	       MCLK = DCOCLK / 1
	    */
	    UCSCTL4 = SELA__XT1CLK | SELS__DCOCLK | SELM__DCOCLK;
	    UCSCTL5 = DIVPA__32 | DIVA__1 | DIVS__1 | DIVM__1;

	    /* Turn on FLL */
	    _bic_SR_register(SCG0);

	    /* Wait for FLL and DCO to stabilize (select the correct DCO tap
	       and modulator settings).  Settling time for the tap has a worst
	       case of (n * 32 * 32) FLLREFCLK cycles (n is defined above),
	       or about 31.25 ms.
	       (n * 32 * 32) FLLREFCLK cycles = (D * (N+1) * n * 32 * 32) DCOCLK cycles
	    */
	    /* Wait 626688 MCLK (DCOCLK) cycles */
	    _delay_cycles(208896ul);
	    //WATCHDOG_RESET();
	    _delay_cycles(208896ul);
	    //WATCHDOG_RESET();
	    _delay_cycles(208896ul);
	    //WATCHDOG_RESET();

	    /* Enable conditional requests for SMCLK, MCLK, and ACLK. */
	    UCSCTL8 = SMCLKREQEN | MCLKREQEN | ACLKREQEN;

	    /* Clear DCO and all oscillator fault flags. */
	    /* After FLL stabilizes, the DCO tap should not be at its maximum
	       or minimum value, so a fault should not occur.  If a fault
	       does occur, it will be caught by the ASSERT in the user NMI interrupt.
	    */
	    UCSCTL7 = 0u;

	    /* Clear, then enable oscillator fault interrupt. */
	    SFRIFG1 &= ~(OFIFG);
	    SFRIE1 |= OFIE;
	}


int main( void )
{
	configure_clock();
	configure_uart();
	open_uart();
	_enable_interrupts();
	enable_receive();

	for (;;)
	{
#if 0
		if (uart.AreBytesAvailable(port))
		{
	    	P6DIR = P6DIR | 0x02; // Set P6.1 as an output.
	    	P6SEL = P6SEL & 0xFD; // Select IO function for P6.1.
    		P6OUT = P6OUT | 0x02; // Set P6.1.
		}
#endif
	}
}

  • Hi Steve,

    I'm currently working to reproduce this issue and will get back to you once it's confirmed.

    Sincerely,
    Sean
  • What's the value of SYSRSTIV after a reset?
  • Very good question, I forgot to include this in my original post.

    When I first power up the board: SYSRSTIV_BOR

    When the first reset occurs after a character is sent to the USRT: SYSRSTIV_RSTNMI

    When the second reset occurs: SYSRSTIV_PMMKEY

    Any resets following those are all SYSRSTIV_PMMKEY.

    As some point, it stops resetting. I believe it's locked up, but I'm not completely sure... Cycling power resets this sequence back to the beginning.

  • Sean Huang15 said:
    Hi Steve,

    I'm currently working to reproduce this issue and will get back to you once it's confirmed.

    That would be awesome, but I doubt you'll be able to ... we have boards/micros here that behave properly, so I think the program is probably correct.

    Also, this is with CCS 5.2.1 with the MSP430 compiler version 4.1.1.

  • SYSRSTIV_RSTNMI

    Now you need to read SYSUNIV and/or SYSSNIV.

    SYSRSTIV_PMMKEY

    Strange; I don't see any code accessing the PMM registers.

  • Clemens Ladisch said:
    SYSRSTIV_RSTNMI

    Now you need to read SYSUNIV and/or SYSSNIV.

    I just did, and they both come back as 0x0000 (no interrupt pending).

  • You didn't, just by chance, connect the RXD signal to the RST pin? ;-)

    Well, there might be a noise or power issue. Do the boards have proper decoupling capacitors?

  • Hello, I'm the hardware engineer that suckered Steve into helping me with this problem.

    To answer your questions, I do not have the layout files to verify the board fully (this is a design that was handed off to us by a third party).  However, the decoupling capacitors are of appropriate size and follow the recommendations (470nF for Vcore and >10uF for DVcc/AVcc) so nothing obvious there.  The decoupling capacitors are as close to the pins as possible.  I can't rule out a noise issue yet.

  • We attempted to disable the PMM as a reset source by trying to write to PMMRIE. We were eventually successful after figuring out how to unlock the register access. However, before we properly unlocked the PMM registers, there was unexpected behavior.

    Right near the top of main I was writing to PMMRIE, which caused an immediate reset. Of course, this caused it to reset over and over again. I expected to see SYSRSTIV_PMMKEY set in SYSRSTIV every time, but instead on power up I got SYSRSTIV_BOR, the first reset was SYSRSTIV_RSTNMI (with SYSUNIV and SYSSNIV both 0x0000), with the following resets being PMMKEY.

    This happens to be the exact sequence of reset reasons as when the UART resets the board. Why isn't the very first reset, cause by the PMMRIE write, not a PMMKEY reset?
  • Clemens Ladisch said:

    Well, there might be a noise or power issue. Do the boards have proper decoupling capacitors?

    This is possible, but an experiment I just tried might rule that out.

    Instead of receiving from the UART in an ISR, I left interrupts completely disabled, and in my loop checked whether UCA1IFG had UCRXIFG set, and if so, read the byte from UCA1RXBUF and echo it back. This works without any resets.

    I then re-enabled interrupts, but left the UART receive interrupt disabled, and this also works. I then re-enabled the receive interrupt, and the problem was back. The position of cables and such on my desk remains unchanged, and the board is unchanged.

    I'm not using transmit interrupts in any of this, but in case I forgot to mention it earlier, a TX interrupt can also cause the same behavior and the RX interrupt. I'm about to set up a timer and see if its interrupt will do so as well...

  • Also, on the noise front, we tried injecting noise near the PCB to see if it was generally sensitive. First we used a capacitive coupling means to an ESD gun (self-discharge to a metal plate) and then inductive coupling (self-discharge to a cable loop). Neither caused any upset at 8kV.

    I was also able to get a look at the gerbers for the whole PCB stackup, and while it is not done the way I would want based on my layout-for-EMC background, nothing is out of the ordinary.
  • I wanted to see if another interrupt might also cause problems, so I set up TIMERA0 to provide an overflow interrupt. I thought initially I was able to cause the same behavior with this interrupt, but that turns out to not be the case (I made our "known good" board fail this way too, so maybe I'm doing something wrong). The timer ISR is an empty function:

    #pragma vector=TIMER0_A0_VECTOR
    __interrupt void Timer_A (void)
    {
    }

    I'm using the following function to enable it:

    void enable_timer()
    {
    	TA0CTL = (TA0CTL & 0x00FF) | 0x0200; // Select submain clock as clock source.
    	TA0CTL = TA0CTL | 0x00C0; // Clock divide by 8.
    	TA0CTL = (TA0CTL & 0xFFCF) | 0x0020; // Continuous mode.
    	TA0EX0 = 0x0007; // Clock divide by 8 again.
    	TA0CTL = TA0CTL | 0x0002; // Enable timer interrupt.
    }

    With the timer interrupt enabled, I get the following sequence of resets:

    1. Apply power. SYSRSTIV_BOR.
    2. Micro resets. SYSRSTIV_RSTNMI (no interrupts pending in the other two registers)
    3. Micro resets. SYSRSTIV_SECYV
    4. Repeat of 3...
    5. Repeat of 3...

    If I disable the interrupt (comment out line 7 of enable_timer()), the resets don't occur...

  • I tried to decode the magic numbers in configure_clock(). Am I correct in concluding that you're trying to run the CPU at 20 MHz?

    This will not work unless the core voltage (PMMCOREV) is increased. (And while you're at it, take a look at all those interesting PMM errata of the MSP430F5342.)

  • I'm working on raising Vcore. The MSP430 User's Guide has the following note in it:

    NOTE: See the MSP430x5xx and MSP430x6xx Core Libraries (SLAA448). These libraries contain
    useful and ready-to-use functions for easily configuring and using the PMM module.

    The link to SLAA448 is broken, a search of TI's web site didn't yield anything useful that I could tell. Where can I find these library functions?

    I tried using the sample code from slau208o section 2.2.4:

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

    I'm calling this right from the top of main():

    	for (unsigned int i = 1; i < 4; i++)
    		SetVCoreUp(i);

    However, execution never gets past the following line of code, during the first call to SetVCoreUp():

    	// Make sure no flags are set for iterative sequences
    	while ((PMMIFG & SVSMHDLYIFG) == 0);

  • Better use the example code for your MCU (MSP430F534x_UCS_10.c in slac504):

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

    Alternatively, use PMM_setVCoreUp() from driverlib:

    uint16_t PMM_setVCoreUp(uint8_t level){
        uint32_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
        HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0xA5;
    
        //Disable dedicated Interrupts
        //Backup all registers
        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 flags
        HWREG16(PMM_BASE + OFS_PMMIFG) = 0;
    
        //Set SVM highside to new level and check if a VCore increase is possible
        HWREG16(PMM_BASE + OFS_SVSMHCTL) = SVMHE | SVSHE | (SVSMHRRL0 * level);
    
        //Wait until SVM highside is settled
        while((HWREG16(PMM_BASE + OFS_PMMIFG) & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        HWREG16(PMM_BASE + OFS_PMMIFG) &= ~SVSMHDLYIFG;
    
        //Check if a VCore increase is possible
        if((HWREG16(PMM_BASE + OFS_PMMIFG) & SVMHIFG) == SVMHIFG)
        {
            //-> Vcc is too low for a Vcore increase
            //recover the previous settings
            HWREG16(PMM_BASE + OFS_PMMIFG) &= ~SVSMHDLYIFG;
            HWREG16(PMM_BASE + OFS_SVSMHCTL) = SVSMHCTL_backup;
    
            //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
            HWREG16(PMM_BASE + OFS_PMMRIE) = PMMRIE_backup;
            //Lock PMM registers for write access
            HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0x00;
            //return: voltage not set
            return (STATUS_FAIL);
        }
    
        //Set also SVS highside to new level
        //Vcc is high enough for a Vcore increase
        HWREG16(PMM_BASE + OFS_SVSMHCTL) |= (SVSHRVL0 * level);
    
        //Wait until SVM highside is settled
        while((HWREG16(PMM_BASE + OFS_PMMIFG) & SVSMHDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        HWREG16(PMM_BASE + OFS_PMMIFG) &= ~SVSMHDLYIFG;
    
        //Set VCore to new level
        HWREG8(PMM_BASE + OFS_PMMCTL0_L) = PMMCOREV0 * level;
    
        //Set SVM, SVS low side to new level
        HWREG16(PMM_BASE + OFS_SVSMLCTL) = SVMLE | (SVSMLRRL0 * level) |
                                           SVSLE | (SVSLRVL0 * level);
    
        //Wait until SVM, SVS low side is settled
        while((HWREG16(PMM_BASE + OFS_PMMIFG) & SVSMLDLYIFG) == 0)
        {
            ;
        }
    
        //Clear flag
        HWREG16(PMM_BASE + OFS_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
        HWREG16(PMM_BASE + OFS_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
        HWREG16(PMM_BASE + OFS_SVSMLCTL) |= SVSMLCTL_backup;
    
        //Restore High side settings
        //Clear all other bits except level settings
        HWREG16(PMM_BASE + OFS_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
        HWREG16(PMM_BASE + OFS_SVSMHCTL) |= SVSMHCTL_backup;
    
        //Wait until high side, low side settled
        while(((HWREG16(PMM_BASE + OFS_PMMIFG) & SVSMLDLYIFG) == 0) ||
              ((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
        HWREG16(PMM_BASE + OFS_PMMRIE) = PMMRIE_backup;
    
        //Lock PMM registers for write access
        HWREG8(PMM_BASE + OFS_PMMCTL0_H) = 0x00;
    
        return (STATUS_SUCCESS);
    }

  • I tried the first function from your post instead of bringing driverlib into the project, and it appears to be working (at least, it appears to be setting Vcore properly). However, the timer interrupt is still resetting the micro.

    I also reduced the frequency to 4,194,304, but to no avail. I also tried lower the freq to 4 MHz and set Vcore to max, that also did not resolve it.
  • Clemens Ladisch said:

    I tried to decode the magic numbers in configure_clock(). Am I correct in concluding that you're trying to run the CPU at 20 MHz?

    This will not work unless the core voltage (PMMCOREV) is increased.

    This was the key to the problem. Raising Vcore seems to have resolved it! Thanks!

**Attention** This is a public forum