Cannot get my Interrupt Handler to fire or be called

Tip / Sign in to post questions, reply, level up, and achieve exciting badges. Know more

cross mob
Anonymous
Not applicable

I am trying to simply configure P2 as an external. rising edge interrupt.  I currently have it connected to a simple switch that transitions from high to low.  I have verified that my port mapping is correct by a simple debug loop that outputs traces on the HCI_UART to indicate the state of the pin.  When I run this loop in create(), the correct input state is read via gpio_getPinInput(), this verifies that I have the right pin, and the change in state can be detected.

I have read the following:

How to Write WICED Smart Applications

--> Followed the example code int he GPIO section  - can't get my ISR to run

Re: Wiced Smart Software Runtime -- Lots of Questions

--> As this thread suggested, I tried registering my interrupt callback (ISR) before the bleprofile_Init() call in create(), did not work

interrupt latency

--> This has some interesting points about interrupt priority and such but nothing I can see that can explain what's happening.

Re: how to identify GPIO interrupt source pin?

--> Again, interesting, and this post makes it seem doable, but again, this did not help solve my problem

What I tried, was to check the state of that pin, P2 (PORT 0, PIN 2), using gpio_getPinInput() in the 1 second timer tick.  In that function, regardless the state of my switch controlling the logic level on that pin, the pin is reported as low.   This suggests that perhaps the input is not coming through when I want it to?


I have a trace debug statement in my ISR that would tell me when it is called, and it is NEVER called, regardless how many times I flip the switch.   My code is below, I'm sure I'm doing something wrong, just can't seem to figure out what it is since all the docs and threads make this sound so easy but I can't get it to work at all.


    // dump the database to debug uart.

    legattdb_dumpDb();

    // As per some readings online, it is recommended that you register your interrupt handlers before you call bleprofile_Init()

        UINT16 interrupt_handler_mask[3] = {0, 0, 0};

        interrupt_handler_mask[IRQ_PORT] |= (1 << IRQ_PIN); //IRQ_PORT = 0, IRQ_PIN=2

      // Now register the interrupt handler.

        gpio_registerForInterrupt(interrupt_handler_mask, application_gpio_interrupt_handler, NULL);

        gpio_configurePin(AMS3911_IRQ_PORT, IRQ_PIN,GPIO_INPUT_ENABLE|GPIO_PULL_DOWN|GPIO_EN_INT_RISING_EDGE,GPIO_PIN_OUTPUT_LOW);

      // Clear out any spurious interrupt status..

        gpio_clearPinInterruptStatus(IRQ_PORT, IRQ_PIN);

    bleprofile_Init(bleprofile_p_cfg);

    bleprofile_GPIOInit(bleprofile_gpio_p_cfg);

    // Initialized ROM code which will monitor the battery

    blebat_Init();

...

....

....

// Thread context interrupt handler.

void application_gpio_interrupt_handler(void *parameter, UINT8 data)

{

ble_trace0("******** Interrupt Detected*******\n");

    UINT8 iregs[3] = {0,0,0};

    u32 irqStatus;

    BYTE gpio_level = gpio_getPinInput(IRQ_PORT, IRQ_PIN);

    do

    {

     cfa_kickWatchdog();

//DO STUFF TO READ REGISTERS OF A SPI CONNECTED PERIPHERAL

gpio_level = gpio_getPinInput(IRQ_PORT, IRQ_PIN);

    } while(gpio_level); /* PIC24 irq is edge triggered, sometimes there is no edge but still an interrupt */

}



0 Likes
1 Solution
Anonymous
Not applicable

Hi Everyone,

So, I figured it out: It turned out I had a gpio_init() call in some function that was called to set up the SPI communication.  Calling gpio_init() causes all the GPIO settings to reset, so once I scoured the code for this call and removed it, it started to work!    I guess this function is not really meant to be called by the developer.

BAD gpio_init()!  BAD!


