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.

MSP430F5328 How to catch VMAIFG by SYSNMI ISR when stack over?



Hi Everybody,

I am trying to catch VMAIFG in my SYSNMI_VECTOR when stack over. and I use a recursion function to force stack over but I can not catch it in  SYSNMI_VECTOR when VMAIFG active and code will restart itself then I found SYSSNIV=0x000A so it means VMAIFG is actived. would you please help me to use ISR to catch this trap? my code is as below:

int main(void)
{
 volatile unsigned int i;

   WDTCTL = WDTPW+WDTHOLD;                   // Stop WDT
   

  PMAPPWD = 0x02D52;                        // Enable Write-access to modify port mapping registers
   P4MAP7 = PM_MCLK;
   PMAPPWD = 0;                              // Disable Write-Access to modify port mapping registers

   UCSCTL3 = SELREF_2;                       // Set DCO FLL reference = REFO
   UCSCTL4 |= SELA_2;                        // Set ACLK = REFO

   __bis_SR_register(SCG0);                  // Disable the FLL control loop
   UCSCTL0 = 0x0000;                         // Set lowest possible DCOx, MODx
   UCSCTL1 = DCORSEL_5;                      // Select DCO range 16MHz operation
   UCSCTL2 = FLLD_1 + 249;                   // Set DCO Multiplier for 8MHz
                                             // (N + 1) * FLLRef = Fdco
                                             // (249 + 1) * 32768 = 8MHz

   __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 8 MHz / 32,768 Hz = 250000 = MCLK cycles for DCO to settle
   __delay_cycles(250000);

   // Loop until XT1,XT2 & DCO stabilizes - In this case only DCO has to stabilize
   do
   {
     UCSCTL7 &= ~(XT2OFFG + XT1LFOFFG + DCOFFG);
                                             // Clear XT2,XT1,DCO fault flags
     SFRIFG1 &= ~OFIFG;                      // Clear fault flags
   }while (SFRIFG1&OFIFG);                   // Test oscillator fault flag


_bis_SR_register(GIE);  // enable GIE
  //========enable NMI IE========//
  SFRIE1 |= VMAIE + OFIE + NMIIE + ACCVIE;

  //=============================//

  while(1)
  {
   /*if ((P2IN & BIT0) == 0)*/ {
         Value = 851;
       }

       Value = sumr(Value);
    _NOP();

  }
}


unsigned long sumr(unsigned long n)
{
    return (n<=0)?0:( n+sumr(n-1) );
}

#pragma vector=UNMI_VECTOR
__interrupt void UNMI_ISR (void)
{
 switch(__even_in_range(SYSUNIV,0x08))  // all need to trace
 {
  case  SYSUNIV_NONE: break;
  case  SYSUNIV_NMIIFG: break;
  case SYSUNIV_OFIFG: break;
  case SYSUNIV_ACCVIFG:break;

  default:  break;
 }
}

#pragma vector=SYSNMI_VECTOR
__interrupt void SYSNMI_ISR (void)
{
 switch(__even_in_range(SYSSNIV,0x12))
 {
  case  SYSSNIV_NONE: break;
  case  SYSSNIV_SVMLIFG: break;
  case SYSSNIV_SVMHIFG: break;
  case SYSSNIV_DLYLIFG:break;
  case SYSSNIV_DLYHIFG:break;
  case SYSSNIV_VMAIFG:
   P1OUT |= LED;
   __delay_cycles(250000);
   P1OUT &= ~LED;
   __delay_cycles(250000);
   P1OUT |= LED;
   __delay_cycles(250000);
   P1OUT &= ~LED;
   __delay_cycles(250000);
   P1OUT |= LED;
   __delay_cycles(250000);
   P1OUT &= ~LED;
   break;   // maybe need to trace
  case SYSSNIV_JMBINIFG:break;
  case SYSSNIV_JMBOUTIFG:break;
  case SYSSNIV_VLRLIFG:break;
  case SYSSNIV_VLRHIFG:break;

  default:  break;
 }
}

  • You don’t need to enable GIE to get an NMI. NMI is not maskable and will always be called - unless you’re already in an NMI ISR.

    However, if the VAMIFG is set because the stack has grown beyond RAM, then trying to call the NMI ISR will push the return address on the stack - another vacant memory access.

    Returning from the ISR will read a wrong value from stack as return address - and is another VMA. However, at least one instruction is executed before entering the SYNMI ISR again. Which may (due to the wrong return address) cause a PUC and leave VMAIFG set.
    However, the ISR should be called. But you might not see the LED toggling because it seems you did not set P1.LED to output (P1DIR |= LED;)

  • Hi Michael,

    Thank for your great reply. sorry I think that is my mistake but I found another problem.

    My MCU will happen abnormal reset and it will active SYSRSTIV.PERF = 1. I store SYSRSTIV in info memory 0x1800 when system happen abnormal reset and that be caught in the head of my main program and I found 0x1800(SYSRSTIV) = 0x1E but I just get the description that 0x1E = PERF peripheral/configuration area fetch in user's guide but how is its reason? how does it caused by? would you please explain it for me? thanks a lot.

  • PERF means that the program counter somehow has been set to an address in the peripheral area (usually the lower 1k or 4k of the address range), so the CPU tries to fetch and execute peripheral data as code instructions.
    You don’t raise PMMCOREV, so the maximum MCLK frequency is 8MHz. While you’re working a the edge of the allowed range, this shouldn’t be a problem. If you’d try to run the CPU faster than 8MHz without raising the core frequency, this could result in all kinds of malfunctions, including jumping to wrong addresses and executing (or trying to execute) code from peripheral area.
    Other possible reasons are:
    - missing ISR for an enabled interrupt. But you don’t seem to have one.
    - Not disabling interrupts (including all NMIs) during a flash write (also no problem here)
    - Stack overflow. Either into data area, so stack content is overwritten by static data writes, causing return addresses on stack to be corrupted and pointing to the void, or letting the stack grow below ram area, so everything written to stack is lost.

  • Hi Michael,

    Many thank for your reply and I will base on your comment to figure out the reason and I will tell you my result.

**Attention** This is a public forum