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.

Not able to call a function inside the gpio interrupt callback function

Part Number: CC3235S

Hi TI, 

I am facing an issue in my program where i am typing to call a function inside the gpio interrupt callback function. i can set/clear a boolean flag inside gpio  callback function whenever interrupt comes. but whenever I am trying to call a function, my program is getting crashed.

This one is working well

*
 *  ======== gpiointerrupt.c ========
 */
#include <stdint.h>
#include <stddef.h>
#include <stdbool.h>
#include <string.h>
#include "MFRC522.h"
/* Driver Header files */
#include <ti/drivers/GPIO.h>
#include <ti/drivers/SPI.h>

/* Driver configuration */
#include "ti_drivers_config.h"

SPI_Params spiParams;
byte status;

volatile bool bNewInt = false;
byte regVal = 0x7F;

static void spi_Initializer(void);
static void rf_Detector(void);

uint8_t myKeyId[]={0xb0,0xaa,0xe6,0x25,'\0'};

/*
 *  ======== transferCompleteFxn ========
 *  Callback function for SPI_transfer().
 */
static void transferCompleteFxn(SPI_Handle handle, SPI_Transaction *transaction)
{
    sem_post(&masterSem);
}


static void spi_Initializer()
{
    /* Open SPI as master (default)*/
    SPI_Params_init(&spiParams);
    spiParams.dataSize = 8;
    spiParams.frameFormat = SPI_POL1_PHA1;
    spiParams.bitRate = 8000000;   //8MHz
    spiParams.transferMode = SPI_MODE_CALLBACK;
    spiParams.transferCallbackFxn = transferCompleteFxn;
//    spiParams.transferCallbackFxn = NULL;
    spiParams.mode = SPI_MASTER;

    masterSpi = SPI_open(CONFIG_SPI_0, &spiParams);

    if (masterSpi == NULL)
    {
        Display_printf(display, 0, 0, "Error initializing master SPI\n");
        while (1)
            ;
    }
    else
    {
        Display_printf(display, 0, 0, "Master SPI initialized\n");
    }
}

/*
 *  ======== gpioButtonFxn0 ========
 *  Callback function for the GPIO interrupt on CONFIG_GPIO_BUTTON_0.
 */
void gpioButtonFxn0(uint_least8_t index)
{
    /* Clear the GPIO interrupt and toggle an LED */
//    GPIO_disableInt(RF_IRQ_PIN);
//    GPIO_clearInt(RF_IRQ_PIN);
//    rf_Detector();
    bNewInt = true;
}

/*
 *  ======== mainThread ========
 */
void *mainThread(void *arg0)
{
    /* Call driver init functions */
    GPIO_init();
    SPI_init();

    Display_Params params;
    Display_Params_init(&params);

    display = Display_open(Display_Type_UART, &params);
    if (display == NULL )
    {
            /* Failed to open a display */
            while (1);
    }
    else
    {
        Display_printf(display, 0, 0, "Hello Serial!");
    }

    status = sem_init(&masterSem, 0, 0);
    if (status != 0)
    {
        while (1)
            ;
    }

    spi_Initializer();

    MFRC522_PCD_Init(); /* reset MFRC522 or wake up from powerDown */

    /* read and printout the MFRC522 version (valid values 0x91 & 0x92)*/
    byte readReg = PCD_ReadRegister(VersionReg);
    Display_printf(display, 0, 0, "Ver : 0x%x",readReg);

    /* Enable interrupts */
    GPIO_enableInt(RF_IRQ_PIN);

    /*
    * Allow the ... irq to be propagated to the IRQ pin
    * For test purposes propagate the IdleIrq and loAlert
    */
    regVal = 0xA0; //rx irq
    PCD_WriteRegister(ComIEnReg, regVal);

    bNewInt = false; //interrupt flag

    do { //clear a spourious interrupt at start
        ;
      } while (bNewInt);
      bNewInt = false;

      Display_printf(display, 0, 0, "End setup!");


    /* Configure the LED and button pins */
//    GPIO_setConfig(CONFIG_GPIO_LED_0, GPIO_CFG_OUT_STD | GPIO_CFG_OUT_LOW);
//    GPIO_setConfig(CONFIG_GPIO_BUTTON_0, GPIO_CFG_IN_PU | GPIO_CFG_IN_INT_FALLING);

    /* Turn on user LED */
//    GPIO_write(CONFIG_GPIO_LED_0, CONFIG_GPIO_LED_ON);

    /* install Button callback */
    GPIO_setCallback(RF_IRQ_PIN, gpioButtonFxn0);

   while(1)
   {
       if (bNewInt)  //new read interrupt
       {
           GPIO_disableInt(RF_IRQ_PIN);
           GPIO_clearInt(RF_IRQ_PIN);
           Display_printf(display, 0, 0," ****************** Interrupt **************** ");
           PICC_ReadCardSerial(); //read the tag data
           Display_printf(display, 0, 0,"Card UID:");// Show some details of the PICC (that is: the tag/card)
           if(dump_byte_array(uid.uidByte, uid.size))
           {
               Display_printf(display, 0, 0,"ID matched!");
           }
           else
           {
               Display_printf(display, 0, 0,"ID Mis Matched!");
           }
           clearInt();
           PICC_HaltA();
           bNewInt = false;
           GPIO_enableInt(RF_IRQ_PIN);
         }
       else
       {
           Display_printf(display, 0, 0,".");
       }
       activateRec();
       usleep(500000);
   }
//    return (NULL);
}

