GPIO Interrupt and sleep mode

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

cross mob
huangj
Level 4
Level 4
Welcome! 25 replies posted 10 replies posted

Hi,

The sensor has serial communication interface. When the BCM20737S send a request signal, and the sensor will generate clk and data(similar to 3 wire SPI). I connect the GPIO of BCM20737S and sensor together.

BCM20737S P11 GPIO output  <===>   Sensor Req. pin

BCM20737S P12 GPIO iutput   <===>   Sensor data pin

BCM20737S P13 GPIO iutput    <===>   Sensor clk pin

The BCM20737S will send  request signal to the sensor, and then the clk signal will trigger the interrupt. I receive the data in the interrupt call back. When I disabled the sleep function, and it work fine. But when I enabled the sleep function, and it have some trouble. I don't know how to fix it.

Here is my code in the hello_sensor create function. I enable GPIO interrupt and wake up source by GPIO.

******************************************************************************************************************************************

gpio_configurePin(11 / 16, 11 % 16, GPIO_OUTPUT_ENABLE, 1);      //req.

gpio_configurePin(12 / 16, 12 % 16, GPIO_INPUT_ENABLE, GPIO_PIN_OUTPUT_LOW);     //data

UINT16 masks[3] = {(1 << 13), 0 , 0};          //clock interrupt setting

gpio_configurePin(13 / 16, 13 % 16, GPIO_EN_INT_RISING_EDGE, GPIO_PIN_OUTPUT_LOW);

gpio_clearPinInterruptStatus(13 / 16, 13 % 16);

gpio_configurePin(14 / 16, 14 % 16, GPIO_OUTPUT_ENABLE, 1);               //debug pin

devlpm_init();                                             //choose wake up source

devlpm_enableWakeFrom(DEV_LPM_WAKE_SOURCE_GPIO);

devlpm_registerForLowPowerQueries(uart_device_lpm_queriable, 0);     //disable sleep function

******************************************************************************************************************************************

UINT32 uart_device_lpm_queriable(LowPowerModePollType type, UINT32 context){

     return 0;     //0 is mean disable sleep

}

******************************************************************************************************************************************

Here is my code in the interrupt call back. When the interrupt is trigger,it will change the output level in the pin14. I can use the logic analyzer or oscilloscope to check all interrupt is trigger.

******************************************************************************************************************************************

gpio_clearPinInterruptStatus(0,13);

if(gpio_getPinInput(0,13)){             

        test1 = ~test1;

        gpio_configurePin(14 / 16, 14 % 16, GPIO_OUTPUT_ENABLE, test1);

}

******************************************************************************************************************************************

Here is the result when I disable the sleep function. All of interrupts are triggered.

pastedImage_8.png

But I enable the sleep function. Some interrupt didn't triggered. I assume the BCM20737S in the sleep mode, so it need time to wake up. I miss several interrupt because the BCM20737S need time to wake up. But it trigger 8 times after wake up, and it miss the interrupt again. How to solve the problem. I can't disable sleep function because our device will work with the battery. Thanks for any suggestions.

pastedImage_10.png

Jack

0 Likes
5 Replies
JacobT_81
Employee
Employee
250 replies posted 100 replies posted 50 replies posted

As long you can handle the initial wake up latency i.e. missing those first 12 CLK pulses, then you should be able to get around this by dynamically disabling sleep in your interrupt handler. And then don't reinitialize sleep until your communication is done.

Jacob

Hi Jacob,

Thanks for your suggestion.

then you should be able to get around this by dynamically disabling sleep in your interrupt handler.

>I have add the disable sleep in the interrupt callback, and it will not miss the interrupt  anymore. But the BCM20737S will not enter sleep mode again. I need BCM2037S wake up to receive the interrupt and sleep again until next interrupt. The sensor will send next data in 69 ms.

pastedImage_1.png

Here is the code in my interrupt call back. When the first interrupt was trigger, and it will disable the sleep function. After I get enough interrupt, and I will reinitialize sleep.  It will not miss the interrupt, but the BCM20737S didn't enter to sleep mode.

********************************************************************************

gpio_clearPinInterruptStatus(0,13);

