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.

INTERRUPT ISSUE ON TMS320F28069M

Other Parts Discussed in Thread: TMS320F28069, TMS320F28069M, CONTROLSUITE

Hello everybody,

I work with the TMDSHVMTRPFCKIT and the board Piccolo TMS320F28069 controlCARD.

The microcontrollor that i use is the TMS320F28069M for motor control.

I have implemented the TIMER2  (see Interruption Project).

When the TIMER2 = 0 there is an interrupt INT14.

The address vector for this interrupt is 0x00000D1C  (see vector table)

 

My interrupt function is:

 "

// Function Declaration

__interrupt void int_timer2();


# pragma vector = 0x00000D1C

__interrupt void int_timer2()
{
a = 2;
//Prescale /2
 *TIMER2TPR |= (unsigned short)1 << 1;
}

"


When i build my project there is a warning:

"../main.c", line 45: warning #163-D: unrecognized #pragma


and when i debug step by step, the flag INT14 is 1 Ok

but i don't go into my interrupt function int_timer2.

 

Could you help me please,

Thanks.

  • Alexandre,

    There is no "vector" pragma for C28x.  A list of supported pgagmas can be found in section 6.9 on the C Compiled User's Guide:

    http://www.ti.com/lit/ug/spru514j/spru514j.pdf

    To use interrupts you'll need to map each ISR address into the PIE interrupt table, then enable the interrupt.  You can see how this is done in the attached file taken from the adc_soc example in controlSUITE.  Line 76 loads an address in the table, and line 88 enables the respective PIE interrupt.

    There is more information on how to set up and use interrupts in the on-line C2000 1-day workshop.  The relevant section is here:

    https://training.ti.com/c2000-mcu-1-day-workshop-series-5-8-reset-interrupts-and-system-initialization

    Hope this helps.

    Regards,

    Richard

    //###########################################################################
    // Description:
    //! \addtogroup f2806x_example_list
    //! <h1> ADC Start of Conversion (adc_soc)</h1>
    //! 
    //! This ADC example uses ePWM1 to generate a periodic ADC SOC - ADCINT1.
    //! Two channels are converted, ADCINA4 and ADCINA2.
    //! 
    //! \b Watch \b Variables \n
    //! - Voltage1[10]    - Last 10 ADCRESULT0 values
    //! - Voltage2[10]    - Last 10 ADCRESULT1 values
    //! - ConversionCount - Current result number 0-9
    //! - LoopCount       - Idle loop counter
    //
    //
    //###########################################################################
    // $TI Release: F2806x C/C++ Header Files and Peripheral Examples V151 $
    // $Release Date: February  2, 2016 $
    // $Copyright: Copyright (C) 2011-2016 Texas Instruments Incorporated -
    //             http://www.ti.com/ ALL RIGHTS RESERVED $
    //###########################################################################
    
    #include "DSP28x_Project.h"     // Device Headerfile and Examples Include File
    
    // Prototype statements for functions found within this file.
    __interrupt void adc_isr(void);
    void Adc_Config(void);
    
    
    // Global variables used in this example:
    Uint16 LoopCount;
    Uint16 ConversionCount;
    Uint16 Voltage1[10];
    Uint16 Voltage2[10];
    
    
    main()
    {
    
    // Step 1. Initialize System Control:
    // PLL, WatchDog, enable Peripheral Clocks
    // This example function is found in the F2806x_SysCtrl.c file.
       InitSysCtrl();
    
    
    // Step 2. Initialize GPIO:
    // This example function is found in the F2806x_Gpio.c file and
    // illustrates how to set the GPIO to it's default state.
    // InitGpio();  // Skipped for this example
    
    // Step 3. Clear all interrupts and initialize PIE vector table:
    // Disable CPU interrupts
       DINT;
    
    // Initialize the PIE control registers to their default state.
    // The default state is all PIE interrupts disabled and flags
    // are cleared.
    // This function is found in the F2806x_PieCtrl.c file.
       InitPieCtrl();
    
    // Disable CPU interrupts and clear all CPU interrupt flags:
       IER = 0x0000;
       IFR = 0x0000;
    
    // Initialize the PIE vector table with pointers to the shell Interrupt
    // Service Routines (ISR).
    // This will populate the entire table, even if the interrupt
    // is not used in this example.  This is useful for debug purposes.
    // The shell ISR routines are found in F2806x_DefaultIsr.c.
    // This function is found in F2806x_PieVect.c.
       InitPieVectTable();
    
    // Interrupts that are used in this example are re-mapped to
    // ISR functions found within this file.
       EALLOW;  // This is needed to write to EALLOW protected register
       PieVectTable.ADCINT1 = &adc_isr;
       EDIS;    // This is needed to disable write to EALLOW protected registers
    
    // Step 4. Initialize all the Device Peripherals:
    // This function is found in F2806x_InitPeripherals.c
    // InitPeripherals(); // Not required for this example
       InitAdc();  // For this example, init the ADC
       AdcOffsetSelfCal();
    
    // Step 5. User specific code, enable interrupts:
    
    // Enable ADCINT1 in PIE
       PieCtrlRegs.PIEIER1.bit.INTx1 = 1;	// Enable INT 1.1 in the PIE
       IER |= M_INT1; 						// Enable CPU Interrupt 1
       EINT;          						// Enable Global interrupt INTM
       ERTM;          						// Enable Global realtime interrupt DBGM
    
       LoopCount = 0;
       ConversionCount = 0;
    
    // Configure ADC
    	EALLOW;
        AdcRegs.ADCCTL2.bit.ADCNONOVERLAP = 1;	// Enable non-overlap mode
    	AdcRegs.ADCCTL1.bit.INTPULSEPOS	= 1;	// ADCINT1 trips after AdcResults latch
    	AdcRegs.INTSEL1N2.bit.INT1E     = 1;	// Enabled ADCINT1
    	AdcRegs.INTSEL1N2.bit.INT1CONT  = 0;	// Disable ADCINT1 Continuous mode
        AdcRegs.INTSEL1N2.bit.INT1SEL 	= 1;    // setup EOC1 to trigger ADCINT1 to fire
        AdcRegs.ADCSOC0CTL.bit.CHSEL 	= 4;    // set SOC0 channel select to ADCINA4
        AdcRegs.ADCSOC1CTL.bit.CHSEL 	= 2;    // set SOC1 channel select to ADCINA2
        AdcRegs.ADCSOC0CTL.bit.TRIGSEL 	= 5;    // set SOC0 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
        AdcRegs.ADCSOC1CTL.bit.TRIGSEL 	= 5;    // set SOC1 start trigger on EPWM1A, due to round-robin SOC0 converts first then SOC1
    	AdcRegs.ADCSOC0CTL.bit.ACQPS 	= 6;	// set SOC0 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    	AdcRegs.ADCSOC1CTL.bit.ACQPS 	= 6;	// set SOC1 S/H Window to 7 ADC Clock Cycles, (6 ACQPS plus 1)
    	EDIS;
    
    // Assumes ePWM1 clock is already enabled in InitSysCtrl();
       EPwm1Regs.ETSEL.bit.SOCAEN	= 1;		// Enable SOC on A group
       EPwm1Regs.ETSEL.bit.SOCASEL	= 4;		// Select SOC from CMPA on upcount
       EPwm1Regs.ETPS.bit.SOCAPRD 	= 1;		// Generate pulse on 1st event
       EPwm1Regs.CMPA.half.CMPA 	= 0x0080;	// Set compare A value
       EPwm1Regs.TBPRD 				= 0xFFFF;	// Set period for ePWM1
       EPwm1Regs.TBCTL.bit.CTRMODE 	= 0;		// count up and start
    
    // Wait for ADC interrupt
       for(;;)
       {
          LoopCount++;
       }
    
    }
    
    
    __interrupt void  adc_isr(void)
    {
    
      Voltage1[ConversionCount] = AdcResult.ADCRESULT0;
      Voltage2[ConversionCount] = AdcResult.ADCRESULT1;
    
      // If 20 conversions have been logged, start over
      if(ConversionCount == 9)
      {
         ConversionCount = 0;
      }
      else ConversionCount++;
    
      AdcRegs.ADCINTFLGCLR.bit.ADCINT1 = 1;		//Clear ADCINT1 flag reinitialize for next SOC
      PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE
    
      return;
    }
    
    
    

  • Richard,

    Thank you very much for your answer.

    But when I try to use "PieVectorTable", it's an unknown variable.

    Where can I find it? How to define it?

    Because all of my interrupt program (for INT14 <=> CPU-TIMER2) is well configured. But when I debug it, even if the interrupt flag for INT14 is enable at the end of my countdown, instructions in the interrupt function are not executed.

    This is my program if it can help you to find a solution:

    START OF THE PROGRAM

    #include <STDIO.H>

    //******************************************************************************
    // PIE, Control Register
    unsigned short *PIECTRL = (unsigned short *)0x00000CE0;
    // PIE, Acknowledge Register
    unsigned short *PIEACK = (unsigned short *)0x00000CE1;
    //PIE, INT1 Group Enable Register
    unsigned short *PIEIER1 = (unsigned short *)0x00000CE2;
    //PIE, INT1 Group Flag Register
    unsigned short *PIEIFR1 = (unsigned short *)0x00000CE3;

    //! \brief External reference to the interrupt flag register (IFR) register
    extern cregister volatile unsigned int IFR;
    //! \brief External reference to the interrupt enable register (IER) register
    extern cregister volatile unsigned int IER;

    // CPU-Timer 2, Counter Register
    unsigned short *TIMER2TIM = (unsigned short *)0x00000C10;
    // CPU-Timer 2, Counter Register
    unsigned short *TIMER2TIMH = (unsigned short *)0x00000C11;
    // CPU-Timer 2, Period Register
    unsigned short *TIMER2PRD = (unsigned short *)0x00000C12;
    // CPU-Timer 2, Period Register
    unsigned short *TIMER2PRDH = (unsigned short *)0x00000C13;
    // CPU-Timer 2, Control Register
    unsigned short *TIMER2TCR = (unsigned short *)0x00000C14;
    // CPU-Timer 2, Prescale
    unsigned short *TIMER2TPR = (unsigned short *)0x00000C16;
    // CPU-Timer 2, Prescale
    unsigned short *TIMER2TPRH = (unsigned short *)0x00000C17;
    // Peripheral Clock Control Register 3
    unsigned short *PCLKCR3 = (unsigned short *)0x0007020;

    // \brief Define to allow protected register writes
    #define ENABLE_PROTECTED_REGISTER_WRITE_MODE asm(" EALLOW")
    // \brief Define to disable protected register writes
    #define DISABLE_PROTECTED_REGISTER_WRITE_MODE asm(" EDIS")
    *********************************************************************************
    int main(void)
    {
    a = 0;

    ENABLE_PROTECTED_REGISTER_WRITE_MODE;
    //Prescale /8
    *TIMER2TPR |= ((unsigned short)1 << 3);
    //Period 8
    *TIMER2PRD = (unsigned short)0x0008;
    //Load period
    *TIMER2TCR |= ((unsigned short)1 << 5);

    // Enable INT14 Timer 2
    IER |= ((unsigned short)1 << 13);

    DISABLE_PROTECTED_REGISTER_WRITE_MODE;
    while (1);
    }

    interrupt void int_timer2(void)
    {
    *TIMER2TPR |= (unsigned short)1 << 0;
    return;
    }


    END OF THE PROGRAM

    Thank you again Richard.
  • Hi Alexandre,

    "PieVectorTable" is a structure defined in the peripheral header files for this device.

    I strongly recommend basing your program on the peripheral header file structures.  You can write the register definitions yourself, but it's a lot of work and you'll be finding all kinds of issues along the way.  It's a million times easier to use the header files and examples as the starting point.  If you have already downloaded controlSUITE to the default location on your machine, you'll find example projects for the F28069 device at:

    C:\ti\controlSUITE\device_support\f2806x\v151\F2806x_examples_ccsv5

    If you open and run (for example) the "cpu_timer" example it shows how to configure and use the three CPU timers to generate interrupts, as you have done in you code.  I think this is much the best way.  Please post back if you run into any difficulties with that.

    Regards,

    Richard