<?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>nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/f/nordic-q-a/58110/nrf52840-dk--softdevice-events-handling</link><description>Hello : 
 I come from STM32 programming and I am new to Nordic device programming. 
 for nRF52840 DK, I am looking at the ble-blinking example and try to understand Softdevice event handling process flow. 
 
 I understand when a Softdevice has an event</description><dc:language>en-US</dc:language><generator>Telligent Community 13</generator><lastBuildDate>Wed, 26 Feb 2020 07:22:18 GMT</lastBuildDate><atom:link rel="self" type="application/rss+xml" href="https://devzone.nordicsemi.com/f/nordic-q-a/58110/nrf52840-dk--softdevice-events-handling" /><item><title>RE: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/236420?ContentTypeID=1</link><pubDate>Wed, 26 Feb 2020 07:22:18 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:213c3846-5bfb-47f5-b623-dfdcdb785f19</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Yes, its a tad complicated with the debounce timer and function pointer being passed around. However, from a top level the app_button module is quite easy to use and understand :)&amp;nbsp;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/236371?ContentTypeID=1</link><pubDate>Tue, 25 Feb 2020 18:25:44 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:6e15b3f5-1ce9-4144-bfd1-9952c1093123</guid><dc:creator>ACAMP</dc:creator><description>&lt;p&gt;what&amp;nbsp; a story.&lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/236141?ContentTypeID=1</link><pubDate>Tue, 25 Feb 2020 07:55:09 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:ffb338b8-ff66-4f2f-93c9-579ebfdddad1</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Yes, the event handler is passed to app_button_init as a the button_handler member of the&amp;nbsp;app_button_cfg_t struct in the buttons array. The buttons array of type&amp;nbsp;&lt;span&gt;app_button_cfg_t&amp;nbsp;is saved to an internal variable,&amp;nbsp;mp_buttons, in app_button.c.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;When ever a pin in the buttons array is pressed the app_button module will start an application timer that acts as a debounce timer, i,e, the pin is check when the interrupt is triggered, then you wait for a short period for the voltage level to stabilize on the pin before you check the state of the pin again. In app_button.c the last step is done in&amp;nbsp;detection_delay_timeout_handler() where you see that the&amp;nbsp;mp_buttons array, which is identical to the buttons array passed to&amp;nbsp;app_button_init, is traversed and the&amp;nbsp;evt_handle() is called if there is a state change.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;In evt_handle the state is processed and the&amp;nbsp;usr_event() function is called which looks up the configuration for the given pin and then calls the&amp;nbsp;button_handler() function, which is the function pointer to&amp;nbsp;&lt;strong&gt;button_event_handler.&lt;/strong&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;/* Find configuration structure for given pin. */
static app_button_cfg_t const * button_get(uint8_t pin)
{
    for (int i = 0; i &amp;lt; m_button_count; i++)
    {
        app_button_cfg_t const * p_btn = &amp;amp;mp_buttons[i];
        if (pin == p_btn-&amp;gt;pin_no) {
            return p_btn;
        }
    }

    /* If button is not found then configuration is wrong. */
    ASSERT(false);
    return NULL;
}