It turned out that I was initializing my SPI communication after my IRQ setup, and since hat SPI initializaition called gpio_init(), that negated all my config.  It was in a library function deeper in the project so it was not obvious, but it now works! 

View solution in original post

13 Replies
MiTo_1583836
Level 5
Level 5
50 likes received 25 likes received 10 likes received

Hi dshalaby, I will get back to you very soon, I am looking into this right now.

0 Likes
Anonymous
Not applicable

Hello dshalaby,

1.  Examine the I2C_temperature sensor App in the SDK.

2.  LM73 Sensor Code should explain this.

Thanks

JT

0 Likes
MiTo_1583836
Level 5
Level 5
50 likes received 25 likes received 10 likes received

This is the sample code that we are using for our Mpresssion/Odyssey platform. We have an interruption set for P4 between the BCM20737S and a uC. The interruption is activated on falling edge (see example below: GPIO_EN_INT_FALLING_EDGE). Our P4 is pulled down by a resistor and the uC will force a state HIGH followed by LOW.

The defines are:

#define GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT0
#define GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN4

I put in bold the important pieces of code to enable an interruption on a specific pin.

void gpio_config_efm32_interrupt()

{

  //Declare the three ports even if we are only using one!

  UINT16 interrupt_handler_mask[3] = {0,0,0};

  DBG_PRINT_GPIO("gpio_config_efm32_interrupt> start...\n");

  //Setup the interruption line for P4, the Port is 0 (4/16) and the Pin is 4 (4%16)

  gpio_configurePin(GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT, GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN,

  GPIO_INPUT_ENABLE | GPIO_EN_INT_FALLING_EDGE, GPIO_PIN_OUTPUT_LOW);

  //Set the mask for the specific PORT of interest (PORT 0 in our case!)

interrupt_handler_mask[GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT] |=

  (1<< GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN);

  gpio_registerForInterrupt(interrupt_handler_mask, gpio_efm32_interrupt_routine, (void*)NULL);

  // Clear out any spurious interrupt status. (not sure it is needed, I saw it in the sample code

  //from Broadcom, may not be needed). Also when an interrupt happens there is no need to call this

  //function, the Broadcom stack does it for us!

  gpio_clearPinInterruptStatus(GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PORT,

  GPIO_APPLICATION_EXTERNAL_EFM32_INTERRUPT_PIN);

  DBG_PRINT_GPIO("gpio_config_efm32_interrupt> end...\n");

}

void gpio_efm32_interrupt_routine(void* parameter, UINT8 arg)

{

     //do something during the interrupt.

}

0 Likes

In our case APPLICATION_INIT() would call bleapp_set_cfg(xx,xx,xx,xx, xx, main_client). As soon as APPLICATION_INIT() returns we execute main_client and this is where we set the interruption posted above.

0 Likes

In the interruption routine I would do the minimum for now, just print ble_trace0("******** Interrupt Detected*******\n");

0 Likes
Anonymous
Not applicable

Ok thank you very much.   Not sure how this code differs from what I am doing,  can you please highlight what,  if any,  code that I  am missing that is in your example?   From what I can see,  we're both doing the same thing in our code.

0 Likes

Can you try to call the initialization of the interrupt in your "main" function?

0 Likes
Anonymous
Not applicable

Hi, thanks again for your help.  I can call the ISR manually, and it does run at that point, that said, the GPIO level is always read as low, regardless the actual state of that pin.

0 Likes
Anonymous
Not applicable

I have tried adjusting the BLE_PROFILE_GPIO_CFG to apply some interrupt settings (as defined in bleprofile.h, GPIO flag bits), to "pin" 2, as defined in platform.h, which suggests that in the context of hte _GPIO_CFG, "pin" means the number suffixed to the pin label "PXX", rather than the way pin is defined in the H/W user manual, where PORT = <PORT NUM>/16, PIN = <PORT_NUM> % 16.

