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.

Compiler/TMS320F28027F: INTERRUPT AND TIMER C28x

Part Number: TMS320F28027F
Other Parts Discussed in Thread: LAUNCHXL-F28027F, C2000WARE

Tool/software: TI C/C++ Compiler

I am  using 2 external interrupts to find distance covered by an encoder and a timer at 40 hertz which runs pid to maintain some constant velocity . It doesn't respond if thr input is more than a certain velocity. 
    CPU_enableInt(myCpu, CPU_IntNumber_1) is used by both interrupts and timer . Can that be an issue?

here is the outline of the code-


#include "DSP28x_Project.h"


#include "common/include/adc.h"
#include "common/include/clk.h"
#include "common/include/flash.h"
#include "common/include/gpio.h"
#include "common/include/pie.h"
#include "common/include/pll.h"
#include "common/include/cap.h"
#include "common/include/wdog.h"
#include "common/include/timer.h"
#include "IQmathLib.h"

#define RANGE_SPEED 2500

//
__interrupt void xint1_isr(void);
__interrupt void xint2_isr(void);
__interrupt void cpu_timer0_isr(void);

//
// Function Prototypes
//
void scia_echoback_init(void);
void scia_fifo_init(void);
void scia_xmit(int a);
void scia_msg(char *msg);
uint16_t direction = 0;
unsigned long CMD;
float asd;

ADC_Handle myAdc;
CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;
TIMER_Handle myTimer;

//
// Globals
//

Uint16 ReceivedChar=0;
uint32_t pwmdata=0,pwm1=0;

#define DELAY (CPU_RATE/1000*6*510) //Qual period at 6 samples


volatile signed short lookup = 0; ///<find encoder direction
signed long iAngle = 0,StartAngle=0, AngleTravelled=0,TotalAngle=0,PreviAngle=0,Speed=0,targetangle=0; ///<curent position wrt initial position
int Acceleration=2;
uint16_t gpiodata1,gpiodata2;
unsigned char ab = 0; ///<read encoder pins
unsigned char pidflag=0,flag=1;
//float kp,ki,kd,previousvalue;
//int MAX_SPEED=100;
int32_t sumerror,differror,error,previouserror;
signed long MAX_SPEED=0,PREV_MAX_SPEED=0,savediangle,savedpreviangle,SpeedActual=0,up;
static signed long counter=0;
float pidpwm;


typedef struct { _iq Cmd; // Input: Reference input
_iq Fbk; // Input: Feedback input
_iq Err; // Variable: Error
_iq Kp; // Parameter: Proportional gain
_iq Up; // Variable: Proportional output
_iq Ui; // Variable: Integral output
_iq Ud; // Variable: Derivative output
_iq OutPreSat; // Variable: Pre-saturated output
_iq OutMax; // Parameter: Maximum output
_iq OutMin; // Parameter: Minimum output
_iq Out; // Output: PID output
_iq SatErr; // Variable: Saturated difference
_iq Ki; // Parameter: Integral gain
_iq Kc; // Parameter: Integral correction gain
_iq Kd; // Parameter: Derivative gain
_iq Up1; // History: Previous proportional output
} PIDREG3;

typedef PIDREG3 *PIDREG3_handle;

#define PIDREG3_DEFAULTS { 0, \
0, \
0, \
_IQ(0.2), \
0, \
0, \
0, \
0, \
_IQ(+1000), \
_IQ(-1000), \
0, \
0, \
_IQ(0.0), \
_IQ(0.0), \
_IQ(0.0), \
0, \
}

PIDREG3 Motor = PIDREG3_DEFAULTS;

//
// Main
//
CAP_Handle myCap;


void main(void)
{

char *msg;

CPU_Handle myCpu;
PLL_Handle myPll;
WDOG_Handle myWDog;

//
// Initialize all the handles needed for this application
//
myAdc = ADC_init((void *)ADC_BASE_ADDR, sizeof(ADC_Obj));
myClk = CLK_init((void *)CLK_BASE_ADDR, sizeof(CLK_Obj));
myCpu = CPU_init((void *)NULL, sizeof(CPU_Obj));
myFlash = FLASH_init((void *)FLASH_BASE_ADDR, sizeof(FLASH_Obj));
myGpio = GPIO_init((void *)GPIO_BASE_ADDR, sizeof(GPIO_Obj));
myPie = PIE_init((void *)PIE_BASE_ADDR, sizeof(PIE_Obj));
myPll = PLL_init((void *)PLL_BASE_ADDR, sizeof(PLL_Obj));
myCap = CAP_init((void *)CAPA_BASE_ADDR, sizeof(CAP_Obj));
myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));
myTimer = TIMER_init((void *)TIMER0_BASE_ADDR, sizeof(TIMER_Obj));

//
// Perform basic system initialization
//
WDOG_disable(myWDog);
CLK_enableAdcClock(myClk);
(*Device_cal)();
// CLK_disableAdcClock(myClk);

//
// Select the internal oscillator 1 as the clock source
// //
CLK_setOscSrc(myClk, CLK_OscSrc_Internal);

