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.

Inverted external interrupts issue

Other Parts Discussed in Thread: LAUNCHXL-F28027, CONTROLSUITE

Hello!

I have C2000 Piccolo LAUNCHXL-F28027 and 4x4 matrix keypad, so I want to connect keypad to the F28027 using GPIO pins but get issue:

I connected my keypad to the J6 pins, after that I changed ExternalInterrupt code sample from the controlSuite and launched this code on the my F28027.

The problem is that I get interrupts all time from the beginning like due to the timer tick(but I don't use timers). And key pressing stops this interrupts but I need the opposite - call xint1_isr and xint2_isr functions ONLY when keys was pressed.

I tried a a lot of the code samples, but all of them gives the same(so you can check just only one of them)!

First sample(changed controlSUITE\device_support\f2802x\v230\f2802x_examples_drivers\external_interrupt):

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/flash.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pie.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/pwr.h"
#include "f2802x_common/include/wdog.h"

// Prototype statements for functions found within this file.
__interrupt void xint1_isr(void);
__interrupt void xint2_isr(void);

CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;

// Global variables for this example
volatile uint32_t Xint1Count;
volatile uint32_t Xint2Count;
uint32_t LoopCount;

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

void main(void)
{
    CPU_Handle myCpu;
    PLL_Handle myPll;
    WDOG_Handle myWDog;

    uint32_t TempX1Count;
    uint32_t TempX2Count;

    // Initialize all the handles needed for this application
    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));
    myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));

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

    //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);

    // If running from flash copy RAM only functions to RAM
#ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

    // Setup a debug vector table and enable the PIE
    PIE_setDebugIntVectorTable(myPie);
    PIE_enable(myPie);

    // Register interrupt handlers in the PIE vector table
    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);

    // Clear the counters
    Xint1Count = 0; // Count XINT1 interrupts
    Xint2Count = 0; // Count XINT2 interrupts
    LoopCount = 0;  // Count times through idle loop

    // Enable XINT1 and XINT2 in the PIE: Group 1 interrupt 4 & 5
    // Enable INT1 which is connected to WAKEINT
    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);

    // Enable Global Interrupts
    CPU_enableGlobalInts(myCpu);




    // GPIO2 - GPIO5 are outputs
    GPIO_setLow(myGpio, GPIO_Number_2);
    GPIO_setMode(myGpio, GPIO_Number_2, GPIO_2_Mode_GeneralPurpose);
    GPIO_setDirection(myGpio, GPIO_Number_2, GPIO_Direction_Output);

    GPIO_setLow(myGpio, GPIO_Number_3);
    GPIO_setMode(myGpio, GPIO_Number_3, GPIO_3_Mode_GeneralPurpose);
    GPIO_setDirection(myGpio, GPIO_Number_3, GPIO_Direction_Output);


    GPIO_setLow(myGpio, GPIO_Number_4);
    GPIO_setMode(myGpio, GPIO_Number_4, GPIO_4_Mode_GeneralPurpose);
    GPIO_setDirection(myGpio, GPIO_Number_4, GPIO_Direction_Output);

    GPIO_setLow(myGpio, GPIO_Number_5);
    GPIO_setMode(myGpio, GPIO_Number_5, GPIO_5_Mode_GeneralPurpose);
    GPIO_setDirection(myGpio, GPIO_Number_5, GPIO_Direction_Output);



    // GPIO0 and GPIO1 are inputs
    GPIO_setMode(myGpio, GPIO_Number_0, GPIO_0_Mode_GeneralPurpose);
    GPIO_setDirection(myGpio, GPIO_Number_0, GPIO_Direction_Input);


    GPIO_setMode(myGpio, GPIO_Number_1, GPIO_1_Mode_GeneralPurpose);
    GPIO_setDirection(myGpio, GPIO_Number_1, GPIO_Direction_Input);

    // GPIO0 is XINT1, GPIO1 is XINT2
    GPIO_setExtInt(myGpio, GPIO_Number_0, CPU_ExtIntNumber_1);
    GPIO_setExtInt(myGpio, GPIO_Number_1, CPU_ExtIntNumber_2);

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

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


    for(;;)
    {
    	asm(" NOP");
    }
}

__interrupt void xint1_isr(void)
{
    Xint1Count++;

    // Acknowledge this interrupt to get more from group 1
    PIE_clearInt(myPie, PIE_GroupNumber_1);
}

__interrupt void xint2_isr(void)
{
    Xint2Count++;

    // Acknowledge this interrupt to get more from group 1
    PIE_clearInt(myPie, PIE_GroupNumber_1);
}

//===========================================================================
// No more.
//===========================================================================

