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.

TMS320F28069: Inconsistency in F28069 Run-time and power up behavior among various chips

Part Number: TMS320F28069

Hi all, 

We are starting manufacturing of a control board that uses F28069U as the central DSP, we had completed our tests on our prototypes and before starting the main production, we manufactured 12 units just to see how is their behaviour and we got a big surprise which is almost all the 12 boards showing inconsistency in Power-up process and the details of the issue is as below:

Our system can turn ON at any time with any frequency ( like Turn ON/OFF every 2 seconds or more ) , now we have our code running on these boards, and we are randomly trying to turn them ON and OFF, most of the time the code starts right after Power up, and there is a LED on the board that will blink if the code is not frozen( we, of course, checked all the other functionalities), however, let's say 2 out of 10 times, the DSPs don't boot up and they stay frozen, the LED is also staying off, until we have to recycle the power again. 
After power recycling, mostly they start to work again but sometimes it requires multiple power recycling until the DSP can boot up again...

To this date, This behaviour has never been seen in the prototype which has the exact same circuit and components ( the 12 boards are its clones)!

Given this big headache, we started to investigate what is causing the issue, I started by checking the Voltages, transients at startup and so on, but everything seems good, there is no current drop or abnormal behaviour in the supply transients once we get the DSP frozen condition. ( the XRS stays always high and I think this seem to show there are no Brownout or other power-related issues, ...)

After this, I move to check the code, and I figure out a very strange thing, which was the DSPs in production fail in the following function:

void enable_interrupts()
{

      EALLOW;
      PieVectTable.ADCINT1 = &ADCINT1_isr; /* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER1.bit.INTx1 = 1;   /* Enable interrupt ADCINT1*/
      IER |= M_INT1;
      EALLOW;
      PieVectTable.EQEP1_INT = &EQEP1_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER5.bit.INTx1 = 1;   /* Enable interrupt EQEP1_INT*/
      IER |= M_INT5;
      EALLOW;
      PieVectTable.SCIRXINTA = &SCIRXINTA_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER9.bit.INTx1 = 1;   /* Enable interrupt SCIRXINTA*/
      IER |= M_INT9;
      EALLOW;
      PieVectTable.ECAP1_INT = &ECAP1_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER4.bit.INTx1 = 1;   /* Enable interrupt ECAP1_INT*/
      IER |= M_INT4;
      EALLOW;
      PieVectTable.ECAP2_INT = &ECAP2_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER4.bit.INTx2 = 1;   /* Enable interrupt ECAP2_INT*/
      IER |= M_INT4;
      EALLOW;
      PieVectTable.ECAP3_INT = &ECAP3_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER4.bit.INTx3 = 1;   /* Enable interrupt ECAP3_INT*/
      IER |= M_INT4;
      EALLOW;
      PieVectTable.ECAN0INTA = &ECAN0INTA_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER9.bit.INTx5 = 1;   /* Enable interrupt ECAN0INTA*/
      IER |= M_INT9;

//  EALLOW;
//  PieVectTable.ADCINT1 = &ADCINT1_isr; /* Hook interrupt to the ISR*/
//  PieVectTable.EQEP1_INT = &EQEP1_INT_isr;/* Hook interrupt to the ISR*/
//  PieVectTable.SCIRXINTA = &SCIRXINTA_isr;/* Hook interrupt to the ISR*/
//  PieVectTable.ECAP1_INT = &ECAP1_INT_isr;/* Hook interrupt to the ISR*/
//  PieVectTable.ECAP2_INT = &ECAP2_INT_isr;/* Hook interrupt to the ISR*/
//  PieVectTable.ECAP3_INT = &ECAP3_INT_isr;/* Hook interrupt to the ISR*/
//  PieVectTable.ECAN0INTA = &ECAN0INTA_isr;/* Hook interrupt to the ISR*/
//  EDIS;
//
//  PieCtrlRegs.PIEIER1.bit.INTx1 = 1;   /* Enable interrupt ADCINT1*/
//  IER |= M_INT1;
//  PieCtrlRegs.PIEIER5.bit.INTx1 = 1;   /* Enable interrupt EQEP1_INT*/
//  IER |= M_INT5;
//  PieCtrlRegs.PIEIER9.bit.INTx1 = 1;   /* Enable interrupt SCIRXINTA*/
//  IER |= M_INT9;
//  PieCtrlRegs.PIEIER4.bit.INTx1 = 1;   /* Enable interrupt ECAP1_INT*/
//  IER |= M_INT4;
//  PieCtrlRegs.PIEIER4.bit.INTx2 = 1;   /* Enable interrupt ECAP2_INT*/
//  IER |= M_INT4;
//  PieCtrlRegs.PIEIER4.bit.INTx3 = 1;   /* Enable interrupt ECAP3_INT*/
//  IER |= M_INT4;
//  PieCtrlRegs.PIEIER9.bit.INTx5 = 1;   /* Enable interrupt ECAN0INTA*/
//  IER |= M_INT9;

  /* Enable global Interrupts and higher priority real-time debug events:*/
  EINT;                                /* Enable Global interrupt INTM*/
  ERTM;                               /* Enable Global realtime interrupt DBGM*/

}

and the exact point of failure is when the code hooks the ECAP1 to the ISR as : 

EALLOW;
PieVectTable.ECAP1_INT = &ECAP1_INT_isr;/* Hook interrupt to the ISR*/
EDIS;

