5 Replies Latest reply on Sep 12, 2016 1:44 PM by JacobT_81

    GPIO Interrupt and sleep mode

    huangj

      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.

       

      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.

       

       

      Jack

        • 1. Re: GPIO Interrupt and sleep mode
          JacobT_81

          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

          1 of 1 people found this helpful
          • 2. Re: GPIO Interrupt and sleep mode
            huangj

            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.

             

            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.

             

            Jack

            • 3. Re: GPIO Interrupt and sleep mode
              JacobT_81

              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

              1 of 1 people found this helpful
              • 4. Re: GPIO Interrupt and sleep mode
                huangj

                Hi JacobT_81

                 

                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.

                 

                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.

                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

                • 5. Re: GPIO Interrupt and sleep mode
                  JacobT_81

                  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

                  1 of 1 people found this helpful