Firstly, can someone confirm my understanding here that pin is defined differently when setting up your BLE_PROFILE_GPIO_CFG than when setting up gpio with the gpiodriver.h?

Secondly, if my understanding is correct, is there something wrong with my config (settings in BOLD are what I applied😞

const BLE_PROFILE_GPIO_CFG genoav1_0_gpio_cfg =

{

    {

        GPIO_PIN_WP,                               // This need to be used to enable/disable NVRAM write protect

        GPIO_PIN_BUTTON, GPIO_PIN_LED, GPIO_PIN_BUZZER, 2, // try to enable the IRQ line on P2

        -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 // Other GPIOs are not used

    },

    /*.gpio_flag =*/

    {

        GPIO_SETTINGS_WP,

        GPIO_SETTINGS_BUTTON, GPIO_SETTINGS_LED, GPIO_SETTINGS_BUZZER, GPIO_INT,

        0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0

    }

};

0 Likes

P2 refers to GPIO P2 (physical pin 22). If you need to find the port associated to P2 you will do 2/16 = 0 --> PORT0. You can use the definition that you have to enable the GPIO that's an option. You need to make sure that you pass the address of the structure called genoav1_0_gpio_cfg to bleapp_set_cfg() in APPLICATION_INIT.

The code that you put together yesterday looks good. Can you try to disable the pull down from the GPIO? and try again. If this is not working we can try the same code on the Tag3 board. We can setup an interruption on P0 and fire the interruption via the application button on the board.

I am still no convinced that you do your initialization in the "main" function the one called right after APPLICATION_INIT returns, could you please confirm?

0 Likes
Anonymous
Not applicable

Hi 79rpm,

Okay so I am doing my initialization of these IRQs in a function called genoav1_0_create() which is called after APPLICATION_INIT().  The initialization is:

UINT16 interrupt_handler_mask[3] = {0, 0, 0};

interrupt_handler_mask[IRQ_PORT] |= (1 << IRQ_PIN);

// Now register the interrupt handler.

gpio_registerForInterrupt(interrupt_handler_mask, application_gpio_interrupt_handler, NULL);

gpio_configurePin(IRQ_PORT,IRQ_PIN,GPIO_INPUT_ENABLE|GPIO_EN_INT_RISING_EDGE,GPIO_PIN_OUTPUT_LOW);

// Clear out any spurious interrupt status..

gpio_clearPinInterruptStatus(IRQ_PORT,IRQ_PIN);

I have tried setting the GPIO_PULL_UP and GPIO_PULL_DOWN that made no difference.

I have tried calling gpio_ConfigurePin() before gpio_registerForInterrupt() and vice versa, no difference.

I have tried playing with the BLE_PROFILE_GPIO_CFG , no difference

I have tried changing my #define statements for PORT and PIN to use parenthesis, (2) rather than 2.  No difference

Also, I have loaded the i2c_temerature_sensor example, and that one does fire the ISR correctly when I toggle P4, and when I simply change the LM73_ALERT_INTERRUPT_PIN to (2), and apply my external toggle switch, it does run the ISR.  So this confirms that it's not a hardware config issue, but that it's a config thing.

Also, now the loop that once correctly detected the state of that pin no longer works, it just reports the pin is low no matter what, so something is wrong.

Any additional support would be greatly appreciated.

Thanks in advance

Anonymous
Not applicable

Hi Everyone,

So, I figured it out: It turned out I had a gpio_init() call in some function that was called to set up the SPI communication.  Calling gpio_init() causes all the GPIO settings to reset, so once I scoured the code for this call and removed it, it started to work!    I guess this function is not really meant to be called by the developer.

BAD gpio_init()!  BAD!


It turned out that I was initializing my SPI communication after my IRQ setup, and since hat SPI initializaition called gpio_init(), that negated all my config.  It was in a library function deeper in the project so it was not obvious, but it now works! 

Thanks for sharing the solution with everyone!

0 Likes