Right after this piece of code in faulty DSPs the system goes into a halt or frozen mode (occasionally and Not Always), I found this by putting another GPIO enabling and I tracked down the problem to here since my code now is running from Flash through a boot loader ( USB bootload written for DFUprog), now I'm going to explain some other important observations:

  1. our control cards don't have a JTAG locally mounted, so whenever the DSPs are frozen, right after I connect the JTAG they go back to normal operation!! the LED starts to blink and it seems everything is going great, also as long as the JTAG is in-circuit the code never fails...

  2. I tried to use our Watch-dog and the point is the Watch-dog whenever the failure occurs keeps resetting the board, but it can never recover it back to normal operation until I fully recycle the power ( we are using software watchdog not NMI)

  3. on our board, we don't have the GPIO 34 or TDO pulled up externally. ( I checked, even with external pull-ups there is no difference and it seems the issue is not the boot mode selection...)
  4. To eliminate the effect of the Boot-loader, I removed it, and I made our code stand-alone, just to be sure the boot-loader is not causing the issue, and again without the boot-loader, the code halts in the same spot occasionally and not always ( I wish it was always)

  5. I have attached here for you our Linker command file for our system.

here are the Serial Numbers engraved on the Faulty and Working F28069U :

Faulty: F28069UPNT - G4A - 08AFXHW - G4
Working: F28069UPNT - G4A - 99C4EXW - G4

I couldn't find a way to track down the production date of these chips but it appears to me by some speculations that the faulty ones are older as in the 3rd section it starts with Zero...

So now the question is This:

Is this a hardware problem or software problem and how to solve it? 

Thanks in advance
John

