<?xml version="1.0" encoding="UTF-8" ?>
<?xml-stylesheet type="text/xsl" href="https://devzone.nordicsemi.com/cfs-file/__key/system/syndication/rss.xsl" media="screen"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>Duplicate GPIO callbacks after initializing button to support &amp;quot;wake up&amp;quot; from power OFF</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/109043/duplicate-gpio-callbacks-after-initializing-button-to-support-wake-up-from-power-off</link><description>I&amp;#39;m using SDK v2.5.2 on the nRF52833, and my project is trying to accomplish two things: 
 
 Initialize the button GPIO and use its callback in the main application 
 Use the button GPIO as a means to &amp;quot;wake up&amp;quot; the system from &amp;quot;power OFF&amp;quot; state 
 
 I</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Mon, 11 Mar 2024 14:34:09 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/109043/duplicate-gpio-callbacks-after-initializing-button-to-support-wake-up-from-power-off" /><item><title>RE: Duplicate GPIO callbacks after initializing button to support "wake up" from power OFF</title><link>https://devzone.nordicsemi.com/thread/473234?ContentTypeID=1</link><pubDate>Mon, 11 Mar 2024 14:34:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c63f3870-1a2a-41c1-b927-002c40f9166f</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;There is a smaller chance of losing events when using PIN events instead of PORT events, since PIN events provide a dedicated event for a single pin, as opposed to a PORT event, which is common to all pins with sense enabled. I was also able to reproduce the same issue of duplicated events with PIN events,&amp;nbsp;but not&amp;nbsp;as easily.&lt;/p&gt;
&lt;p&gt;I suspect the problem is related to button debouncing, and your software workaround effectively acts as a debouncing filter in software. The&amp;nbsp;DK doesn&amp;#39;t have a&amp;nbsp;debounce filter for the button inputs.&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Duplicate GPIO callbacks after initializing button to support "wake up" from power OFF</title><link>https://devzone.nordicsemi.com/thread/473154?ContentTypeID=1</link><pubDate>Mon, 11 Mar 2024 11:57:50 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:47cfbd2a-30ee-45fa-bcb3-4e6745978f2c</guid><dc:creator>cal.rubbo</dc:creator><description>&lt;p&gt;UPDATE: I&amp;#39;ve mostly mitigated the issue, but this seems sort-of hacky and I am still curious whether this &amp;quot;GPIO sense callback accuracy&amp;quot; is a known issue or not, or if there&amp;#39;s a better way to resolve it than what I&amp;#39;ve come up with.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;This is how I mitigated the issue:&lt;/p&gt;
&lt;ol&gt;
&lt;li&gt;In the GPIO callback, add a check to only process the callback if it&amp;#39;s been a certain amount of time since the previous callback (I chose 15 milliseconds)&lt;/li&gt;
&lt;li&gt;Move the actual &amp;quot;work&amp;quot; that needs to be done after a GPIO callback to a work queue&lt;/li&gt;
&lt;li&gt;Sleep for a short amount of time at the beginning of this &amp;quot;work&amp;quot; (I also chose 15 milliseconds)&lt;/li&gt;
&lt;/ol&gt;
&lt;p&gt;Here&amp;#39;s the&amp;nbsp;result:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define AF_BUTTON_EVENT_MINIMUM_MSEC 15
uint32_t af_button_previous_event = 0;

// Callback when button is either released or pressed
void af_button_state_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
    
    // Ignore this event if a previous event happened within the millisecond threshold
    uint32_t af_button_current_event = k_uptime_get_32();
    if ((af_button_current_event - af_button_previous_event) &amp;lt; AF_BUTTON_EVENT_MINIMUM_MSEC)
        return;
    
    // Submit event work!
    k_work_submit(&amp;amp;af_button_state_work);
    af_button_previous_event = af_button_current_event;
}