if(gpio_getPinInput(0,13)){           

        test1 = ~test1;

        gpio_configurePin(14 / 16, 14 % 16, GPIO_OUTPUT_ENABLE, test1);

        int_trigger++;          //the int_trigger will clear in the timer

        if(first_trigger){                              //disable sleep

               first_trigger = FALSE;

               devlpm_registerForLowPowerQueries(uart_device_lpm_queriable,0);

        }else{

               if(int_trigger==41){          //reinitialize sleep

                    first_trigger = TRUE;

                    devlpm_registerForLowPowerQueries(uart_device_lpm_queriable,0xFFFFFFFF);

               }

        }

}

UINT32 LVDT_device_lpm_queriable(LowPowerModePollType type, UINT32 context){

     if(int_trigger>0){

          if(first_trigger){      //return 0xFFFFFFFF  reinitialize sleep

               return 0xFFFFFFFF;

          }else{                    //return 0  disable sleep

               return 0;

          }

     }

}

********************************************************************************

Here is the result. Sometime the interrupt didn't trigger. I don't know the reason why the interrupt has miss, and the power consumption was 4.6 mA. So the BCM20737S didn't enter to sleep mode, and the BCM20737S will miss few interrupt. Can you help me to figure out the problem? Thanks for any suggestion.

pastedImage_3.png

Jack

0 Likes
JacobT_81
Employee
Employee
250 replies posted 100 replies posted 50 replies posted

A few things I noted when going through your code:

1. There's no need to call the register function more than once:

devlpm_registerForLowPowerQueries(uart_device_lpm_queriable,0);

You only need to call this once in create, then conditionally return 1 or 0 depending on whether your communication is starting or finished. Please remove this function from your conditional and add it to your create function.

2. Naming mismatch: 'LVDT_device_lpm_queriable' is callback name. 'uart_device_lpm_queriable' is registered instead. (I'm assuming this is a copy/paste error)

3. Your *_device_lpm_queriable callback should return 1 or 0. Your 0xffffffff is truncated to 8 bits in compilation. Although this wouldn't have caused any problems.

4. Calling gpio_getPinInput(0,13) won't work when the pin is configured as an interrupt. You must reconfigure the pin as an input, poll the value, then change it back to an interrupt when you're ready.

5. Where do you reset init_trigger? this needs to go back to 0 at the end.

Please fix these things and let me know if you see better functionality.

Jacob

Hi jakewtorres

Thanks for your response.

3. Your *_device_lpm_queriable callback should return 1 or 0. Your 0xffffffff is truncated to 8 bits in compilation. Although this wouldn't have caused any problems.

>>The "Managing Advertisements and Sleep States to Minimize Power Consumption" design guide indicates that 0xffffff the LE stack will choose Sleep or Deep Sleep states for a duration. But I will return 0 or 1 in my app.

pastedImage_0.png

4. Calling gpio_getPinInput(0,13) won't work when the pin is configured as an interrupt. You must reconfigure the pin as an input, poll the value, then change it back to an interrupt when you're ready.

>>Because I found the interrupt had triggered in the low level(I use Rising edge). So I check the pin level to avoid trigger in low level. The clk pin had a pull up resistor(10K for 3.3V) in our hardware.

pastedImage_2.png

5. Where do you reset init_trigger? this needs to go back to 0 at the end.

>>I will clean it in the timer.

I will revise my app, and post result to the community.

Jack

0 Likes
JacobT_81
Employee
Employee
250 replies posted 100 replies posted 50 replies posted

4. Calling gpio_getPinInput(0,13) won't work when the pin is configured as an interrupt. You must reconfigure the pin as an input, poll the value, then change it back to an interrupt when you're ready.

>>Because I found the interrupt had triggered in the low level(I use Rising edge). So I check the pin level to avoid trigger in low level. The clk pin had a pull up resistor(10K for 3.3V) in our hardware.

It's not a problem that you want to check pin state after receiving an interrupt, the problem is attempting to read a pin as an input which is currently configured as an interrupt. It will likely feed you bad values. Please do this:

          gpio_configurePin(13 / 16, 13 % 16, GPIO_INPUT_ENABLE, 0);

          if(gpio_getPinInput(0,13)){          

                  test1 = ~test1;

                    ....

          }

          gpio_configurePin(13 / 16, 13 % 16, GPIO_EN_INT_RISING_EDGE, 0);

Jacob