c28069_CLA_BL.zip

  • Just an update:

    Today I changed the DSP to a new one on one of the boards and the Boot-up issue is still present ( occasional boot-up failure as mentioned above).

    Thanks
    John

  • and the exact point of failure is when the code hooks the ECAP1 to the ISR as : 

    Hi John,

    Is the eCAP ISR already copied from flash to RAM before the interrupt is connected and enabled in the PIE?

    My line of thinking is it maybe an order of setting things up that sometimes doesn't go as planned.  I'm thinking in the "doesn't work" case an eCAP event may be detected (via some glitch on the GPIO during setup) before everything is completely setup.  In this case the ISR would be taken as soon as enabled in the PIE.  So the system would need to be ready before this occurs. An experiment maybe clearing any pending eCAP interrupt before it is enabled in the PIE.  

    -Lori

  • Hi Lori, 

    I believe yes, as the first thing in the Main function is copying the contents of the flash to the RAM, through c2000_flash_init() function shown below:

    void c2000_flash_init(void)
    {
      #if MW_RUNTIME_FLASHLOAD
      // Copy InitFlash function code and Flash setup code to RAM
      memcpy(& RamfuncsRunStart,&RamfuncsLoadStart, (Uint32)(&RamfuncsLoadEnd-&RamfuncsLoadStart));
      #ifdef CLA_BLOCK_INCLUDED
        memcpy(&Cla1funcsRunStart, &Cla1funcsLoadStart, (Uint32)&Cla1funcsLoadSize);
        memcpy(&Cla1mathTablesRunStart, &Cla1mathTablesLoadStart, (Uint32)&Cla1mathTablesLoadSize);
      #endif
      // Call Flash Initialization to setup flash waitstates
      // This function must reside in RAM
      InitFlash();
      #endif
    }

    The code in the main is done as below:

    int main(void)
    {
      float modelBaseRate = 0.001;
      float systemClock = 90;
    
      /* Initialize variables */
      stopRequested = false;
      runModel = false;
    
      CsmUnlock();
    
      c2000_flash_init();
      init_board();
      initialize(); //initialize global variables, activation of USB clock
      configureADCINT1();
      enableADCInterrupt1();
      enable_interrupts(); //here ECAP gets activated
      initWatchdog();
      globalInterruptEnable();
      while (runModel) {
        stopRequested = !(
                          rtmGetErrorStatus(V001_M) == (NULL));
      }
    
      /* Disable rt_OneStep() here */
    
      /* Terminate model */
      terminate();
      globalInterruptDisable();
      return 0;
    }

    An experiment maybe clearing any pending eCAP interrupt before it is enabled in the PIE.  

    so for this case you mean I delay activation of ECAP interrupt or sth else? how can I know the ECAP interrupt is pending?

    Regards
    John

  • I believe yes, as the first thing in the Main function is copying the contents of the flash to the RAM, through c2000_flash_init()

    ok, my hunch may not be valid.  I also see globalInterruptEnable() is called later - an actual interrupt would not be taken until that spot.

    so for this case you mean I delay activation of ECAP interrupt or sth else? how can I know the ECAP interrupt is pending?

    At this point (before the system really begins running) you can clear the PIEIFR register and the CPU's IFR register.  This would clear any interrupt that is pending.

    Note: During runtime you typically would not do this as it can cause missed interrupts.    But it maybe worth a try to see if it changes the behavior and provides some clues. 

    I'm re-reading through all of the information and had a couple of questions -

    Today I changed the DSP to a new one on one of the boards and the Boot-up issue is still present

    Does the problem follow a board or does it follow a device ?  i.e.

    • Was the new device a known "working" DSP? Did it work on board A but not board P (the issue follows board P).  

    This would help narrow down if the issue is board or device.  

    To eliminate the effect of the Boot-loader, I removed it, and I made our code stand-alone, just to be sure the boot-loader is not causing the issue, and again without the boot-loader, the code halts in the same spot occasionally and not always ( I wish it was always)

    If the code does not halt in the same place then it is likely not related to that eCAP ISR.  I missed this previously. 

    I'm beginning to lean more on it being a board issue, rather than a code issue. 

    Summary and some questions:

    1. Problem is not seen on all boards.
      1. If the flash image is exactly the same, then this reduces the chances of a linker command file problem.
    2. Problem is intermittent.  
    3. Fail signature varies - i.e. CPU execution stops in different locations.
    4. Watchdog 
    5. Problem goes away when JTAG is connected. 
    6. Problem is seen after a power-up / power-cycle of the board.
      1. Please double check the power sequencing of the design against the data sheet requirements
      2. If you wait longer between power down / up is the behavior different? 
    7. What is the boot mode?
      1. You mentioned TDO and GPIO34 are high so you are using get mode? 
      2. You mentioned external pull-ups on TDO/GPIO34 do not change the behavior.  
    8. Is there any temperature dependency - i.e. does the behavior get better or worse based on ambient temp?
    9. Does a device that fails feel "hot" or warmer than one that is working normally? 
    10. Does the problem follow a particular device or a particular board?  
      1. You mentioned a potential serial number tie
    11. Please double check the device errata for any issues that may apply to the specific design.
    12. You mentioned checking clocks and power. 
      1. double check to make sure there is no power droop before the issue is seen.  
      2. check power-up sequencing against the data sheet  
    13. Does TRSTn have an external 2.2 k ohm (or less) resister?
  • Hi
    After your idea yesterday regarding "an eCAP event may be detected (via some glitch on the GPIO during setup) before everything is completely setup" and as our eCAP indeed is connected to a GPIO to sense the Hall sensors signals, I proceed on as following, by placing all the interrupts except the ADC interrupt right before the forever while loop as you can see below in  Interrupt_Activation_AUX() function:

    int main(void)
    {
      float modelBaseRate = 0.001;
      float systemClock = 90;
    
      /* Initialize variables */
      stopRequested = false;
      runModel = false;
    
      CsmUnlock();
    
      c2000_flash_init();
      init_board();
    
      bootloaderInit();
      rtmSetErrorStatus(V001_M, 0);
      initialize();
      configureADCINT1();
      enableADCInterrupt1();
      enable_interrupts();
      initWatchdog();
      globalInterruptEnable();
    
      Interrupt_Activation_AUX();
    
      while (runModel) {
        stopRequested = !(
                          rtmGetErrorStatus(V001_M) == (NULL));
      }

    the Interrupt_Activation_AUX() has the following form:

    void Interrupt_Activation_AUX()
    {
    
      DINT;
      IER &= 0xC001;
      IFR &= 0xC001; //clearing pending interrupts except ADC,...
      EALLOW;
      PieVectTable.EQEP1_INT = &EQEP1_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER5.bit.INTx1 = 1;   /* Enable interrupt EQEP1_INT*/
      IER |= M_INT5;
      EALLOW;
      PieVectTable.SCIRXINTA = &SCIRXINTA_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER9.bit.INTx1 = 1;   /* Enable interrupt SCIRXINTA*/
      IER |= M_INT9;
      EALLOW;
      PieVectTable.ECAP1_INT = &ECAP1_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER4.bit.INTx1 = 1;   /* Enable interrupt ECAP1_INT*/
      IER |= M_INT4;
      EALLOW;
      PieVectTable.ECAP2_INT = &ECAP2_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER4.bit.INTx2 = 1;   /* Enable interrupt ECAP2_INT*/
      IER |= M_INT4;
      EALLOW;
      PieVectTable.ECAP3_INT = &ECAP3_INT_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER4.bit.INTx3 = 1;   /* Enable interrupt ECAP3_INT*/
      IER |= M_INT4;
      EALLOW;
      PieVectTable.ECAN0INTA = &ECAN0INTA_isr;/* Hook interrupt to the ISR*/
      EDIS;
      PieCtrlRegs.PIEIER9.bit.INTx5 = 1;   /* Enable interrupt ECAN0INTA*/
      IER |= M_INT9;
    
      EINT;
    }

    After doing so, I see the problem is mostly gone and as long as ADC interrupt is exerted with "Full-speed" everything seems to be normal, but to explain what I mean by "Full-Speed", I should say, our ADC interrupt is synched with ePWM1 output, and our system can have frequencies from 7 to 90kHz on the ePWM1.

    Once the PWM frequency is well above 40kHz I see no problem in start-up, but when we reduce it further to values like 20kHz, I see the ADC interrupt freezes occasionally ( the previous problem shows up again on Boot up and it freezes).

    In our environment, the maximum sampling rate from the ADC1 that we can reach is something around 35 micro seconds or near 30kHz (our run-time sampling rate), All the code is placed in the ADC1 interrupt.

    I can say the ADC interrupt freezes because it doesn't kick the Watchdog inside of it which is the only place that we reset the watchdog, and the watchdog keeps resetting the DSP ( after failure DSP never recovers and keeps resetting itself).

    So it seems to me that the ADC interrupt somehow fails ( maybe overflows or sth) and it never recovers.

    The strangest thing is after the watchdog reset the problem doesn't go away and it seems the ADC doesn't re-initialize itself.

    I tried to add the following code in the initialization part of the main() function to clear the overflow flag in the ADC1 after reset but it didn't help:

      if (AdcRegs.ADCINTOVF.all != 0){
          AdcRegs.ADCINTFLGCLR.all = 0x1FF;
          AdcRegs.ADCINTOVFCLR.all = 0x1FF;
      }

    To answer your above questions:

    If you wait longer between power down / up is the behavior different? 

    Yes, it's certainly showing better behaviour, like 3s waiting is literally showing no problem.

    What is the boot mode?

    it's booting from Flash

    Is there any temperature dependency - i.e. does the behavior get better or worse based on ambient temp?

    Not clear or measured ( I feel it's independant)

    Does the problem follow a particular device or a particular board? 

    almost we see this on all of the boards.

    double check to make sure there is no power droop before the issue is seen.  

    Done, as said before the power is stable.

    Does TRSTn have an external 2.2 k ohm (or less) resister?

    Yes, it has a 2.2k tied to 3.3V with a 0.1uF CAP on the XRS pin.

    I will be waiting for your thoughts.
    John

  • John,

    Is there any interrupt nesting involved?

    Is there an ISR installed for every interrupt  in the PIE?  In our example SW we have code that initializes the whole PIE vector table - even if they are not used in the system.  It can help catch the CPU going into the weeds.   

    Is it true that with JTAG connected, the issue never occurs?  

    I've asked a colleague to also take a look at the case to see if they have any additional suggestions of what to check. 

    -Lori

  • Is there any interrupt nesting involved?

    I'm not sure about that, we are certainly having a non-preemptive interrupt assigned to ADC1, and here is the initialization function of the ADC1 Interrupt:

    interrupt void ADCINT1_isr(void)
    {
      volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
      PieCtrlRegs.PIEIER1.all &= ~1;
                                  /*disable group1 lower/equal priority interrupts*/
      asm(" RPT #5 || NOP");               /*wait 5 cycles        */
      IFR &= ~1;      /*eventually disable lower/equal priority pending interrupts*/
      PieCtrlRegs.PIEACK.all = 1;
                       /*ACK to allow other interrupts from the same group to fire*/
      IER |= 1;
      EINT;                                /*global interrupt enable*/
      isr_int1pie1_task_fcn();
      DINT;
      /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR    */
      PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;
                                       /*restore PIEIER register that was modified*/
      EALLOW;
      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
      EDIS;
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
                                         /* Acknowledge to receive more interrupts*/
    }

    the configureADCINT1(void) is like:

    void configureADCINT1(void)
    {
    	EALLOW;
    	PieVectTable.ADCINT1 = &SEQ1INT_isr;     /* Hook interrupt to the ISR*/
    	EDIS;
    
    	PieCtrlRegs.PIEIER1.bit.INTx1 = 1;   /* Enable interrupt ADCINT1 */
    	IER |= M_INT1;
    }

    and the SEQ1INT_isr() is like:

    interrupt void SEQ1INT_isr(void)
    {
        volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
        PieCtrlRegs.PIEIER1.all &= ~PIEMASK0;      /* disable group1 lower/equal priority interrupts */
        asm(" RPT #5 || NOP");               /* wait 5 cycles */
        IFR &= ~IFRMASK;                           /* eventually disable lower/equal priority pending interrupts */
        PieCtrlRegs.PIEACK.all = IFRMASK;          /* ACK to allow other interrupts from the same group to fire */
        IER |= 1;
        EINT;                                /* global interrupt enable */
        DINT;                                /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR */
      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
      PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;/*restore PIEIER register that was modified */
    
    }

    and the enableADCInterrupt1() is like:

    void enableADCInterrupt1(void)
    {
    	asm(" SETC INTM"); /* Disable Interrupt Global Enable Bit - set it to 1 */
    	PieCtrlRegs.PIEIER1.all |= 1; /* Enable PIER bit for ADCINT1 */
    	asm(" CLRC INTM"); /* Enable Interrupt Global Enable Bit - set it to 0 */
    }

    so the order of ADC interrupt initialization calls are :

    1- configureADCINT1() ==> calls SEQ1INT_isr()

    2- enableADCInterrupt1()

    3- enable_interrupts() ==> enables the ADC interrupt and it's ISR

    Is there an ISR installed for every interrupt  in the PIE?  In our example SW we have code that initializes the whole PIE vector table - even if they are not used in the system.  It can help catch the CPU going into the weeds.

    if you mean for every possible interrupt in the CPU, I should say no, I believe only the used interrupts are initialized and the rest are not, I will check this example if I can find it ( I hope in C2000 examples...)

    Is it true that with JTAG connected, the issue never occurs?  

    yes, with JTAG connected the issue never occurs, even in conditions that the CPU is frozen, as soon as I connect the JTAG, the CPU goes back to normal operation ( Even Reseting the Micro doesn't put it back to normal operation and it stays freezes or continuously getting reset by Watchdog)

     I will be waiting for your thoughts on these initializations of ADC interrupt.

    Regards
    John

  • John,

    The code is nesting interrupts - this is done by the code at the start of the ADC ISR - it is enabling lower priority interrupts to be serviced while the ADC ISR runs.

    The reason I asked about this is there are some fairly strict guidelines for nesting interrupts and if they are not followed it can cause issues.  Since the behavior you see is related to the rate of interrupts this is a path to follow and see if it yields anything. 

    Refer to

    In particular this caution:

    I'm wondering if the code void enableADCInterrupt1(void) may be called somewhere outside of an ISR. 

    Adding an interrupt handler for every interrupt can help to catch this problem if it is happening and also keep the PC from going into the weeds.  In particular interrupt 1 in each group (i.e. INTx.1) interrupts can be triggered even if not enabled or used.  It can be one actual ISR that all the unused vectors point to.  This is what our examples do in the default ISR setup routines. 

    Regards

    Lori

  • Hi Lori, 

    following up with your suggestions:

    Adding an interrupt handler for every interrupt can help to catch this problem if it is happening and also keep the PC from going into the weeds.  In particular interrupt 1 in each group (i.e. INTx.1) interrupts can be triggered even if not enabled or used.  It can be one actual ISR that all the unused vectors point to.  This is what our examples do in the default ISR setup routines. 

    I added an ISR for all the unused interrupts and I saw that I catch nothing ( I checked the function by activating hooking some active interrupt to the trap and I saw it catches them), the interrupt Trap was as below:

    interrupt void ILLEGAL_isr(void)
    {
        GpioDataRegs.GPBSET.bit.GPIO39 = 1;
    
        //IFR &= 0x0000; //disable all interrupts
        //PieCtrlRegs.PIEACK.all = 0x0FFF;
    
        /* Acknowledge to receive more interrupts*/
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP2;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP3;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP4;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP5;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP6;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP7;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP8;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP9;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP10;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP11;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP12;
    
        return;
    }
    
    void hook_illegal_interrupts()
    {
        //DELAY_US(3000);                      // wait 3ms for the board to stabilize
        /* Disable and clear all CPU interrupts */
        //DINT;
        //IER &= 0xC001;
        //IFR &= 0xC001;
        EALLOW;
    //INTx.1 group
        PieVectTable.EPWM1_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM1_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.SPIRXINTA = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.DINTCH1 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.I2CINT1A = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT1 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.XINT3 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
    //INTx.2 group
        PieVectTable.ADCINT2 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM2_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM2_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EQEP2_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.SPITXINTA = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.DINTCH2 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.I2CINT2A = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.SCITXINTA = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ADCINT2 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT2 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
    //INTx.3 group
        PieVectTable.EPWM3_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM3_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.SPIRXINTB = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.DINTCH3 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.SCIRXINTB = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ADCINT3 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT3 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
    //INTx.4 group
        PieVectTable.XINT1 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM4_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM4_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.HRCAP3_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.SPITXINTB = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.DINTCH4 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.SCITXINTB = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ADCINT4 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT4 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
    //INTx.5 group
        PieVectTable.XINT2 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM5_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM5_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.HRCAP4_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.MRINTA = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.DINTCH5 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ADCINT5 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT5 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
    //INTx.6 group
        PieVectTable.ADCINT9 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM6_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM6_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.MXINTA = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.DINTCH6 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ECAN1INTA = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ADCINT6 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT6 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
    //INTx.7 group
        PieVectTable.TINT0 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM7_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM7_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.HRCAP1_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ADCINT7 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT7 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.LVF = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
    //INTx.8 group
        PieVectTable.WAKEINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM8_TZINT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.EPWM8_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.HRCAP2_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        //PieVectTable.USB0_INT = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.ADCINT8 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.CLA1_INT8 = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
        PieVectTable.LUF = &ILLEGAL_isr; /* Hook interrupt to the ISR*/
    
        EDIS;
    }

    So now that I know I don't have any illegal or uninitialized interrupt causing the issue I put my focus on the Nesting issue, for instance, if I change the ADC interrupt ISR as below, the problem will be gone but non of the other interrupts will work as the ADC interrupt is non-pre-emptive and has the highest priority I think:

    interrupt void ADCINT1_isr(void)
    {
      volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
      volatile unsigned int PIEIER4_stack_save = PieCtrlRegs.PIEIER4.all;
      volatile unsigned int PIEIER5_stack_save = PieCtrlRegs.PIEIER5.all;
      volatile unsigned int PIEIER9_stack_save = PieCtrlRegs.PIEIER9.all;
      PieCtrlRegs.PIEIER1.all &= ~1;
                                  /*disable group1 lower/equal priority interrupts*/
      PieCtrlRegs.PIEIER4.all &= ~7;
                                  /*disable group4 lower/equal priority interrupts*/
      PieCtrlRegs.PIEIER5.all &= ~1;
                                  /*disable group5 lower/equal priority interrupts*/
      PieCtrlRegs.PIEIER9.all &= ~17;
                                  /*disable group9 lower/equal priority interrupts*/
      asm(" RPT #5 || NOP");               /*wait 5 cycles        */
      IFR &= ~281;    /*eventually disable lower/equal priority pending interrupts*/
      PieCtrlRegs.PIEACK.all = 281;
                       /*ACK to allow other interrupts from the same group to fire*/
      IER |= 1;
      EINT;                                /*global interrupt enable*/
      isr_int1pie1_task_fcn();
      DINT;
      /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR    */
      PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;
                                       /*restore PIEIER register that was modified*/
      PieCtrlRegs.PIEIER4.all = PIEIER4_stack_save;
                                       /*restore PIEIER register that was modified*/
      PieCtrlRegs.PIEIER5.all = PIEIER5_stack_save;
                                       /*restore PIEIER register that was modified*/
      PieCtrlRegs.PIEIER9.all = PIEIER9_stack_save;
                                       /*restore PIEIER register that was modified*/
      EALLOW;
      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
      EDIS;
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
                                         /* Acknowledge to receive more interrupts*/
    }

    So now there is a strong guess that Nesting is causing the issue, but I wasn't able to fix the case, with Nesting the ADC ISR is as shown above in the previous post, but for this part of your recommendations I didn't get what do you mean?

    I'm wondering if the code void enableADCInterrupt1(void) may be called somewhere outside of an ISR. 

    this function is already outside of the ISR ....

    based on this, one should never touch PIEIERx register outside of the ISR of the same group, but using enableADCInterrupt1(void) the PIEIER1 is altered and it seems this is in contradiction with what the guide suggests, however now, how can I activate the interrupt inside of the ISR itself? 

    I mean shouldn't we first activate the interrupt and then service it? now the process seems reversed...

    so I got lost here in this part, any help is much appreciated.

    Regards
    John

  • John,

    In the nested ISR information link, there is this caution:

    Do not modify PIEIER registers outside of an ISR for that group. For example, PIEIER1 should only be modified within an ISR from group 1. Likewise PIEIER2 should only be modified within a group 2 ISR.

    Referencing your last post - The ADC ISR is in PIE group 1  (reference PIE Interrupt Vector table 3-5 in the TRM), but the code is also modifying other group PIEIER registers (group 4, group 5, group9).  This violates the caution. 

    I don't see this in your previous code, so I think my comments caused some confusion. 


    PieCtrlRegs.PIEIER4.all &= ~7;
    /*disable group4 lower/equal priority interrupts*/
    PieCtrlRegs.PIEIER5.all &= ~1;
    /*disable group5 lower/equal priority interrupts*/
    PieCtrlRegs.PIEIER9.all &= ~17;
    /*disable group9 lower/equal priority interrupts*/

    I'm wondering if the code void enableADCInterrupt1(void) may be called somewhere outside of an ISR. 

    this function is already outside of the ISR ....

    The function modifies PIEIER1.  It can be called during initialization (before interrupts start) or from a group 1 interrupt as part of the nesting scheme. If it is called from, for example, a group 5 ISR or in the middle of a random function during runtime, then it violates the caution. 

    based on this, one should never touch PIEIERx register outside of the ISR of the same group, but using enableADCInterrupt1(void) the PIEIER1 is altered and it seems this is in contradiction with what the guide suggests, however now, how can I activate the interrupt inside of the ISR itself? 

    The initial system setup - before interrupts are started - the PIEIER registers can be configured freely.  Once interrupts start, modifying a PIEIERx register should only be modified inside a group x ISR.   

    The reason: When the CPU services an ISR from group x, the PIE will hold off additional interrupts from group x until the PIEACK is done by the CPU.  During this time, PIEIERx can be modified because no additional group x interrupts will have been passed to the CPU's IFR x.   

    If (in the same group x interrupt) instead PIEIERy is modified, and the PIEACK is NOT holding off group y interrupts to the CPU, there is the possibility of a race condition as described in the TRM. 

  • Hi Lori,

    The function modifies PIEIER1.  It can be called during initialization (before interrupts start) or from a group 1 interrupt as part of the nesting scheme. If it is called from, for example, a group 5 ISR or in the middle of a random function during runtime, then it violates the caution. 

    placing this function before activation of the interrupt is not helping, BTW, I reverted back the code to the old version and the ADC ISR now is like this:

    interrupt void ADCINT1_isr(void)
    {
    
        volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
        PieCtrlRegs.PIEIER1.all &= ~1;
        /*disable group1 lower/equal priority interrupts*/
        asm(" RPT #5 || NOP");
        /*wait 5 cycles        */
        IFR &= ~1; /*eventually disable lower/equal priority pending interrupts*/
        PieCtrlRegs.PIEACK.all = 1;
        /*ACK to allow other interrupts from the same group to fire*/
        IER |= 1;
        EINT;
        /*global interrupt enable*/
        isr_int1pie1_task_fcn();
        DINT;
        /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR    */
        PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;
        /*restore PIEIER register that was modified*/
        EALLOW;
        AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
        EDIS;
        PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
        /* Acknowledge to receive more interrupts*/
    }

    So clearly the issue is with Nesting but I have no idea how to track down the issue...

    any thoughts on that are highly appreciated.

    Regards
    John

  • John,

    The sequence in the code above does not match that in the nesting guide.  For example, there isn't a NOP between the PIEACK and EINT...

    Can you try with the exact same sequence?  

    // // C28x ISR Code // // Enable nested interrupts // // interrupt
    void EPWM1_TZINT_ISR(void)
    {
            uint16_t TempPIEIER;
            TempPIEIER = PieCtrlRegs.PIEIER2.all; // Save PIEIER register for later
            IER |= 0x002;                         // Set global priority by adjusting IER
            IER &= 0x002;
            PieCtrlRegs.PIEIER2.all &= 0x0002;    // Set group priority by adjusting PIEIER2 to allow INT2.2 to interrupt current ISR
            PieCtrlRegs.PIEACK.all = 0xFFFF;      // Enable PIE interrupts
            asm("       NOP");                    // Wait one cycle
            EINT;                                 // Clear INTM to enable interrupts
            //
            // Insert ISR Code here.......
            // for now just insert a delay
            //
            for(i = 1; i <= 10; i++) {}
            //
            // Restore registers saved:
            //
            DINT;
            PieCtrlRegs.PIEIER2.all = TempPIEIER;
    }

  • Hi Lori, 

    if by exact same process you mean the following function, unfortunately, I should say it doesn't work and the ADC ISR is not fired at all...

    interrupt void ADCINT1_isr(void)
    {
        volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
        IER |= 0x001;                         // Set global priority by adjusting IER
        IER &= 0x001;
        PieCtrlRegs.PIEIER1.all &= 0x0001;    // Set group priority by adjusting PIEIER1 to allow INT1.1 to interrupt current ISR
        PieCtrlRegs.PIEACK.all = 0xFFFF;      // Enable PIE interrupts
        asm("       NOP");                    // Wait one cycle
        EINT;                                 // Clear INTM to enable interrupts
        isr_int1pie1_task_fcn();
        DINT;
        PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;
    
    }

    do you think in this case the  SEQ1INT_isr(void) is playing any role as it's called before hooking the ADC ISR to the interrupt?

    interrupt void SEQ1INT_isr(void)
    {
        volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
        PieCtrlRegs.PIEIER1.all &= ~PIEMASK0;      /* disable group1 lower/equal priority interrupts */
        asm(" RPT #5 || NOP");               /* wait 5 cycles */
        IFR &= ~IFRMASK;                           /* eventually disable lower/equal priority pending interrupts */
        PieCtrlRegs.PIEACK.all = IFRMASK;          /* ACK to allow other interrupts from the same group to fire */
        IER |= 1;
        EINT;                                /* global interrupt enable */
        DINT;                                /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR */
      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
      PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;/*restore PIEIER register that was modified */
    
    }

  • if by exact same process you mean the following function, unfortunately, I should say it doesn't work and the ADC ISR is not fired at all...

    Hi John,

    By sequence I meant the sequence of steps and the order of the steps - i.e. (1) store PIEIER (2) modify IER (3) clear PIEACK (4) wait one cycle.... etc.  The actual values loaded into the registers is dependent on the system itself and which interrupts you want to allow to nest.   The function I pasted was just an example.

    The steps are outlined here: 

    https://software-dl.ti.com/C2000/docs/c28x_interrupt_nesting/html/index.html#adding-simple-software-prioritization-nesting

    it doesn't work and the ADC ISR is not fired at all...

    I am not sure why this would be the case.  It should fire at least once I would think if it is still enabled the same way in the system initialization. 

    do you think in this case the  SEQ1INT_isr(void) is playing any role as it's called before hooking the ADC ISR to the interrupt?

    Any interrupt service routine that allows nesting of interrupts should follow the same sequence of steps in order to enable other interrupts to be serviced during the routine. i.e. (1) store PIEIER (2) modify IER... etc.

    Hope this helps clarify. 

    Cheers

    Lori

  • Hi Lori, 

    so based on our discussions and the guides, I tried to change the ADC ISR with the exact same procedure to comply with interrupt nesting mentioned above as below, I'm putting the ISR routine Before and After applying the changes so you can compare them, now the ADC ISR continuously fires, but the issue with occasional freezing on boot-up is still present ( the issue gets exacerbated when I connect an external module like an encoder which is connected to both Encoder and ECAP inputs ...)

    ADC ISR before :

      interrupt void ADCINT1_isr(void)
    {
      volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
      PieCtrlRegs.PIEIER1.all &= ~1;
                                  /*disable group1 lower/equal priority interrupts*/
      asm(" RPT #5 || NOP");               /*wait 5 cycles        */
      IFR &= ~1;      /*eventually disable lower/equal priority pending interrupts*/
      PieCtrlRegs.PIEACK.all = 1;
                       /*ACK to allow other interrupts from the same group to fire*/
      IER |= 1;
      EINT;                                /*global interrupt enable*/
      isr_int1pie1_task_fcn();
      DINT;
      /* disable global interrupts during context switch, CPU will enable global interrupts after exiting ISR    */
      PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save;
                                       /*restore PIEIER register that was modified*/
      EALLOW;
      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
      EDIS;
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
                                         /* Acknowledge to receive more interrupts*/
    }
                                         

    ADC ISR After ( done following the standard procedure offered):

    interrupt void ADCINT1_isr(void)
    {
    /**********************Standard ISR for  Nesting*********************************/
        volatile unsigned int PIEIER1_stack_save = PieCtrlRegs.PIEIER1.all;
        IER &= ~1;
        PieCtrlRegs.PIEIER1.all &= ~1; /*disable group1 lower/equal priority interrupts*/
        PieCtrlRegs.PIEACK.all = 1; /*ACK to allow other interrupts from the same group to fire*/
        asm("           NOP");
        EINT;
        isr_int1pie1_task_fcn();
        DINT;
        PieCtrlRegs.PIEIER1.all = PIEIER1_stack_save; /*restore PIEIER register that was modified*/
        EALLOW;
        AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;
        EDIS;
    }

    So now the functionality of the code is the same between each of these ISRs but they both show occasional failure in boot-up....

    So do you have any thoughts on this?

    Regards
    John

  • Thank you for the update John. 

    Did you also check to see if there is a modification of a PIEIERx anywhere in the code that is not (a) part of initialization - before any interrupts are started (b) within an interrupt service routine of the same group x ?

    Cheers

    Lori

  • Lori, 

    right after hooking up the ADC ISR and activating it, the other interrupts are hooked and subsequently, their PIEIERx is altered, except this part, nowhere else the PIEIERx is touched in the code.

    void enable_interrupts()
    {
        EALLOW;
        PieVectTable.ADCINT1 = &ADCINT1_isr; /* Hook interrupt to the ISR*/
        EDIS;
        PieCtrlRegs.PIEIER1.bit.INTx1 = 1; /* Enable interrupt ADCINT1*/
        IER |= M_INT1;
        EALLOW;
        PieVectTable.EQEP1_INT = &EQEP1_INT_isr;/* Hook interrupt to the ISR*/
        EDIS;
        PieCtrlRegs.PIEIER5.bit.INTx1 = 1; /* Enable interrupt EQEP1_INT*/
        IER |= M_INT5;
        EALLOW;
        PieVectTable.SCIRXINTA = &SCIRXINTA_isr;/* Hook interrupt to the ISR*/
        EDIS;
        PieCtrlRegs.PIEIER9.bit.INTx1 = 1; /* Enable interrupt SCIRXINTA*/
        IER |= M_INT9;
        EALLOW;
        PieVectTable.ECAP1_INT = &ECAP1_INT_isr;/* Hook interrupt to the ISR*/
        EDIS;
        PieCtrlRegs.PIEIER4.bit.INTx1 = 1; /* Enable interrupt ECAP1_INT*/
        IER |= M_INT4;
        EALLOW;
        PieVectTable.ECAP2_INT = &ECAP2_INT_isr;/* Hook interrupt to the ISR*/
        EDIS;
        PieCtrlRegs.PIEIER4.bit.INTx2 = 1; /* Enable interrupt ECAP2_INT*/
        IER |= M_INT4;
        EALLOW;
        PieVectTable.ECAP3_INT = &ECAP3_INT_isr;/* Hook interrupt to the ISR*/
        EDIS;
        PieCtrlRegs.PIEIER4.bit.INTx3 = 1; /* Enable interrupt ECAP3_INT*/
        IER |= M_INT4;
        EALLOW;
        PieVectTable.ECAN0INTA = &ECAN0INTA_isr;/* Hook interrupt to the ISR*/
        EDIS;
        PieCtrlRegs.PIEIER9.bit.INTx5 = 1; /* Enable interrupt ECAN0INTA*/
        IER |= M_INT9;
    
        /* Enable global Interrupts and higher priority real-time debug events:*/
        EINT;
        /* Enable Global interrupt INTM*/
        ERTM;
        /* Enable Global realtime interrupt DBGM*/
    }
     

    so if chaning the PIEIERx in this routine after activation of ADC ISR which is the first interrupt that is getting activated is not allowed, the question is where can I initialize these PIEIERs for other groups which is used for activation of the other interrupts?

    Regards
    John

  • John,

    I don't see anything wrong with the enable_interrupts() code.  The key is you are only enabling interrupts in the PIEIER registers.  

    The race condition happens when PIEIER is modified such that some interrupts are switched from enabled to disabled.   The CPU may try to service an interrupt and the PIE says "no interrupt enabled - so I'll give you the first ISR vector in the group".  You also have the  ISRs setup that would catch such a case. 

    I'll have to put some more thought into what to suggest next.   I'll get back to you by end of Monday if not before.

    Lori

  • -TRST needs to be connected to GND thru a Pull-down resistor (not to 3.3v). Would you be willing to share your schematics offline?

  • Hi Hareesh, 

    Thanks for answering, My board for this part has a simple connection as below:

    so all the JTAG Pins are going out without any pull-up or pull-down, the JTAG board is separated and it has all the pull-ups and downs as offered by standard TI designs.

    so this board, once operating Standalone, all the pins are left open, and as I said earlier the boot up is fine mostly, and sometimes it fails in run time after activation of some interrupts within the code...

    so you think the problem is the pull-down on TRST? if that's the case how come the code boots up safely like 80% of the time and fails in the other 20% during the run time after lots of initializations and so on?

    Regards
    John

  • You do need PU resistors on the boot-mode select pins. These pins have an internal PU, but they are weak. Any noise on these pins during power-up could put the device in some other boot-mode. 

    Similarly, the -TRST pin also has a weak internal pull-down. It is highly recommended this is supplemented by an external 2.2K PD. 

    Depending on the noise situation, your board may or may not power-up properly (without the external resistors I suggested). These resistors must be connected to the device pins all the time.

    To isolate the problem between H/W & S/W, please try this experiment: Program a simple GPIO toggling code into flash and see if the poser-up is good every time.

  • Hi Hareesh, 

    Ok, I found time to do your instructions.
    so By pulling UP externally the boot mode pins of GPIO34 and TDO and also by pulling down theTRST at the same time with mentioned 2.2K resistor I can see the boot-loader fails to boot up at all the times ( other configurations are also tested based on the table in the datasheet)

    as I said earlier:

    1- I'm Using DFU-prog and the Boot loader made for it in C2000 as a boot-loader with a USB

    2- My code always fails once it's executing the main code, and it doesn't freeze in the boot-loading stage ( as I explained, by removing the boot-loader fully and making the code stand-alone I still see the issue)

    3- as mentioned, the code fails right after activation of the ECAP interrupts in run-time 

    4- after removing the interrupt nesting the failure goes away, and I have always safe boot up, but Nesting is a must, we tried all the other methods by catching bad interrupts and so on.

    So what's your opinion on this? any possibility of having an issue with the Linker command file?

    Regards
    John

  • By pulling UP externally the boot mode pins of GPIO34 and TDO and also by pulling down theTRST at the same time with mentioned 2.2K resistor I can see the boot-loader fails to boot up at all the times

    So even when the PU & PD resistors are permanently connected to the board, the problem is still seen?

    My code always fails once it's executing the main code, and it doesn't freeze in the boot-loading stage

    I presume your bootloader is always executed and executed first, followed by the main code. Your observation almost certainly points to a S/W issue.

    as mentioned, the code fails right after activation of the ECAP interrupts in run-time

    In your design, are there any pins that are driven before the MCU is fully powered up?

    after removing the interrupt nesting the failure goes away

    Again, this points to an issue in S/W, on which our ability to help is very limited (since we cannot get to know all the nuances in your application code)

    I asked you to try flashing a simple GPIO toggling code. What is the result of that experiment?

    Can you share the waveform of the following signals during power-up and power-down?

    • Case A: 3.3v, 1.8v, -XRS, -TRST
    • Case B: 3.3v, -XRS, the two boot-mode select pins 

    Can you try powering up the board using an external power-supply (bypassing the on-board power supply circuit)?

    Can you share your schematics privately with us?  If yes, a friendship request needs to be initiated. We need to look at the entire schematic (at least every connection to the MCU). A small snippet is not useful.

  • So even when the PU & PD resistors are permanently connected to the board, the problem is still seen?

    Yes

    I presume your bootloader is always executed and executed first, followed by the main code. Your observation almost certainly points to a S/W issue.

    yes, as even by removing the boo-loader, and making the code stand-alone I see this.

    In your design, are there any pins that are driven before the MCU is fully powered up?

    I can't say for sure, there are other ICs connected to the MCU, so they might power up faster...

    I asked you to try flashing a simple GPIO toggling code. What is the result of that experiment?

    that must work, as I said by removing the nesting of interrupts the bug is going away, so something happens when I prioritize the interrupts and ADC interrupt is happening non-preemptively. I can imagine the gpio toggling will work too ...

    for the rest of the tests, I need time to provide the signals, but I'll do it soon.

    Can you share your schematics privately with us?  If yes, a friendship request needs to be initiated.

    sure, I'll send you that.

    Regards
    John

  • John,

    Something to check on the software side.  The compiler defines two types of interrupts - a high-priority (HPI) and low-priority (LPI).  Please check that any interrupt which has nesting enabled is not defined as a high-priority interrupt. 

    You can search the codebase for the term HPI.  A high-priority interrupt will have a one of the specifications shown in this screenshot from www.ti.com/lit/spru514 the compiler user's guide.  An interrupt defined as HPI has a faster context save, but does not allow for nesting. 

    I doubt this is the problem since it should manifest with CCS connected as well.  But it is worth checking for. 

  • Hi Lori, 

    Thanks, yes, I checked and nowhere in our code, the mentioned HPI or LPI assignments are used, so it seems this can not be the issue.

    Regards
    John

  • I can't say for sure, there are other ICs connected to the MCU, so they might power up faster...

    If the MCU pins are driven before the MCU is fully powered up, it could be an issue. Please check all MCU pins before/during powerup to ensure this is not the case.

    Can you share the waveform of the following signals during power-up and power-down?

    • Case A: 3.3v, 1.8v, -XRS, -TRST
    • Case B: 3.3v, -XRS, the two boot-mode select pins 

    Still awaiting the waveforms.