Second sample(changed controlSUITE\device_support\f2802x\v230\f2802x_examples_structs\external_interrupt):

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

// Prototype statements for functions found within this file.
__interrupt void xint1_isr(void);
__interrupt void xint2_isr(void);

// Global variables for this example
volatile uint32_t Xint1Count;
volatile uint32_t Xint2Count;
uint32_t LoopCount;

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

void main(void)
{
   uint32_t TempX1Count;
   uint32_t TempX2Count;

// WARNING: Always ensure you call memcpy before running any functions from RAM
// InitSysCtrl includes a call to a RAM based function and without a call to
// memcpy first, the processor will go "into the weeds"
   #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();  // Skipped for this example

// 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();

// 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 registers
   PieVectTable.XINT1 = &xint1_isr;
   PieVectTable.XINT2 = &xint2_isr;
   EDIS;   // This is needed to disable write to EALLOW protected registers

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

// Step 5. User specific code, enable interrupts:

// Clear the counters
   Xint1Count = 0; // Count XINT1 interrupts
   Xint2Count = 0; // Count XINT2 interrupts
   LoopCount = 0;  // Count times through idle loop

// Enable XINT1 and XINT2 in the PIE: Group 1 interrupt 4 & 5
// Enable INT1 which is connected to WAKEINT:
   PieCtrlRegs.PIECTRL.bit.ENPIE = 1;          // Enable the PIE block
   PieCtrlRegs.PIEIER1.bit.INTx4 = 1;          // Enable PIE Group 1 INT4
   PieCtrlRegs.PIEIER1.bit.INTx5 = 1;          // Enable PIE Group 1 INT5
   IER |= M_INT1;                              // Enable CPU INT1
   EINT;                                       // Enable Global Interrupts

// GPIO28 & GPIO29 are outputs, start GPIO28 high and GPIO29 low
   EALLOW;
   GpioDataRegs.GPACLEAR.bit.GPIO2 = 1;         // Load the output latch
   GpioCtrlRegs.GPAMUX1.bit.GPIO2 = 0;        // GPIO
   GpioCtrlRegs.GPADIR.bit.GPIO2 = 1;         // output

   GpioDataRegs.GPACLEAR.bit.GPIO3 = 1;         // Load the output latch
   GpioCtrlRegs.GPAMUX1.bit.GPIO3 = 0;        // GPIO
   GpioCtrlRegs.GPADIR.bit.GPIO3 = 1;         // output

   GpioDataRegs.GPACLEAR.bit.GPIO4 = 1;         // Load the output latch
   GpioCtrlRegs.GPAMUX1.bit.GPIO4 = 0;        // GPIO
   GpioCtrlRegs.GPADIR.bit.GPIO4 = 1;         // output

   GpioDataRegs.GPACLEAR.bit.GPIO5 = 1;         // Load the output latch
   GpioCtrlRegs.GPAMUX1.bit.GPIO5 = 0;        // GPIO
   GpioCtrlRegs.GPADIR.bit.GPIO5 = 1;         // output

   EDIS;

// GPIO0 and GPIO1 are inputs
   EALLOW;
   GpioCtrlRegs.GPAMUX1.bit.GPIO0 = 0;         // GPIO
   GpioCtrlRegs.GPADIR.bit.GPIO0 = 0;          // input
   GpioCtrlRegs.GPAQSEL1.bit.GPIO0 = 0;        // XINT1 Synch to SYSCLKOUT only

   GpioCtrlRegs.GPAMUX1.bit.GPIO1 = 0;         // GPIO
   GpioCtrlRegs.GPADIR.bit.GPIO1 = 0;          // input
   GpioCtrlRegs.GPAQSEL1.bit.GPIO1 = 2;        // XINT2 Qual using 6 samples
   GpioCtrlRegs.GPACTRL.bit.QUALPRD0 = 0xFF;   // Each sampling window is 510*SYSCLKOUT
   EDIS;

// GPIO0 is XINT1, GPIO1 is XINT2
   EALLOW;
   GpioIntRegs.GPIOXINT1SEL.bit.GPIOSEL = 0;   // XINT1 is GPIO0
   GpioIntRegs.GPIOXINT2SEL.bit.GPIOSEL = 1;   // XINT2 is GPIO1
   EDIS;

// Configure XINT1
   XIntruptRegs.XINT1CR.bit.POLARITY = 0;      // Falling edge interrupt
   XIntruptRegs.XINT2CR.bit.POLARITY = 0;      // Rising edge interrupt

// Enable XINT1 and XINT2
   XIntruptRegs.XINT1CR.bit.ENABLE = 1;        // Enable XINT1
   XIntruptRegs.XINT2CR.bit.ENABLE = 1;        // Enable XINT2

// GPIO34 will go low inside each interrupt.  Monitor this on a scope
   EALLOW;
   GpioCtrlRegs.GPBMUX1.bit.GPIO34 = 0;        // GPIO
   GpioCtrlRegs.GPBDIR.bit.GPIO34 = 1;         // output
   EDIS;

// Step 6. IDLE loop:
   for(;;)
   {
	   asm(" NOP");

      TempX1Count = Xint1Count;
      TempX2Count = Xint2Count;

      // Trigger both XINT1
      GpioDataRegs.GPBSET.bit.GPIO34 = 1;   // GPIO34 is high
      GpioDataRegs.GPACLEAR.bit.GPIO2 = 1; // Lower GPIO28, trigger XINT1
      while(Xint1Count == TempX1Count) {}

      // Trigger both XINT2

      GpioDataRegs.GPBSET.bit.GPIO34 = 1;   // GPIO34 is high
      DELAY_US(DELAY);                      // Wait for Qual period
      GpioDataRegs.GPASET.bit.GPIO3 = 1;   // Raise GPIO29, trigger XINT2
      while(Xint2Count == TempX2Count) {}

      // Check that the counts were incremented properly and get ready
      // to start over.
      if(Xint1Count == TempX1Count+1 && Xint2Count == TempX2Count+1)
      {
          LoopCount++;
          GpioDataRegs.GPASET.bit.GPIO2 = 1;   // raise GPIO28
          GpioDataRegs.GPACLEAR.bit.GPIO3 = 1; // lower GPIO29
      }
      else
      {
          __asm("      ESTOP0"); // stop here
      }
   }
}