//
// Setup the PLL for x10 /2 which will yield 50Mhz = 10Mhz * 10 / 2
//
PLL_setup(myPll, PLL_Multiplier_10, PLL_DivideSelect_ClkIn_by_2);

//
// Disable the PIE and all interrupts
//
PIE_disable(myPie);
PIE_disableAllInts(myPie);
CPU_disableGlobalInts(myCpu);
CPU_clearIntFlags(myCpu);

//
#ifdef _FLASH
memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

//
// Step 1. Initialize System Control:
// PLL, WatchDog, enable Peripheral Clocks
// This example function is found in the f2802x_SysCtrl.c file.


//
InitSysCtrl();

//
// Step 2. Initialize GPIO:
// This example function is found in the f2802x_Gpio.c file and
// illustrates how to set the GPIO to it's default state.
//
InitGpio();
//
// For this example, only init the pins for the SCI-A port.
// This function is found in the f2802x_Sci.c file.
//
InitSciaGpio();

//
// Step 3. Clear all interrupts and initialize PIE vector table:
// Disable CPU interrupts
//
DINT;

//
// Initialize 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 f2802x_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 f2802x_DefaultIsr.c.
// This function is found in f2802x_PieVect.c.
//
InitPieVectTable();

EnableInterrupts();

//
// Step 4. Initialize all the Device Peripherals
// Not required for this example
//

//
// Step 5. User specific code
//
InitCpuTimers();


GPIO_setPullUp(myGpio, GPIO_Number_19, GPIO_PullUp_Enable);
GPIO_setQualification(myGpio, GPIO_Number_19, GPIO_Qual_Sync);
GPIO_setMode(myGpio, GPIO_Number_19, GPIO_19_Mode_ECAP1);
GPIO_setMode(myGpio, GPIO_Number_34, GPIO_34_Mode_GeneralPurpose);
GPIO_setDirection(myGpio, GPIO_Number_34, GPIO_Direction_Output);
GPIO_setPullUp(myGpio,GPIO_Number_34 , GPIO_PullUp_Enable);
PIE_setDebugIntVectorTable(myPie);
PIE_enable(myPie);
CLK_enableEcap1Clock(myClk);
CAP_setModeApwm(myCap); // Enable APWM mode
CAP_setApwmPeriod(myCap, 0x9C4); // Set Period value
// CAP_setApwmCompare(myCap,0x4E2); // Set Compare value
CAP_clearInt(myCap, CAP_Int_Type_All); // Clear pending interrupts
CAP_enableInt(myCap, CAP_Int_Type_CTR_CMP); // enable Compare Equal Int

// scia_fifo_init(); // Initialize the SCI FIFO
// scia_echoback_init(); // Initialize SCI for echoback

//
// Start counters
//
CAP_enableTimestampCounter(myCap);
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_7,
(intVec_t)&cpu_timer0_isr);

//
// Configure CPU-Timer 0 to interrupt every 500 milliseconds:
// 60MHz CPU Freq, 50 millisecond Period (in uSeconds)
//
//ConfigCpuTimer(&CpuTimer0, 60, 500000);
//
TIMER_stop(myTimer);
TIMER_setPeriod(myTimer, 1250000);
TIMER_setPreScaler(myTimer, 0);
TIMER_reload(myTimer);
TIMER_setEmulationMode(myTimer,
TIMER_EmulationMode_StopAfterNextDecrement);
TIMER_enableInt(myTimer);

TIMER_start(myTimer);


//
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_4,
(intVec_t)&xint1_isr);
PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_5,
(intVec_t)&xint2_isr);


PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1);
PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_2);
CPU_enableInt(myCpu, CPU_IntNumber_1);
//
PIE_enableTimer0Int(myPie);
//
// Enable Global Interrupts
//
CPU_enableGlobalInts(myCpu);
// CPU_enableDebugInt(myCpu);
//
// GPIO0 and GPIO1 are inputs
//
GPIO_setMode(myGpio, GPIO_Number_6, GPIO_6_Mode_GeneralPurpose);
GPIO_setDirection(myGpio, GPIO_Number_6, GPIO_Direction_Input);
GPIO_setQualification(myGpio, GPIO_Number_6, GPIO_Qual_Sample_3);

GPIO_setMode(myGpio, GPIO_Number_7, GPIO_7_Mode_GeneralPurpose);
GPIO_setDirection(myGpio, GPIO_Number_7, GPIO_Direction_Input);
GPIO_setQualification(myGpio, GPIO_Number_7, GPIO_Qual_Sample_3);
GPIO_setQualificationPeriod(myGpio, GPIO_Number_7, 0x80);
GPIO_setQualificationPeriod(myGpio, GPIO_Number_6, 0x80);

//
// GPIO0 is XINT1, GPIO1 is XINT2
//
GPIO_setExtInt(myGpio, GPIO_Number_6, CPU_ExtIntNumber_1);
GPIO_setExtInt(myGpio, GPIO_Number_7, CPU_ExtIntNumber_2);