/*
 * The function sending to the MFRC522 the needed commands to activate the reception
 */
void activateRec() {
  PCD_WriteRegister(FIFODataReg, PICC_CMD_REQA);
  PCD_WriteRegister(CommandReg, PCD_Transceive);
  PCD_WriteRegister(BitFramingReg, 0x87);
}

/*
 * The function to clear the pending interrupt bits after interrupt serving routine
 */
void clearInt() {
  PCD_WriteRegister(ComIrqReg, 0x7F);
}

/**
 * Helper routine to dump a byte array as hex values to Serial.
 */
extern bool dump_byte_array(byte *buffer, byte bufferSize)
{
    byte i = 0;
    for (i = 0; i < bufferSize; i++)
    {
        Display_printf(display, 0, 0, "0x%x ", buffer[i]);
    }

     if(!strcmp((char*) buffer, (char*) myKeyId))
     {
         return 1;
     }
     else
     {
         return 0;
     }

}

static void rf_Detector()
{
    GPIO_disableInt(RF_IRQ_PIN);
    GPIO_clearInt(RF_IRQ_PIN);
//    Display_printf(display, 0, 0," ****************** Interrupt **************** ");
    PICC_ReadCardSerial(); //read the tag data
//    Display_printf(display, 0, 0,"Card UID:");// Show some details of the PICC (that is: the tag/card)
    if(dump_byte_array(uid.uidByte, uid.size))
    {
        Display_printf(display, 0, 0,"ID matched!");
    }
    else
    {
        Display_printf(display, 0, 0,"ID Mis Matched!");
    }
    clearInt();
    PICC_HaltA();
    bNewInt = false;
    GPIO_enableInt(RF_IRQ_PIN);
}

but that is also polling only. i want to stop my main loop task, whenever interrupt comes, it should go inside interrupt function and perform rfid authentication task, once it is done come back to the main loop task.

so, for that i have to call authentication whenever interrupt comes. for that i changed my  gpioButtonFxn0. 

/*
 *  ======== gpioButtonFxn0 ========
 *  Callback function for the GPIO interrupt on CONFIG_GPIO_BUTTON_0.
 */
void gpioButtonFxn0(uint_least8_t index)
{
    /* Clear the GPIO interrupt and toggle an LED */
//    GPIO_disableInt(RF_IRQ_PIN);
//    GPIO_clearInt(RF_IRQ_PIN);
    rf_Detector();
//    bNewInt = true;
}

but it crashing in 

static void rf_Detector()
{
    GPIO_disableInt(RF_IRQ_PIN);
    GPIO_clearInt(RF_IRQ_PIN);
//    Display_printf(display, 0, 0," ****************** Interrupt **************** ");
    PICC_ReadCardSerial(); //read the tag data
//    Display_printf(display, 0, 0,"Card UID:");// Show some details of the PICC (that is: the tag/card)
    if(dump_byte_array(uid.uidByte, uid.size))
    {
        Display_printf(display, 0, 0,"ID matched!");
    }
    else
    {
        Display_printf(display, 0, 0,"ID Mis Matched!");
    }
    clearInt();
    PICC_HaltA();
    bNewInt = false;
    GPIO_enableInt(RF_IRQ_PIN);
}

my rfid (MFRC522) is connected over spi. 

To find out the reason of crashing, i started the tracing of the code by putting breakpoints and debug the code. what i find out it is crashing in 

 sem_wait(&masterSem);

of spi transfer function

extern uint8_t spi_transfer(uint8_t add)
{
    uint8_t returnData;

    masterTxBuffer[0] = add;
//    masterTxBuffer[1] = 0x01;

    memset((void*) masterRxBuffer, '\0', sizeof(masterRxBuffer));
    trans.count = 1;
    trans.txBuf = (void*) masterTxBuffer;
    trans.rxBuf = (void*) masterRxBuffer;

//    GPIO_write(SPI_CS, 0);

    /* Perform SPI transfer */
    transferOK = SPI_transfer(masterSpi, &trans);
    if (!transferOK)
    {
        Display_printf(display, 0, 0, "Unsuccessful SPI transfer\n");
        while (1)
            ;
    }
    else
    {
        /* Wait until transfer has completed */
        sem_wait(&masterSem);
    }

    returnData = masterRxBuffer[0];
//    GPIO_write(SPI_CS, 1);
//    sleep(0.5);
    return returnData;
}

please do let me know where is the issue, or how can i execute rfid authentication function whenever tag detection interrupt comes at gpio interrupt callback function.

thanks in advance.

sarju bhatnagar

  • There are some operations (such as sem_wait) that cannot be done within an interrupt context.

    Since you are already using an OS you can use a high priority thread (i.e. with priority that is higher than your main thread) that will get triggered from the interrupt context to run the rf_Detetctor().

    e.g. assuming you use a global gpioSem (that is initialized in advance, i.e. at boot).

    GpioTask()

    {

        while(1)

        {

             sem_wait(&gpioSem);

             ...

             rf_Detector();

        }

    }

    GpioIntHandler()

    {

         sem_post(&gpioSem); 

    }