static void usr_event(uint8_t pin, uint8_t type)
{
    app_button_cfg_t const * p_btn = button_get(pin);

    if (p_btn &amp;amp;&amp;amp; p_btn-&amp;gt;button_handler)
    {
        NRF_LOG_DEBUG(&amp;quot;Pin %d %s&amp;quot;, pin, (type == APP_BUTTON_PUSH) ? &amp;quot;pressed&amp;quot; : &amp;quot;released&amp;quot;);
        p_btn-&amp;gt;button_handler(pin, type);
    }
}&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/236095?ContentTypeID=1</link><pubDate>Mon, 24 Feb 2020 22:25:26 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:a8cec43a-ca0b-4be0-ab0d-5f770de93e84</guid><dc:creator>ACAMP</dc:creator><description>&lt;p&gt;Another thread question:&amp;nbsp; &lt;strong&gt;Button notification&lt;/strong&gt;&lt;/p&gt;
&lt;p&gt;for the same example code:&lt;/p&gt;
&lt;p&gt;&lt;span&gt;nRF5SDK160098a08e2\examples\ble_peripheral\&lt;/span&gt;&lt;strong&gt;ble_app_blinky&lt;/strong&gt;&lt;span&gt;\pca10056\s140\ses&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;b&gt;Button notification:&amp;nbsp; &amp;nbsp;&lt;/b&gt;&lt;/p&gt;
&lt;p&gt;Could you explain&amp;nbsp;how&amp;nbsp;&lt;strong&gt;button_event_handler&lt;/strong&gt;&amp;nbsp;() get called ?&lt;/p&gt;
&lt;p&gt;Looks like when button is pressed, GPIO interrupt is triggered and serviced, but how does the GPIO interrupt service trigger&amp;nbsp;&lt;strong&gt;button_event_handler ()&lt;/strong&gt;&lt;span&gt;&amp;nbsp; ?&amp;nbsp; My guess is that is done somehow by function pointer ?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Could you explain?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thanks a lot !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&amp;nbsp;&lt;/span&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: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/235861?ContentTypeID=1</link><pubDate>Mon, 24 Feb 2020 07:33:14 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:5a21683e-42f6-4be6-92cf-da92a2302ef6</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;Yes, in the ble_app_blinky example its the&amp;nbsp;&lt;span&gt;BLE_LBS_DEF() macro that is used to register the&amp;nbsp;ble_lbs_on_ble_evt() event handler for the Led Button Service.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&amp;nbsp;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define BLE_LBS_DEF(_name)                                                                          \
static ble_lbs_t _name;                                                                             \
NRF_SDH_BLE_OBSERVER(_name ## _obs,                                                                 \
                     BLE_LBS_BLE_OBSERVER_PRIO,                                                     \
                     ble_lbs_on_ble_evt, &amp;amp;_name)