// Step 7. Insert all local Interrupt Service Routines (ISRs) and functions here:
// If local ISRs are used, reassign vector addresses in vector table as
// shown in Step 5

__interrupt void xint1_isr(void)
{
	GpioDataRegs.GPBCLEAR.all = 0x4;   // GPIO34 is low
	Xint1Count++;

	// Acknowledge this interrupt to get more from group 1
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

__interrupt void xint2_isr(void)
{
	GpioDataRegs.GPBCLEAR.all = 0x4;   // GPIO34 is low
	Xint2Count++;

	// Acknowledge this interrupt to get more from group 1
	PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;
}

//===========================================================================
// No more.
//===========================================================================

Third sample - changed code from here, it also gives the same.

So how can I get interrupt ONLY when I press the key?

Thanks!

UPD:

#include "DSP28x_Project.h"     // Device Headerfile and Examples Include File

#include "f2802x_common/include/clk.h"
#include "f2802x_common/include/flash.h"
#include "f2802x_common/include/gpio.h"
#include "f2802x_common/include/pie.h"
#include "f2802x_common/include/pll.h"
#include "f2802x_common/include/pwr.h"
#include "f2802x_common/include/wdog.h"

// Prototype statements for functions found within this file.
__interrupt void xint1_isr(void);


CLK_Handle myClk;
FLASH_Handle myFlash;
GPIO_Handle myGpio;
PIE_Handle myPie;

// Global variables for this example
volatile uint32_t Xint1Count;

uint32_t LoopCount;

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

void main(void)
{
    CPU_Handle myCpu;
    PLL_Handle myPll;
    WDOG_Handle myWDog;

    uint32_t TempX1Count;


    // Initialize all the handles needed for this application
    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));
    myWDog = WDOG_init((void *)WDOG_BASE_ADDR, sizeof(WDOG_Obj));

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

    //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);

    // If running from flash copy RAM only functions to RAM
#ifdef _FLASH
    memcpy(&RamfuncsRunStart, &RamfuncsLoadStart, (size_t)&RamfuncsLoadSize);
#endif

    // Setup a debug vector table and enable the PIE
    PIE_setDebugIntVectorTable(myPie);
    PIE_enable(myPie);

    // Register interrupt handlers in the PIE vector table
    PIE_registerPieIntHandler(myPie, PIE_GroupNumber_1, PIE_SubGroupNumber_4,
                              (intVec_t)&xint1_isr);


    // Clear the counters
    Xint1Count = 0; // Count XINT1 interrupts

    LoopCount = 0;  // Count times through idle loop

    PIE_enableInt(myPie, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1);
    CPU_enableInt(myCpu, CPU_IntNumber_1);

    // Enable Global Interrupts
    CPU_enableGlobalInts(myCpu);

    GPIO_setMode(myGpio, GPIO_Number_12, GPIO_12_Mode_GeneralPurpose);

    GPIO_setDirection(myGpio, GPIO_Number_12, GPIO_Direction_Input);

    GPIO_setExtInt(myGpio, GPIO_Number_12, CPU_ExtIntNumber_1);

    PIE_setExtIntPolarity(myPie, CPU_ExtIntNumber_1,
    					  PIE_ExtIntPolarity_RisingEdge);

    PIE_enableExtInt(myPie, CPU_ExtIntNumber_1);

}