// Do the actual work of updating advertising set #1&amp;#39;s advertising data
void af_button_state_work_cb(struct k_work *item) {

    // To avoid reading the wrong GPIO state (e.g. two &amp;quot;high&amp;quot; events in a row, when it should be a &amp;quot;low&amp;quot; event)
    k_msleep(AF_BUTTON_EVENT_MINIMUM_MSEC);

    // Check current state to determine if this is a pressed or released event
    int val = af_button_get_state();

    // If this is a &amp;quot;press&amp;quot; event
    if (val &amp;gt; 0) {
        // ...
    }
    // If this is a &amp;quot;release&amp;quot; event
    else {
        // ...
    }
}
K_WORK_DEFINE(af_button_state_work, af_button_state_work_cb);  // To do the actual work that processes a button &amp;quot;high&amp;quot; or &amp;quot;low&amp;quot; event&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Duplicate GPIO callbacks after initializing button to support "wake up" from power OFF</title><link>https://devzone.nordicsemi.com/thread/473145?ContentTypeID=1</link><pubDate>Mon, 11 Mar 2024 11:05:59 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:c27c201a-da64-4ff2-9763-8291cd69ee34</guid><dc:creator>cal.rubbo</dc:creator><description>&lt;p&gt;Thanks Vidar.&lt;/p&gt;
&lt;p&gt;Using this, I can confirm the GPIO callback now works (almost) as expected, and that the &amp;quot;sense&amp;quot; functionality is clearly enabled because I&amp;#39;m able to wake the device from sleep.&amp;nbsp;&lt;/p&gt;
&lt;p&gt;However, I&amp;#39;m now seeing the GPIO callback isn&amp;#39;t as accurate as before. Is that expected? After a few presses, it looks like the callback is returning the GPIO state as &amp;quot;high&amp;quot; many times in a row (which should be impossible, since it&amp;#39;s supposed to be called only once &amp;quot;high&amp;quot;&amp;nbsp;and then once again when it&amp;#39;s &amp;quot;low&amp;quot;).&amp;nbsp;&lt;/p&gt;
&lt;p&gt;I&amp;#39;m using a very simple callback for now, here it is:&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;// Callback when button is either released or pressed
void af_button_state_cb(const struct device *dev, struct gpio_callback *cb, uint32_t pins) {
    
    // Check current state to determine if this is a pressed or released event
    int val = gpio_pin_get_dt(&amp;amp;af_button);
    
    printk(&amp;quot;Button pressed at %&amp;quot; PRIu32 &amp;quot;, val=%d\n&amp;quot;, k_cycle_get_32(), val);
}&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;For example, here&amp;#39;s me pressing the button twice in a row. You can see the second press, the callback was returned &amp;quot;val=1&amp;quot; or &amp;quot;high&amp;quot; on the release event, as well as the press event. Sometimes this happens many times in a row. Note that I think it&amp;#39;s related to how long you hold the button down.&lt;/p&gt;
&lt;p&gt;&lt;pre class="ui-code" data-mode="text"&gt;Button pressed at 1484010, val=1
Button pressed at 1487371, val=0
Button pressed at 1491250, val=1
Button pressed at 1558829, val=1&lt;/pre&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Duplicate GPIO callbacks after initializing button to support "wake up" from power OFF</title><link>https://devzone.nordicsemi.com/thread/473108?ContentTypeID=1</link><pubDate>Mon, 11 Mar 2024 08:41:42 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7d1ede09-8dcf-4862-a999-9d30de1d0ac8</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;I wasn&amp;#39;t aware that configuring GPIO_INT_LEVEL_ACTIVE would cause the event to fire repeatedly. After testing with the Zephyr button sample, I discovered that the solution&amp;nbsp;is&amp;nbsp;to the GPIO_INT_EDGE_BOTH flag and&amp;nbsp;apply&amp;nbsp;the &amp;#39;&lt;a href="https://developer.nordicsemi.com/nRF_Connect_SDK/doc/latest/zephyr/build/dts/api/bindings/gpio/nordic,nrf-gpio.html"&gt;sense-edge-mask&lt;/a&gt;&amp;#39; property to the gpio node in the device tree. This enables edge triggering as before, but with port events.&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Devicetree overlay with sense-edge-mask&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1710146369149v1.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;Input&amp;nbsp;configuration with sense edge mask&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1710146450202v2.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;&lt;strong&gt;GPIOTE configuration&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1710146484246v3.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Duplicate GPIO callbacks after initializing button to support "wake up" from power OFF</title><link>https://devzone.nordicsemi.com/thread/473024?ContentTypeID=1</link><pubDate>Fri, 08 Mar 2024 17:52:29 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:461842d5-fb99-4b6a-8646-74f179b598b0</guid><dc:creator>cal.rubbo</dc:creator><description>&lt;p&gt;Sounds like Port events are the way to go from a idle current standpoint, however I&amp;#39;m confused about how they trigger GPIO callbacks.&lt;/p&gt;
&lt;p&gt;Using&amp;nbsp;&lt;span&gt;GPIO_INT_LEVEL_ACTIVE as you suggested, the GPIO callback is repeatedly (and only) called while the button is&amp;nbsp;held down. It also blocks anything else on the CPU until the button is released.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Is it possible to have a Port event trigger the GPIO callback on press&amp;nbsp;AND release events? like an interrupt?&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: Duplicate GPIO callbacks after initializing button to support "wake up" from power OFF</title><link>https://devzone.nordicsemi.com/thread/473018?ContentTypeID=1</link><pubDate>Fri, 08 Mar 2024 16:57:00 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:11336376-aed1-482d-af37-da0d1d2681bf</guid><dc:creator>Vidar Berg</dc:creator><description>&lt;p&gt;Hello,&amp;nbsp;&lt;/p&gt;
&lt;p&gt;Please try enabling LEVEL triggering instead of EDGE triggering by changing the GPIO_INT_EDGE_BOTH flag to GPIO_INT_LEVEL_ACTIVE. This should configure the pin with sense enabled and use &lt;a title="Port event" href="https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/gpiote.html?cp=5_2_0_20_1#concept_jyp_21x_lr"&gt;Port event&lt;/a&gt;s&lt;span&gt;&amp;nbsp;&lt;/span&gt; instead of&amp;nbsp;&lt;a title="Pin events and tasks" href="https://infocenter.nordicsemi.com/topic/com.nordic.infocenter.nrf52832.ps.v1.1/gpiote.html?cp=5_2_0_20_0#concept_tyh_czw_lr"&gt;Pin events&lt;/a&gt;, making the additional call to nrf_gpio_cfg_sense_set() redundant. Using PORT events also has the added benefit of reducing idle current and should be accurate enough to detect button events.&lt;/p&gt;
&lt;p&gt;&lt;img style="max-height:240px;max-width:320px;" src="https://devzone.nordicsemi.com/resized-image/__size/640x480/__key/communityserver-discussions-components-files/4/pastedimage1709916839321v1.png" alt=" " /&gt;&lt;/p&gt;
&lt;p&gt;&lt;a title="Sleep" href="https://infocenter.nordicsemi.com/topic/ps_nrf52833/_tmp/nrf52833/autodita/CURRENT/parameters.i_sleep.html?cp=5_1_0_4_1_0_0"&gt;Sleep&lt;/a&gt;&lt;/p&gt;
&lt;p&gt;Best regards,&lt;/p&gt;
&lt;p&gt;Vidar&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>