&lt;/pre&gt;&lt;/p&gt;
&lt;p&gt;Best regards&lt;/p&gt;
&lt;p&gt;Bjørn&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/235802?ContentTypeID=1</link><pubDate>Sat, 22 Feb 2020 00:24:13 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:7e257903-37c0-47a2-929d-b2ac9e0c7393</guid><dc:creator>ACAMP</dc:creator><description>&lt;p&gt;I think I figure it out.&lt;/p&gt;
&lt;p&gt;There is&amp;nbsp; &amp;nbsp; macro&amp;nbsp; &amp;nbsp; &amp;nbsp; &amp;nbsp; BLE_LBS_DEF(m_lbs);&amp;nbsp; &amp;nbsp; &amp;nbsp;in main ()&amp;nbsp; file&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Thanks&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item><item><title>RE: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/235785?ContentTypeID=1</link><pubDate>Fri, 21 Feb 2020 17:31:32 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:8e55cd98-3e1f-45e4-804f-61b07544f803</guid><dc:creator>ACAMP</dc:creator><description>&lt;p&gt;That makes great sense to me.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;I do have a follow up question.&lt;/p&gt;
&lt;p&gt;For ble_app_blinky example,&amp;nbsp;&amp;quot;&amp;nbsp; nRF5SDK160098a08e2\examples\ble_peripheral\&lt;strong&gt;ble_app_blinky&lt;/strong&gt;\pca10056\s140\ses &amp;quot;&lt;/p&gt;
&lt;p&gt;Now, I understand&amp;nbsp;&lt;strong&gt;ble_evt_handler is registered through&amp;nbsp;&lt;/strong&gt;NRF_SDH_BLE_OBSERVER.&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;My question is about: How the&lt;strong&gt; LED write function get executed&lt;/strong&gt; from smartphone to Softdevice&amp;nbsp; event and then to application code &amp;quot;&amp;nbsp;&lt;span&gt;on_write ()&lt;/span&gt;&amp;nbsp;&amp;quot;?&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;Looks like LED write event handle is registered through&amp;nbsp;&lt;span&gt;sd_ble_gatts_service_add( )&amp;nbsp; API?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Beside&amp;nbsp;NRF_SDH_BLE_OBSERVER,&amp;nbsp;we can also register an event handle by&amp;nbsp;sd_ble_gatts_service_add( )&amp;nbsp; API ?&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Thanks a lot !&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;static void on_write(ble_lbs_t * p_lbs, ble_evt_t const * p_ble_evt)&lt;/p&gt;
&lt;p&gt;void ble_lbs_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;err_code = sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY, &amp;amp;ble_uuid, &amp;amp;p_lbs-&amp;gt;service_handle);&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&gt;&lt;/p&gt;
&lt;p&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: nRF52840 DK- Softdevice events handling</title><link>https://devzone.nordicsemi.com/thread/235718?ContentTypeID=1</link><pubDate>Fri, 21 Feb 2020 12:57:19 GMT</pubDate><guid isPermaLink="false">137ad170-7792-4731-bb38-c0d22fbe4515:50482cef-1b5b-4f2c-816d-aa8801415465</guid><dc:creator>bjorn-spockeli</dc:creator><description>&lt;p&gt;HI Acamp&lt;/p&gt;
&lt;p&gt;The SoftDevice uses the EGU(Event Generator Unit) to generate a software interrupt to notify the application about BLE and SOC events. So b&lt;span&gt;oth SoC and BLE events from the SoftDevice are signaled through SWI2_EGU2_IRQHandler, here sdh_evts_poll() is called which in turns notifies all observers registered through the NRF_SDH_STACK_OBSERVER() macro, i.e.&amp;nbsp;nrf_sdh_ble_evts_poll() and&amp;nbsp;nrf_sdh_soc_evts_poll(). These functions will in turn notify all the observers registered through the&amp;nbsp;&lt;/span&gt;&lt;span&gt;NRF_SDH_BLE_OBSERVER() and&amp;nbsp;NRF_SDH_SOC_OBSERVER() macros.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So when an observer ( i.e. an event handler ) is registered through the&amp;nbsp;NRF_SDH_BLE_OBSERVER or&amp;nbsp;NRF_SDH_SOC_OBSERVER macros,&amp;nbsp;then the function pointer to the event handler is stored in a specific section in flash. The&amp;nbsp;nrf_sdh_soc_evts_poll() and&amp;nbsp;nrf_sdh_ble_evts_poll() functions will iterate through this section and call the handler functions through the function pointers stored in the section. This section will also be ordered depending on which priority that was assigned to the handler.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Lets take a practical example, in the ble_app_hrs example you&amp;#39;ll see the following macro at the top of main.c.&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;BLE_HRS_DEF(m_hrs);  &lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Going to the definition, we see that this macro registers the&amp;nbsp;ble_hrs_on_ble_evt() function as the handler and assign it&amp;nbsp;BLE_HRS_BLE_OBSERVER_PRIO (its set to 2) as the priority. The BLE_HRS_BLE_OBSERVER_PRIO&amp;nbsp; priority is set in the sdk_config.h file&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;#define BLE_HRS_DEF(_name)                                                                          \
static ble_hrs_t _name;                                                                             \
NRF_SDH_BLE_OBSERVER(_name ## _obs,                                                                 \
                     BLE_HRS_BLE_OBSERVER_PRIO,                                                     \
                     ble_hrs_on_ble_evt, &amp;amp;_name)&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;If we look at ble_stack_init() in the same example, we see that&amp;nbsp;it registers ble_evt_handler() as the handler function with priority&amp;nbsp;APP_BLE_OBSERVER_PRIO( which is set to 3).&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;&lt;/span&gt;&lt;span&gt;&lt;pre class="ui-code" data-mode="c_cpp"&gt;static void ble_stack_init(void)
{
    ret_code_t err_code;

    err_code = nrf_sdh_enable_request();
    APP_ERROR_CHECK(err_code);

    // Configure the BLE stack using the default settings.
    // Fetch the start address of the application RAM.
    uint32_t ram_start = 0;
    err_code = nrf_sdh_ble_default_cfg_set(APP_BLE_CONN_CFG_TAG, &amp;amp;ram_start);
    APP_ERROR_CHECK(err_code);

    // Enable BLE stack.
    err_code = nrf_sdh_ble_enable(&amp;amp;ram_start);
    APP_ERROR_CHECK(err_code);

    // Register a handler for BLE events.
    NRF_SDH_BLE_OBSERVER(m_ble_observer, APP_BLE_OBSERVER_PRIO, ble_evt_handler, NULL);
}
&lt;/pre&gt;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;So whenever a BLE event is signaled by the SoftDevice, then the call stack will roughly be like this&amp;nbsp;SWI2_EGU2_IRQHandler -&amp;gt;&amp;nbsp;nrf_sdh_ble_evts_poll() -&amp;gt;&amp;nbsp;ble_hrs_on_ble_evt -&amp;gt; ble_evt_handler. So&amp;nbsp;ble_hrs_on_ble_evt&amp;nbsp;will be called first by&amp;nbsp;nrf_sdh_ble_evts_poll as it has a higher priority than&amp;nbsp;ble_evt_handler.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;I hope that clarifies it. If not, then just post additional question in comments.&amp;nbsp;&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Best regards&lt;/span&gt;&lt;/p&gt;
&lt;p&gt;&lt;span&gt;Bjørn&lt;/span&gt;&lt;/p&gt;&lt;div style="clear:both;"&gt;&lt;/div&gt;</description></item></channel></rss>