__interrupt void xint1_isr(void)
{
    Xint1Count++;

    // Acknowledge this interrupt to get more from group 1
    PIE_clearInt(myPie, PIE_GroupNumber_1);
}



//===========================================================================
// No more.
//===========================================================================

  • Hi,

    First of all did you check with a single button configuration? Pull one end of the button to Vcc through a resistor and the other end to GND.
    Let us know what you observe. Also, if you don't have the provision to do so check/observe the signal fed to external interrupt when any button is pressed on DSO.

    Regards,
    Gautam
  • Ok, I will do everything what I should, but I have some questions:
    1. Exactly which pins on the microcontroller I need to connect with the keypad? J6 pins (which I already used as a GPIO) or J3 (GND and 3V3)?
    2. If the first answer J3, how do I know if it works? Because it does not a signal contact (GND) and information about the incoming voltage will not be received by the microcontroller.
    3. If the first answer J3, then should I just connect 3V3 to the input of the button, and the GND to the output?
    4. What exactly I should to observe?
    5. Which resistance of the resistor I need to use?
    6. DSO means oscilloscope? If so, I will try to measure the voltage of the output. But then again, which pins I need to use for input and which for the output? J6 or J3?
    Sorry for the my scrupulousness, but I just want to do everything right.
    And thanks for the long-term support!
  • Woahh... lot of questions there :)

    Let me make it very simple, there's a switch present S3 connected to GPIO12. Configure GPIO12 as an external interrupt and check the same.
    You can check the schematics of the lauchpad here:
    C:\ti\controlSUITE\development_kits\C2000_LaunchPad\LAUNCHXL-F28027\HwDevPkg

    Regards,
    Gautam
  • Ok, the basis for the all tests was first code with some modifications:
    1. If I configure GPIO12 as an external interrupt(just change number of GPIO) and check it, then the interruption by pressing the button(S3) occurs only once! Then I need to unplug microcontroller from the USB and plug it again to interruption could work again(but only once). Everything else works fine - the problem with the inverted interruption missing in this test.
    2. If I set one interruption for the keypad and one for the GPIO12 (S3), then interruption of button(S3) occurs as in the 1 item(works only once and after this need rebooting) and interruption of keypad works as before in the very first code (inverted interrupts).
    So why I can press the button(S3) only once without rebooting? And what our next step?

  • For the external interrupt sample code you can press multiple times to see the counter increasing. Match your code with the same code available in controlSuite.
  • Ok, at first, today I changed my C2000 on the exactly same C2000 and tested all previous codes - they still doesn't work properly and gives same result.
    At second, as I said in the my previous post I changed "controlSUITE\device_support\f2802x\v230\f2802x_examples_drivers\external_interrupt\Example_2802xExternalInterrupt.c" code. I uploaded this changed code in the my question (it is marked as "UPD:"), if you can, please test this code on the your C2000. I'm sure the problem is very simple, but I just don't have sufficient qualification.

    Problem for this code the same - "If I configure GPIO12 as an external interrupt(just change number of GPIO) and check it, then the interruption by pressing the button(S3) occurs only once! Then I need to unplug microcontroller from the USB and plug it again to interruption could work again(but only once). Everything else works fine - the problem with the inverted interruption missing in this test."

    Please help me! I really don't know what I'm doing wrong.

    Thanks!

  • I'm very confused...the sample code with appropriate GPIO configuration works directly. I'm not sure what wrongs going on here.
  • It is almost impossible to believe that I have solved this problem, but this is true :D.
    Solution to the problem:
    GpioCtrlRegs.GPAPUD.all = 0;
    Anyway thanks for the support!
    And I still have some questions about the keypad and xint, you can check it: e2e.ti.com/.../482857
  • Common! That's understood Kons.
    Also, calling InitGpio() function takes care of the above! This is present in f2802x_gpio.h header file.
    Do check the same. Anyways, I'll check your new thread.

    Regards,
    Gautam
  • I am also facing same problem , please help 

    I have configured the GPIO12 as XINT1, but it works only once after controllers boots up

  • Hi Mahesh,

    You will be more likely to get an answer if you start a new thread, since this one is well over a year old. Please describe the issue you are facing and what debug you have tried. If your issue is similar to the one in this thread, feel free to link to this one in your new thread.