//
// Configure XINT1
//
PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_1,
PIE_ExtIntPolarity_RisingAndFallingEdge);
PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_2,
PIE_ExtIntPolarity_RisingAndFallingEdge);

//
// Enable XINT1 and XINT2
//
PIE_enableExtInt(myPie, CPU_ExtIntNumber_1);
PIE_enableExtInt(myPie, CPU_ExtIntNumber_2);


msg = "\r\n\n\nHello World!\0";
scia_msg(msg);

msg = "\r\nYou will enter a character, and the DSP will echo it back!\n\0";
scia_msg(msg);

for(;;)
{

//
// Wait for inc character
//
while(SciaRegs.SCIFFRX.bit.RXFFST !=1)
{


// main calculation
}
}

//
// scia_echoback_init - Test 1,SCIA DLB, 8-bit word, baud rate 0x000F, default
// 1 STOP bit, no parity
//
void
scia_echoback_init()
{
//
// Note: Clocks were turned on to the SCIA peripheral
// in the InitSysCtrl() function
//

//
// 1 stop bit, No loopback, No parity, 8 char bits, async mode,
// idle-line protocol
//
SciaRegs.SCICCR.all =0x0007;

//
// enable TX, RX, internal SCICLK, Disable RX ERR, SLEEP, TXWAKE
//
SciaRegs.SCICTL1.all =0x0003;
SciaRegs.SCICTL2.all =0x0003;
SciaRegs.SCICTL2.bit.TXINTENA =1;
SciaRegs.SCICTL2.bit.RXBKINTENA =1;

//
// SCI BRR = LSPCLK/(SCI BAUDx8) - 1
//
#if (CPU_FRQ_60MHZ)
SciaRegs.SCIHBAUD = 0x0000; // 9600 baud @LSPCLK = 15MHz(60 MHz SYSCLK)
SciaRegs.SCILBAUD = 0x00C2;
#elif (CPU_FRQ_50MHZ)
SciaRegs.SCIHBAUD = 0x0000; // 9600 baud @LSPCLK = 12.5 MHz(50 MHz SYSCLK)
SciaRegs.SCILBAUD = 0x00A1;
#elif (CPU_FRQ_40MHZ)
SciaRegs.SCIHBAUD = 0x0000; // 9600 baud @LSPCLK = 10MHz(40 MHz SYSCLK)
SciaRegs.SCILBAUD = 0x0081;
#endif
SciaRegs.SCICTL1.all =0x0023; // Relinquish SCI from Reset
}

//
// scia_xmit - Transmit a character from the SCI
//
void
scia_xmit(int a)
{
while (SciaRegs.SCIFFTX.bit.TXFFST != 0)
{

}
SciaRegs.SCITXBUF=a;
}

//
// scia_msg -
//
void
scia_msg(char * msg)
{
int i;
i = 0;
while(msg[i] != '\0')
{
scia_xmit(msg[i]);
i++;
}
}

//
// scia_fifo_init - Initialize the SCI FIFO
//
void
scia_fifo_init()
{
SciaRegs.SCIFFTX.all=0xE040;
SciaRegs.SCIFFRX.all=0x2044;
SciaRegs.SCIFFCT.all=0x0;
}

//
// xint1_isr -
//
__interrupt void
xint1_isr(void)
{

}

//
// xint2_isr -
//
__interrupt void
xint2_isr(void)
{

}

__interrupt void
cpu_timer0_isr(void)
{

}


//
// End of File
//

  • Part Number: LAUNCHXL-F28027F

    Tool/software: TI C/C++ Compiler

    When motor is moving at a higher velocity, it just get stuck at that interrupt and doesn't execute timer inerrupt. Is there any way to solve this or make timer interrupts at higher priority than external interrupt. Timer interrupt is set at CPU_IntNumber_3 while external interrupts are at CPU_IntNumber_1.

  • Sarthak,
    Thanks for reaching out to the C2000 E2E forums. I'm looking at the code presently, in the meantime I wanted to ask more on your application. You mention that you are using to XINTs to track an encoder input; have you considered the QEP inputs, since this would handed encoder input in HW? This would be alot less CPU intensive, if the inputs support your encoder interface.

    An alternative would be to use the eCAP module to create a timestamp between the encoder pulses that you could then just use in your control function. This would still be less MIPs than the XINT method, where CPU has to service multiple ISRs.


    Matt
  • QEPs are unfortunately not configured for F28027F. Can you gove some more idea about the Ecap module method?
  • Sarthak,

    You're right, no QEP on F28027 sorry about that!  Yes, the eCAP has 4 "capture" registers that basically will time stamp when the eCAP pin state changes(configurable for rising/falling or both).  There are modes that will also capture the "delta" between these values automatically (as well as absolute).  The timer is based off the main CPU clock, but has a fair amount of prescaling depending on what you need.

    There is a basic example here: C:\ti\c2000\C2000Ware_1_00_03_00\device_support\f2802x\examples\drivers\ecap_capture_pwm  that uses a looped back PWM as the source for the capture.

    Link to eCAP UG

    Best,

    Matthew