Pin configured for wakeup from system off sleep misbehaving.

I am working on nrf52832 based custom board and I want system off sleep and wakeup using GPIO pin state change. For that I have configured MCU standby timeout in sdk_config.h.

There is a switch in the hardware that can be pressed to wake up the system from sleep. But the switch has alternate function when the system is awake. So I have configured the pin as wakeup just before the system is going to sleep. Initially this works, but sometime the system skips this configuration and directly goes to sleep. 

So I have modified the hardware and assigned two GPIO pins to the switch, one for normal switch mode and other for wakeup switch. Initially I have configured one of the pins for wakeup using "nrf_gpio_cfg_sense_input()" function. But after that the other pin is not working properly, that means when I configured one pin as wakeup pin the other pin won't working properly. Another issue is while system is awake any transition in the wakeup pin halts the code execution. 

Could anyone help me to solve this issue?

Thanks

Sachin

Parents Reply Children
  • Hi Kazi, 

    Thanks for you reply.

    I have configured two GPIO pins as given below. These two functions were executed initially.

    #define NORMAL_WAKEUP_PIN   27
    #define RESET_PIN           26
    
    void wakeup_from_sleep_pin_init(void)
    {
        nrf_gpio_cfg_sense_input(NORMAL_WAKEUP_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
    }
    
    void reset_pin_init(void)
    {
        nrf_drv_gpiote_in_config_t reset_pin_config = NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(true);
        reset_pin_config.pull = NRF_GPIO_PIN_NOPULL;	
    
        nrf_drv_gpiote_in_init(RESET_SWITCH, &reset_pin_config, NULL);
    
        nrf_drv_gpiote_in_event_enable(RESET_SWITCH, true);
    	
        nrf_gpio_cfg_sense_input(RESET_SWITCH, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE);
    }

    The schematics is given below. Here 4th pin of the connector P6 is pulled up and connected to GPIO pins P0.26 and P0.27

    Thanks

    Sachin

  • Hello Sachin, 

    I am not quite sure the purpose of the application from the code. ''''So, I have modified the hardware and assigned two GPIO pins to the switch, one for normal switch mode and other for wakeup switch.'' what is this normal switch mode?

    Is the nrf_gpio_cfg_sense_input function does not do what it should, or if the function is not called at all. your code does not show how these go to sleep.

    Instead of using 2 pins, can not you try to use one pin and reconfigure it depending on the sleep or wake up mode?

  • Hi Kazi,

    I will try to explain it in detail.

    I am attaching my code main file.

    /* Includes */
    
    /* Standard includes*/
    #include <stdint.h>
    #include <string.h>
    
    /* SDK includes */
    #include "boards.h"
    #include "nordic_common.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "ble.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "ble_db_discovery.h"
    #include "ble_conn_state.h"
    #include "ble_hci.h"
    #include "ble_lbs_c.h"
    #include "ble_lbs.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_ble_scan.h"
    #include "nrf_drv_timer.h"
    #include "nrf_delay.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "ble_bas.h"
    #include "nrf_drv_wdt.h"
    
    /* Define objects */
    NRF_BLE_GQ_DEF(m_ble_gatt_queue, NRF_SDH_BLE_CENTRAL_LINK_COUNT, NRF_BLE_GQ_QUEUE_SIZE);	/**< BLE GATT Queue instance. */
    NRF_BLE_GATT_DEF(m_gatt);                                              						/**< GATT module instance. */
    NRF_BLE_QWRS_DEF(m_qwr, NRF_SDH_BLE_TOTAL_LINK_COUNT);                 						/**< Context for the Queued Write module.*/
    BLE_ADVERTISING_DEF(m_advertising);                                    						/**< Advertising module instance. */
    NRF_BLE_SCAN_DEF(m_scan);                                           						/**< Scanning module instance. */
    BLE_DB_DISCOVERY_DEF(m_db_disc);                                							/**< DB discovery module instance. */
    BLE_LBS_C_DEF(m_ble_lbs_c);                                     							/**< Main structure used by the LBS client module. */
    BLE_LBS_DEF(m_lbs);                                                       					/**< LED Button Service instance. */
    BLE_BAS_DEF(m_bas);                                     									/**< Battery service instance. */
    
    const nrf_drv_timer_t BACKGROUND_TIMER = NRF_DRV_TIMER_INSTANCE(2);							/**< Timer instance. */
    
    #define NORMAL_WAKEUP_PIN   27
    #define RESET_PIN           26
    
    /* Define Variables */
    
    static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;             					/**< Advertising handle used to identify an advertising set. */
    static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];              					/**< Buffer for storing an encoded advertising set. */
    static uint8_t m_enc_scan_response_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];   					/**< Buffer for storing an encoded scan data. */
    
    /**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = m_enc_scan_response_data,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
        }
    };
    
    static ble_gap_scan_params_t m_scan_param =                 								/**< Scan parameters requested for scanning and connection. */
    {
        .active        = 0x01,
        .interval      = NRF_BLE_SCAN_SCAN_INTERVAL,
        .window        = NRF_BLE_SCAN_SCAN_WINDOW,
        .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
        .timeout       = NRF_BLE_SCAN_SCAN_DURATION,
        .scan_phys     = BLE_GAP_PHY_1MBPS,
        .extended      = true,
    };
    
    uint16_t current_conn_handle_periph	= BLE_CONN_HANDLE_INVALID;                              /**< Handle of the current connection from BLE central. */
    uint16_t current_conn_handle_central	= BLE_CONN_HANDLE_INVALID;                          /**< Handle of the current connection from BLE peripheral. */
    uint8_t event_packet_to_send[18];															/**< Array to store event packet to send to gateway. */
    uint16_t reset_delay_cnt=0;                                                                 /**< Variable for storing reset delay count. */
    
    
    /* Function definitions */
    
    /**@brief Handles events from Battery update service
     */
    static void on_bas_evt(ble_bas_t * p_bas, ble_bas_evt_t * p_evt)
    {
    	
    }
    
    /**@brief Function for handling asserts in the SoftDevice.
     *
     * @details This function is called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and is not meant for the final product. You need to analyze
     *          how your product is supposed to react in case of assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in] line_num     Line number of the failing assert call.
     * @param[in] p_file_name  File name of the failing assert call.
     */
    static void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(0xDEADBEEF, line_num, p_file_name);
    }
    
    
    /**@brief Function for handling the LED Button Service client errors.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void lbs_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Function for handling the Heart Rate Service Client
     *        Running Speed and Cadence Service Client.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void service_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for handling errors from the Connection Parameters module.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Handles events from scaning for peripherals
     */
    static void scan_evt_handler(scan_evt_t const * p_scan_evt)
    {
    
        ret_code_t err_code;
    	
    	  ble_gap_evt_adv_report_t const * p_adv =  p_scan_evt->params.filter_match.p_adv_report;
        ble_gap_scan_params_t    const * p_scan_param = p_scan_evt->p_scan_params;
    		
        switch(p_scan_evt->scan_evt_id)
        {
    			   case NRF_BLE_SCAN_EVT_FILTER_MATCH:
            {
    
    					// Initiate connection.
    					err_code = sd_ble_gap_connect(&p_adv->peer_addr,
    																				p_scan_param,
    																				&m_scan.conn_params,
    																				APP_BLE_CONN_CFG_TAG);
    					APP_ERROR_CHECK(err_code);
            } break;
            case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
    				{
                err_code = p_scan_evt->params.connecting_err.err_code;
                APP_ERROR_CHECK(err_code);
    				} break;
            default:
              break;
        }
    }
    
    /**@brief Handles events coming from the LED Button service central module.
     */
    static void lbs_c_evt_handler(ble_lbs_c_t * p_lbs_c, ble_lbs_c_evt_t * p_lbs_c_evt)
    {
        switch (p_lbs_c_evt->evt_type)
        {
            case BLE_LBS_C_EVT_DISCOVERY_COMPLETE:
            {
                ret_code_t err_code;
    
                err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c,
                                                    p_lbs_c_evt->conn_handle,
                                                    &p_lbs_c_evt->params.peer_db);
    //            NRF_LOG_INFO("LED Button service discovered on conn_handle 0x%x.", p_lbs_c_evt->conn_handle);
    					
                // LED Button service discovered. Enable notification of Button.
                err_code = ble_lbs_c_button_notif_enable(p_lbs_c);
                APP_ERROR_CHECK(err_code);
    
            } break; // BLE_LBS_C_EVT_DISCOVERY_COMPLETE
    				
            case BLE_LBS_C_EVT_BUTTON_NOTIFICATION:
            {
    					packet_header* cmd_header;
    					uint16_t crc_16 = 0;
    					uint16_t len=0;
    					len = p_lbs_c_evt->params.button.button_state[2];
    
    					cmd_header = (packet_header*)p_lbs_c_evt->params.button.button_state;
    
    					crc_16 = gen_crc16(p_lbs_c_evt->params.button.button_state,len-2);
    
    					if(cmd_header->start_byte == START_BYTE)
    					{ 
    
    						process_ack_from_gw(cmd_header,crc_16);  // Function defined outside main.c
    
    					}					
    
            } break; // BLE_LBS_C_EVT_BUTTON_NOTIFICATION				
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief Function for initialization the scanning and setting the filters.
     */
    static void scan_init(void)
    {
    	ret_code_t          err_code;
    	nrf_ble_scan_init_t init_scan;
    
    	memset(&init_scan, 0, sizeof(init_scan));
    
    	init_scan.connect_if_match = false;
    	init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
    //	init_scan.p_scan_param = &m_scan_param;
    
    	err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
    	APP_ERROR_CHECK(err_code);
    
    	err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ADDR_FILTER, false);
    	APP_ERROR_CHECK(err_code);
    
    	if (target_dev_addr[0] != 0)
    	{
    		err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, target_dev_addr);
    		APP_ERROR_CHECK(err_code);
    	}
    
    }
    
    /**@brief Function for initializing the advertising.
     */
    static void advertising_start(void)
    {
    	
    	ret_code_t err_code;
    	
    	err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
    //	APP_ERROR_CHECK(err_code);
    
    }
    
    /**
    * @brief Function for force stopping the advertising.
    * @author Sachin
    * @date 02-08-23
    */
    static void advertising_stop(void)
    {
    	
    	ret_code_t err_code;
    
    	err_code = sd_ble_gap_adv_stop(m_adv_handle);
    
    	APP_ERROR_CHECK(err_code);
    
    }
    
    /**@brief Function for assigning new connection handle to available instance of QWR module.
     *
     * @param[in] conn_handle New connection handle.
     */
    static void multi_qwr_conn_handle_assign(uint16_t conn_handle)
    {
        for (uint32_t i = 0; i < NRF_SDH_BLE_TOTAL_LINK_COUNT; i++)
        {
            if (m_qwr[i].conn_handle == BLE_CONN_HANDLE_INVALID)
            {
                ret_code_t err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr[i], conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
            }
        }
    }
    
    /**@brief Function for handling the Connected event.
     *
     * @param[in] p_gap_evt GAP event received from the BLE stack.
     */
    static void on_connected(const ble_gap_evt_t * const p_gap_evt)
    {
        ret_code_t  err_code;
        uint32_t    periph_link_cnt = ble_conn_state_peripheral_conn_count(); // Number of peripheral links.
    
    //    NRF_LOG_INFO("Connection with link 0x%x established.", p_gap_evt->conn_handle);
    	
    	/**Connection handle is required to terminate the connection from the peripheral if an unauthorized
    	   peer(central device) tries to connect.
        *This	way, only the unauthorized peer gets kicked out, authorized peer devices that are currently connected to this perihperal 
    	   will maintan their connections.
    	  *@author - Akshay
    	  *@date - 01-06-23
    	*/
        current_conn_handle_periph = p_gap_evt->conn_handle; 
        // Assign connection handle to available instance of QWR module.
        for (uint32_t i = 0; i < NRF_SDH_BLE_PERIPHERAL_LINK_COUNT; i++)
        {
            if (m_qwr[i].conn_handle == BLE_CONN_HANDLE_INVALID)
            {
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr[i], p_gap_evt->conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
            }
        }
    
    
        if (periph_link_cnt == NRF_SDH_BLE_PERIPHERAL_LINK_COUNT)
        {
    
        }
        else
        {
            // Continue advertising. More connections can be established because the maximum link count has not been reached.
                advertising_start();		
            
        }
    		
    		 nrf_drv_timer_enable(&TIME_SYNC_CHECK);
    }
    
    /**@brief Function for handling the Disconnected event.
     *
     * @param[in] p_gap_evt GAP event received from the BLE stack.
     */
    static void on_disconnected(ble_gap_evt_t const * const p_gap_evt)
    {
    //    ret_code_t  err_code;
        uint32_t    periph_link_cnt = ble_conn_state_peripheral_conn_count(); // Number of peripheral links.
    
    //    NRF_LOG_INFO("Connection 0x%x has been disconnected. Reason: 0x%X",
    //                 p_gap_evt->conn_handle,
    //                 p_gap_evt->params.disconnected.reason);
    
        if (periph_link_cnt == 0)
        {
    
        }
    
        if (periph_link_cnt == (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - 1))
        {
            // Advertising is not running when all connections are taken, and must therefore be started.
            advertising_start();
        }
    }
    
    /**@brief   Function for handling BLE events from the central application.
     *
     * @details This function parses scanning reports and initiates a connection to peripherals when a
     *          target UUID is found. It updates the status of LEDs used to report the central application
     *          activity.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     */
    static void on_ble_central_evt(ble_evt_t const * p_ble_evt)
    {
    
    	ret_code_t err_code;
    
        // For readability.
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    
        switch (p_ble_evt->header.evt_id)
        {
            // Upon connection, check which peripheral has connected (HR or RSC), initiate DB
            // discovery, update LEDs status and resume scanning if necessary. */
            case BLE_GAP_EVT_CONNECTED:
            {					
    					
    						shutter_flags.ble_flags.gw_connected_flag = CONNECTED;
    
    					err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c, p_gap_evt->conn_handle, NULL);
                APP_ERROR_CHECK(err_code);
    					
    						current_conn_handle_central = p_gap_evt->conn_handle;
    
                err_code = ble_db_discovery_start(&m_db_disc, p_gap_evt->conn_handle);
                APP_ERROR_CHECK(err_code);
    
            } break;
    
            // Upon disconnection, reset the connection handle of the peer which disconnected, update
            // the LEDs status and start scanning again.
            case BLE_GAP_EVT_DISCONNECTED:
            {
    					
    						shutter_flags.ble_flags.gw_connected_flag = DISCONNECTED;
    
    						scan_start();		
    					
            } break;
    
            case BLE_GAP_EVT_TIMEOUT:
            {
                // We have not specified a timeout for scanning, so only connection attemps can timeout.
                if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
                {
    //                NRF_LOG_DEBUG("Connection request timed out.");
                }
            } break;
    
            case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
            {
                // Accept parameters requested by peer.
                err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                            &p_gap_evt->params.conn_param_update_request.conn_params);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
            {
                // Disconnect on GATT Client timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTS_EVT_TIMEOUT:
            {
                // Disconnect on GATT Server timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief   Function for handling BLE events from peripheral applications.
     * @details Updates the status LEDs used to report the activity of the peripheral applications.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     */
    static void on_ble_peripheral_evt(ble_evt_t const * p_ble_evt)
    {
        ret_code_t            err_code;
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    	
    		// Resets the System OFF sleep timeout
    		nrf_pwr_mgmt_feed();  
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
    //            NRF_LOG_INFO("Peripheral connected");
                on_connected(&p_ble_evt->evt.gap_evt);	
    				
    						shutter_flags.ble_flags.phone_connected_flag = CONNECTED;
    						shutter_flags.ble_flags.battery_volt_update_flag = SET;
    						power_led_ON();				
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
    //            NRF_LOG_INFO("Peripheral disconnected. conn_handle: 0x%x, reason: 0x%x",
    //                         p_gap_evt->conn_handle,
    //                         p_gap_evt->params.disconnected.reason);
    				
    						shutter_flags.ble_flags.phone_connected_flag = DISCONNECTED;
    						power_led_ON();
    
                on_disconnected(&p_ble_evt->evt.gap_evt);
    						
                break;
    						
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle,
                                                       BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
                                                       NULL,
                                                       NULL);
                APP_ERROR_CHECK(err_code);
                break;						
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
    //            NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    				
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gap_evt.conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
    //            NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
    //            NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief Function for handling advertising events.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        switch (ble_adv_evt)
        {
            case BLE_ADV_EVT_FAST:
            {
    //            NRF_LOG_INFO("Fast advertising.");
            } break;
    
            case BLE_ADV_EVT_IDLE:
            {
                ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
                APP_ERROR_CHECK(err_code);
            } break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief Function for checking whether a bluetooth stack event is an advertising timeout.
     *
     * @param[in] p_ble_evt Bluetooth stack event.
     */
    static bool ble_evt_is_advertising_timeout(ble_evt_t const * p_ble_evt)
    {
        return (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_SET_TERMINATED);
    }
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
    	
        uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        uint16_t role        = ble_conn_state_role(conn_handle);
    
        // Based on the role this device plays in the connection, dispatch to the right handler.
        if (role == BLE_GAP_ROLE_PERIPH || ble_evt_is_advertising_timeout(p_ble_evt))
        {
            on_ble_peripheral_evt(p_ble_evt);
        }
        else if ((role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT))
        {
            on_ble_central_evt(p_ble_evt);
        }
    }
    
    /**@brief LED Button client initialization.
     */
    static void lbs_c_init(void)
    {
        ret_code_t       err_code;
        ble_lbs_c_init_t lbs_c_init_obj;
    
        lbs_c_init_obj.evt_handler   = lbs_c_evt_handler;
        lbs_c_init_obj.p_gatt_queue  = &m_ble_gatt_queue;
        lbs_c_init_obj.error_handler = lbs_error_handler;
    
        err_code = ble_lbs_c_init(&m_ble_lbs_c, &lbs_c_init_obj);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupts.
     */
    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, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&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);
    }
    
    /**@brief Function for initializing the GAP.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device, including the device name, appearance, and the preferred connection parameters.
     */
    static void gap_params_init(void)
    {
        ret_code_t              err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = m_scan.conn_params.min_conn_interval;
        gap_conn_params.max_conn_interval = m_scan.conn_params.max_conn_interval;
        gap_conn_params.slave_latency     = m_scan.conn_params.slave_latency;
        gap_conn_params.conn_sup_timeout  = m_scan.conn_params.conn_sup_timeout;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_CONN_HANDLE_INVALID; // Start upon connection.
        cp_init.disconnect_on_fail             = true;
        cp_init.evt_handler                    = NULL;  // Ignore events.
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling database discovery events.
     *
     * @details This function is a callback function to handle events from the database discovery module.
     *          Depending on the UUIDs that are discovered, this function forwards the events
     *          to their respective services.
     *
     * @param[in] p_event  Pointer to the database discovery event.
     */
    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
        ble_db_discovery_t const * p_db = (ble_db_discovery_t *)p_evt->params.p_db_instance;
    
    		ble_lbs_on_db_disc_evt(&m_ble_lbs_c, p_evt);
    
        if (p_evt->evt_type == BLE_DB_DISCOVERY_AVAILABLE) {
    //        NRF_LOG_INFO("DB Discovery instance %p available on conn handle: %d",
    //                     p_db,
    //                     p_evt->conn_handle);
    //        NRF_LOG_INFO("Found %d services on conn_handle: %d",
    //                     p_db->srv_count,
    //                     p_evt->conn_handle);
        }
    }
    
    /**
     * @brief Database discovery initialization.
     */
    static void db_discovery_init(void)
    {
        ble_db_discovery_init_t db_init;
    
        memset(&db_init, 0, sizeof(ble_db_discovery_init_t));
    
        db_init.evt_handler  = db_disc_handler;
        db_init.p_gatt_queue = &m_ble_gatt_queue;
    
        ret_code_t err_code = ble_db_discovery_init(&db_init);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling Queued Write module errors.
     *
     * @details A pointer to this function is passed to each service that may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code that contains information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Function for handling write events to the LED characteristic.
     *
     * @param[in] p_lbs     Instance of LED Button Service to which the write applies.
     * @param[in] led_state Written/desired state of the LED.
     */
    static void led_write_handler(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t* cmd,uint8_t len)
    {
    	
    	packet_header* cmd_header;
    	uint16_t crc_16 = 0;
    	
    	// Resets the System OFF sleep timeout
    	nrf_pwr_mgmt_feed(); 
    	
    	cmd_header = (packet_header*)cmd;
    	
    	crc_16 = gen_crc16(cmd,len-2);
    	
    //	NRF_LOG_INFO("CRC=%x",crc_16);
    	
    	if(cmd_header->start_byte == START_BYTE)
    	{ 
    	
    //		NRF_LOG_INFO("Received start byte");
    		
    		Ikin_BLE_process_req_cmd(cmd_header,crc_16);      // Function defined outside main.c
    	
    	}
    
    }
    
    /**@brief Function for initializing services that are be used by the application.
     *
     * @details Initialize the Heart Rate, Battery and Device Information services.
     */
    static void services_init(void)
    {
    
        ret_code_t         err_code;
        ble_lbs_init_t     init;
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module instances.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        for (uint32_t i = 0; i < NRF_SDH_BLE_TOTAL_LINK_COUNT; i++)
        {
            err_code = nrf_ble_qwr_init(&m_qwr[i], &qwr_init);
            APP_ERROR_CHECK(err_code);
        }
    
        // Initialize LBS.
        init.led_write_handler = led_write_handler;
    		
        err_code = ble_lbs_init(&m_lbs, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_conn_state_init();
    		
        ble_bas_init_t bas_init_obj;
    
        memset(&bas_init_obj, 0, sizeof(bas_init_obj));
    
        bas_init_obj.evt_handler          = on_bas_evt;
        bas_init_obj.support_notification = true;
        bas_init_obj.p_report_ref         = NULL;
        bas_init_obj.initial_batt_level   = 100;
    
        bas_init_obj.bl_rd_sec        = SEC_OPEN;
        bas_init_obj.bl_cccd_wr_sec   = SEC_OPEN;
        bas_init_obj.bl_report_rd_sec = SEC_OPEN;
    
        err_code = ble_bas_init(&m_bas, &bas_init_obj);
        APP_ERROR_CHECK(err_code);		
    }
    
    /**@brief Function for initializing the advertising functionality.
     */
    static void advertising_init(void)
    {
    
        ret_code_t           err_code;
        ble_advdata_t        advdata;
        ble_advdata_t        srdata;
        ble_gap_adv_params_t adv_params;
    
    
        ble_uuid_t adv_uuids[] = {{LBS_UUID_SERVICE, m_lbs.uuid_type}};
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
    		
        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = true;
        advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
    	advdata.include_ble_device_addr = 1;
    
        memset(&srdata, 0, sizeof(srdata));
        srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        srdata.uuids_complete.p_uuids  = adv_uuids;	
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
        APP_ERROR_CHECK(err_code);
    
        // Start advertising.
        memset(&adv_params, 0, sizeof(adv_params));
        adv_params.p_peer_addr   = NULL;
        adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
        adv_params.interval      = APP_ADV_INTERVAL;
    
        adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        adv_params.duration        = APP_ADV_DURATION;
        adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
    	
    //	NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, 0);
    }
    
    /**@brief Function for handling the idle state (main loop). If there is no pending log operation,
              then sleeps until the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    /**@brief Function for initializing the timer.
     */
    static void timer_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    /* User defined Static Function definitions */
    /**
     * @brief Handler for background timer events.
     * @author Sachin
     * @date 02-01-24
     */
    
    static void background_timer_event_handler(nrf_timer_event_t event_type, void* p_context)
    {
    
        switch (event_type)
        {
            case NRF_TIMER_EVENT_COMPARE0: {
                
                    /***  RESET SWITCH  ***/                
                    if(!read_GPIO_pin(RESET_SWITCH)) {
    
                        reset_delay_cnt++;
                                        
                        switch_state.reset_sensor_status = SWITCH_PRESSED;                      
    
                    }
                    else {
    
                        if(reset_delay_cnt != 0) {
                            reset_delay_cnt = 0;
                        }
                        switch_state.reset_sensor_status = SWITCH_RELEASED; 
                        
                    }           
                
                    break;
                }
    
            default:
                    break;
        }
    }
    
    void config_background_timer(void)
    {
    
        uint32_t time_ms = 1; //Time(in miliseconds) between consecutive compare events.
        uint32_t time_ticks;
        uint32_t err_code = NRF_SUCCESS;
    
        //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
        nrf_drv_timer_config_t custom_timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        err_code = nrf_drv_timer_init(&BACKGROUND_TIMER, &custom_timer_cfg, background_timer_event_handler);
        APP_ERROR_CHECK(err_code);
    
        time_ticks = nrf_drv_timer_ms_to_ticks(&BACKGROUND_TIMER, time_ms);
    
        nrf_drv_timer_extended_compare(&BACKGROUND_TIMER, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    
        nrf_drv_timer_enable(&BACKGROUND_TIMER);
        
    }
    
    void wakeup_from_sleep_pin_init(void)
    {
        nrf_gpio_cfg_sense_input(NORMAL_WAKEUP_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
    }
    
    void reset_pin_init(void)
    {
        nrf_drv_gpiote_in_config_t reset_pin_config = NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(true);
        reset_pin_config.pull = NRF_GPIO_PIN_NOPULL;    
    
        nrf_drv_gpiote_in_init(RESET_SWITCH, &reset_pin_config, NULL);
    
        nrf_drv_gpiote_in_event_enable(RESET_SWITCH, true);
        
        nrf_gpio_cfg_sense_input(RESET_SWITCH, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE);
    }
     
    static void reset_switch_handler(void)
    {
        /* If reset_delay_cnt is greater than 5000, that means the reset switch is pressed for 5 seconds.
             Then intiating the soft reset  */
        if(reset_delay_cnt >= 5000) {           // reset_delay_cnt is incremented in timer handler when switch is pressed once
    
            reset_delay_cnt = 0;
            power_led_toggle_PURPLE();
            NVIC_SystemReset();
    
        }
    }   
    	
    /**@brief Function for initializing the application main entry.
     */
    int main(void)
    {
    	// Initialize.
    	timer_init();
    	power_management_init();
    	ble_stack_init();
    	scan_init();
    	gap_params_init();
    	gatt_init();	
    	services_init();
    	advertising_init();
    	conn_params_init();
    	db_discovery_init();
    	lbs_c_init();
    
        reset_pin_init();
        system_off_sleep_pin_init();  
    	config_background_timer();
    
    			
    	for(;;)									// Loop for ever
    	{
            reset_switch_handler();
    	}
    }

    In my system there is a feature to perform soft reset initiated by a switch press by the user. For that I have configured pin P0.26 as GPIO input with no pullup/pulldown and not interrupt. In the code I am checking that pin status in polling method. If the switch is pressed for 5 seconds, soft reset is performed. This feature is mentioned as 'normal switch mode'. The function 'reset_pin_init();' initialize the GPIO pin.

    I also want the system should go to system off sleep mode after 45 seconds of inactivity. For that I made some modifications in the sdk_config.h file as follows.

    // <e> NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED - Enable standby timeout.
    //==========================================================
    #ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED
    #define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_ENABLED 1
    #endif
    // <o> NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S - Standby timeout (in seconds). 
    // <i> Shutdown procedure will begin no earlier than after this number of seconds.
    
    #ifndef NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S
    #define NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S 45
    #endif
    
    // </e>

    To wakeup from the sleep I am using the same switch. But in the hardware the switch is also connected to P0.27. So in the function 'wakeup_from_sleep_pin_init()' the pin P0.27 is initialized as wakeup pin and is called initially. 

    Here P0.27 is configured as wakeup pin. But when system is awake any change in the pin, halt the code execution. And in this configuration the pin P0.26 in not working as GPIO input.

    Instead of using 2 pins, can not you try to use one pin and reconfigure it depending on the sleep or wake up mode?

    Initially I was doing so. In the for loop in main function, I was checking the value of 'm_standby_counter' and if it's near 'NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S' the function  'wakeup_from_sleep_pin_init()'  is called. For that I made the variable 'm_standby_counter' global in 'nrf_pwr_mgmt.c' file and declared as extern in main.c. The old main file is given below.

    /* Includes */
    
    /* Standard includes*/
    #include <stdint.h>
    #include <string.h>
    
    /* SDK includes */
    #include "boards.h"
    #include "nordic_common.h"
    #include "nrf_sdh.h"
    #include "nrf_sdh_soc.h"
    #include "nrf_sdh_ble.h"
    #include "app_timer.h"
    #include "ble.h"
    #include "ble_advdata.h"
    #include "ble_advertising.h"
    #include "ble_conn_params.h"
    #include "ble_db_discovery.h"
    #include "ble_conn_state.h"
    #include "ble_hci.h"
    #include "ble_lbs_c.h"
    #include "ble_lbs.h"
    #include "nrf_ble_gatt.h"
    #include "nrf_ble_qwr.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_ble_scan.h"
    #include "nrf_drv_timer.h"
    #include "nrf_delay.h"
    #include "nrf_pwr_mgmt.h"
    #include "nrf_log.h"
    #include "nrf_log_ctrl.h"
    #include "nrf_log_default_backends.h"
    #include "ble_bas.h"
    #include "nrf_drv_wdt.h"
    
    /* Define objects */
    NRF_BLE_GQ_DEF(m_ble_gatt_queue, NRF_SDH_BLE_CENTRAL_LINK_COUNT, NRF_BLE_GQ_QUEUE_SIZE);    /**< BLE GATT Queue instance. */
    NRF_BLE_GATT_DEF(m_gatt);                                                                   /**< GATT module instance. */
    NRF_BLE_QWRS_DEF(m_qwr, NRF_SDH_BLE_TOTAL_LINK_COUNT);                                      /**< Context for the Queued Write module.*/
    BLE_ADVERTISING_DEF(m_advertising);                                                         /**< Advertising module instance. */
    NRF_BLE_SCAN_DEF(m_scan);                                                                   /**< Scanning module instance. */
    BLE_DB_DISCOVERY_DEF(m_db_disc);                                                            /**< DB discovery module instance. */
    BLE_LBS_C_DEF(m_ble_lbs_c);                                                                 /**< Main structure used by the LBS client module. */
    BLE_LBS_DEF(m_lbs);                                                                         /**< LED Button Service instance. */
    BLE_BAS_DEF(m_bas);                                                                         /**< Battery service instance. */
    
    const nrf_drv_timer_t BACKGROUND_TIMER = NRF_DRV_TIMER_INSTANCE(2);                         /**< Timer instance. */
    
    #define NORMAL_WAKEUP_PIN   27
    #define RESET_PIN           26
    
    /* Define Variables */
    
    static uint8_t m_adv_handle = BLE_GAP_ADV_SET_HANDLE_NOT_SET;                               /**< Advertising handle used to identify an advertising set. */
    static uint8_t m_enc_advdata[BLE_GAP_ADV_SET_DATA_SIZE_MAX];                                /**< Buffer for storing an encoded advertising set. */
    static uint8_t m_enc_scan_response_data[BLE_GAP_ADV_SET_DATA_SIZE_MAX];                     /**< Buffer for storing an encoded scan data. */
    
    /**@brief Struct that contains pointers to the encoded advertising data. */
    static ble_gap_adv_data_t m_adv_data =
    {
        .adv_data =
        {
            .p_data = m_enc_advdata,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
        },
        .scan_rsp_data =
        {
            .p_data = m_enc_scan_response_data,
            .len    = BLE_GAP_ADV_SET_DATA_SIZE_MAX
    
        }
    };
    
    static ble_gap_scan_params_t m_scan_param =                                                 /**< Scan parameters requested for scanning and connection. */
    {
        .active        = 0x01,
        .interval      = NRF_BLE_SCAN_SCAN_INTERVAL,
        .window        = NRF_BLE_SCAN_SCAN_WINDOW,
        .filter_policy = BLE_GAP_SCAN_FP_ACCEPT_ALL,
        .timeout       = NRF_BLE_SCAN_SCAN_DURATION,
        .scan_phys     = BLE_GAP_PHY_1MBPS,
        .extended      = true,
    };
    
    uint16_t current_conn_handle_periph = BLE_CONN_HANDLE_INVALID;                              /**< Handle of the current connection from BLE central. */
    uint16_t current_conn_handle_central    = BLE_CONN_HANDLE_INVALID;                          /**< Handle of the current connection from BLE peripheral. */
    uint8_t event_packet_to_send[18];                                                           /**< Array to store event packet to send to gateway. */
    uint16_t reset_delay_cnt=0;                                                                 /**< Variable for storing reset delay count. */
    
    extern static uint16_t m_standby_counter;           // This variable is declared in nrf_pwr_mgmt.c file
    /* Function definitions */
    
    /**@brief Handles events from Battery update service
     */
    static void on_bas_evt(ble_bas_t * p_bas, ble_bas_evt_t * p_evt)
    {
        
    }
    
    /**@brief Function for handling asserts in the SoftDevice.
     *
     * @details This function is called in case of an assert in the SoftDevice.
     *
     * @warning This handler is an example only and is not meant for the final product. You need to analyze
     *          how your product is supposed to react in case of assert.
     * @warning On assert from the SoftDevice, the system can only recover on reset.
     *
     * @param[in] line_num     Line number of the failing assert call.
     * @param[in] p_file_name  File name of the failing assert call.
     */
    static void assert_nrf_callback(uint16_t line_num, const uint8_t * p_file_name)
    {
        app_error_handler(0xDEADBEEF, line_num, p_file_name);
    }
    
    
    /**@brief Function for handling the LED Button Service client errors.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void lbs_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Function for handling the Heart Rate Service Client
     *        Running Speed and Cadence Service Client.
     *
     * @param[in]   nrf_error   Error code containing information about what went wrong.
     */
    static void service_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    
    /**@brief Function for handling errors from the Connection Parameters module.
     *
     * @param[in] nrf_error  Error code containing information about what went wrong.
     */
    static void conn_params_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Handles events from scaning for peripherals
     */
    static void scan_evt_handler(scan_evt_t const * p_scan_evt)
    {
    
        ret_code_t err_code;
        
          ble_gap_evt_adv_report_t const * p_adv =  p_scan_evt->params.filter_match.p_adv_report;
        ble_gap_scan_params_t    const * p_scan_param = p_scan_evt->p_scan_params;
            
        switch(p_scan_evt->scan_evt_id)
        {
                   case NRF_BLE_SCAN_EVT_FILTER_MATCH:
            {
    
                        // Initiate connection.
                        err_code = sd_ble_gap_connect(&p_adv->peer_addr,
                                                                                    p_scan_param,
                                                                                    &m_scan.conn_params,
                                                                                    APP_BLE_CONN_CFG_TAG);
                        APP_ERROR_CHECK(err_code);
            } break;
            case NRF_BLE_SCAN_EVT_CONNECTING_ERROR:
                    {
                err_code = p_scan_evt->params.connecting_err.err_code;
                APP_ERROR_CHECK(err_code);
                    } break;
            default:
              break;
        }
    }
    
    /**@brief Handles events coming from the LED Button service central module.
     */
    static void lbs_c_evt_handler(ble_lbs_c_t * p_lbs_c, ble_lbs_c_evt_t * p_lbs_c_evt)
    {
        switch (p_lbs_c_evt->evt_type)
        {
            case BLE_LBS_C_EVT_DISCOVERY_COMPLETE:
            {
                ret_code_t err_code;
    
                err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c,
                                                    p_lbs_c_evt->conn_handle,
                                                    &p_lbs_c_evt->params.peer_db);
    //            NRF_LOG_INFO("LED Button service discovered on conn_handle 0x%x.", p_lbs_c_evt->conn_handle);
                        
                // LED Button service discovered. Enable notification of Button.
                err_code = ble_lbs_c_button_notif_enable(p_lbs_c);
                APP_ERROR_CHECK(err_code);
    
            } break; // BLE_LBS_C_EVT_DISCOVERY_COMPLETE
                    
            case BLE_LBS_C_EVT_BUTTON_NOTIFICATION:
            {
                        packet_header* cmd_header;
                        uint16_t crc_16 = 0;
                        uint16_t len=0;
                        len = p_lbs_c_evt->params.button.button_state[2];
    
                        cmd_header = (packet_header*)p_lbs_c_evt->params.button.button_state;
    
                        crc_16 = gen_crc16(p_lbs_c_evt->params.button.button_state,len-2);
    
                        if(cmd_header->start_byte == START_BYTE)
                        { 
    
                            process_ack_from_gw(cmd_header,crc_16);  // Function defined outside main.c
    
                        }                   
    
            } break; // BLE_LBS_C_EVT_BUTTON_NOTIFICATION               
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief Function for initialization the scanning and setting the filters.
     */
    static void scan_init(void)
    {
        ret_code_t          err_code;
        nrf_ble_scan_init_t init_scan;
    
        memset(&init_scan, 0, sizeof(init_scan));
    
        init_scan.connect_if_match = false;
        init_scan.conn_cfg_tag     = APP_BLE_CONN_CFG_TAG;
    //  init_scan.p_scan_param = &m_scan_param;
    
        err_code = nrf_ble_scan_init(&m_scan, &init_scan, scan_evt_handler);
        APP_ERROR_CHECK(err_code);
    
        err_code = nrf_ble_scan_filters_enable(&m_scan, NRF_BLE_SCAN_ADDR_FILTER, false);
        APP_ERROR_CHECK(err_code);
    
        if (target_dev_addr[0] != 0)
        {
            err_code = nrf_ble_scan_filter_set(&m_scan, SCAN_ADDR_FILTER, target_dev_addr);
            APP_ERROR_CHECK(err_code);
        }
    
    }
    
    /**@brief Function for initializing the advertising.
     */
    static void advertising_start(void)
    {
        
        ret_code_t err_code;
        
        err_code = sd_ble_gap_adv_start(m_adv_handle, APP_BLE_CONN_CFG_TAG);
    //  APP_ERROR_CHECK(err_code);
    
    }
    
    /**
    * @brief Function for force stopping the advertising.
    * @author Sachin
    * @date 02-08-23
    */
    static void advertising_stop(void)
    {
        
        ret_code_t err_code;
    
        err_code = sd_ble_gap_adv_stop(m_adv_handle);
    
        APP_ERROR_CHECK(err_code);
    
    }
    
    /**@brief Function for assigning new connection handle to available instance of QWR module.
     *
     * @param[in] conn_handle New connection handle.
     */
    static void multi_qwr_conn_handle_assign(uint16_t conn_handle)
    {
        for (uint32_t i = 0; i < NRF_SDH_BLE_TOTAL_LINK_COUNT; i++)
        {
            if (m_qwr[i].conn_handle == BLE_CONN_HANDLE_INVALID)
            {
                ret_code_t err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr[i], conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
            }
        }
    }
    
    /**@brief Function for handling the Connected event.
     *
     * @param[in] p_gap_evt GAP event received from the BLE stack.
     */
    static void on_connected(const ble_gap_evt_t * const p_gap_evt)
    {
        ret_code_t  err_code;
        uint32_t    periph_link_cnt = ble_conn_state_peripheral_conn_count(); // Number of peripheral links.
    
    //    NRF_LOG_INFO("Connection with link 0x%x established.", p_gap_evt->conn_handle);
        
        /**Connection handle is required to terminate the connection from the peripheral if an unauthorized
           peer(central device) tries to connect.
        *This   way, only the unauthorized peer gets kicked out, authorized peer devices that are currently connected to this perihperal 
           will maintan their connections.
          *@author - Akshay
          *@date - 01-06-23
        */
        current_conn_handle_periph = p_gap_evt->conn_handle; 
        // Assign connection handle to available instance of QWR module.
        for (uint32_t i = 0; i < NRF_SDH_BLE_PERIPHERAL_LINK_COUNT; i++)
        {
            if (m_qwr[i].conn_handle == BLE_CONN_HANDLE_INVALID)
            {
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr[i], p_gap_evt->conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
            }
        }
    
    
        if (periph_link_cnt == NRF_SDH_BLE_PERIPHERAL_LINK_COUNT)
        {
    
        }
        else
        {
            // Continue advertising. More connections can be established because the maximum link count has not been reached.
                advertising_start();        
            
        }
            
             nrf_drv_timer_enable(&TIME_SYNC_CHECK);
    }
    
    /**@brief Function for handling the Disconnected event.
     *
     * @param[in] p_gap_evt GAP event received from the BLE stack.
     */
    static void on_disconnected(ble_gap_evt_t const * const p_gap_evt)
    {
    //    ret_code_t  err_code;
        uint32_t    periph_link_cnt = ble_conn_state_peripheral_conn_count(); // Number of peripheral links.
    
    //    NRF_LOG_INFO("Connection 0x%x has been disconnected. Reason: 0x%X",
    //                 p_gap_evt->conn_handle,
    //                 p_gap_evt->params.disconnected.reason);
    
        if (periph_link_cnt == 0)
        {
    
        }
    
        if (periph_link_cnt == (NRF_SDH_BLE_PERIPHERAL_LINK_COUNT - 1))
        {
            // Advertising is not running when all connections are taken, and must therefore be started.
            advertising_start();
        }
    }
    
    /**@brief   Function for handling BLE events from the central application.
     *
     * @details This function parses scanning reports and initiates a connection to peripherals when a
     *          target UUID is found. It updates the status of LEDs used to report the central application
     *          activity.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     */
    static void on_ble_central_evt(ble_evt_t const * p_ble_evt)
    {
    
        ret_code_t err_code;
    
        // For readability.
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
    
        switch (p_ble_evt->header.evt_id)
        {
            // Upon connection, check which peripheral has connected (HR or RSC), initiate DB
            // discovery, update LEDs status and resume scanning if necessary. */
            case BLE_GAP_EVT_CONNECTED:
            {                   
                        
                            shutter_flags.ble_flags.gw_connected_flag = CONNECTED;
    
                        err_code = ble_lbs_c_handles_assign(&m_ble_lbs_c, p_gap_evt->conn_handle, NULL);
                APP_ERROR_CHECK(err_code);
                        
                            current_conn_handle_central = p_gap_evt->conn_handle;
    
                err_code = ble_db_discovery_start(&m_db_disc, p_gap_evt->conn_handle);
                APP_ERROR_CHECK(err_code);
    
            } break;
    
            // Upon disconnection, reset the connection handle of the peer which disconnected, update
            // the LEDs status and start scanning again.
            case BLE_GAP_EVT_DISCONNECTED:
            {
                        
                            shutter_flags.ble_flags.gw_connected_flag = DISCONNECTED;
    
                            scan_start();       
                        
            } break;
    
            case BLE_GAP_EVT_TIMEOUT:
            {
                // We have not specified a timeout for scanning, so only connection attemps can timeout.
                if (p_gap_evt->params.timeout.src == BLE_GAP_TIMEOUT_SRC_CONN)
                {
    //                NRF_LOG_DEBUG("Connection request timed out.");
                }
            } break;
    
            case BLE_GAP_EVT_CONN_PARAM_UPDATE_REQUEST:
            {
                // Accept parameters requested by peer.
                err_code = sd_ble_gap_conn_param_update(p_gap_evt->conn_handle,
                                            &p_gap_evt->params.conn_param_update_request.conn_params);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTC_EVT_TIMEOUT:
            {
                // Disconnect on GATT Client timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            case BLE_GATTS_EVT_TIMEOUT:
            {
                // Disconnect on GATT Server timeout event.
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
            } break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief   Function for handling BLE events from peripheral applications.
     * @details Updates the status LEDs used to report the activity of the peripheral applications.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     */
    static void on_ble_peripheral_evt(ble_evt_t const * p_ble_evt)
    {
        ret_code_t            err_code;
        ble_gap_evt_t const * p_gap_evt = &p_ble_evt->evt.gap_evt;
        
            // Resets the System OFF sleep timeout
            nrf_pwr_mgmt_feed();  
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
    //            NRF_LOG_INFO("Peripheral connected");
                on_connected(&p_ble_evt->evt.gap_evt);  
                    
                            shutter_flags.ble_flags.phone_connected_flag = CONNECTED;
                            shutter_flags.ble_flags.battery_volt_update_flag = SET;
                            power_led_ON();             
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
    //            NRF_LOG_INFO("Peripheral disconnected. conn_handle: 0x%x, reason: 0x%x",
    //                         p_gap_evt->conn_handle,
    //                         p_gap_evt->params.disconnected.reason);
                    
                            shutter_flags.ble_flags.phone_connected_flag = DISCONNECTED;
                            power_led_ON();
    
                on_disconnected(&p_ble_evt->evt.gap_evt);
                            
                break;
                            
            case BLE_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(p_ble_evt->evt.gap_evt.conn_handle,
                                                       BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP,
                                                       NULL,
                                                       NULL);
                APP_ERROR_CHECK(err_code);
                break;                      
    
            case BLE_GAP_EVT_PHY_UPDATE_REQUEST:
            {
    //            NRF_LOG_DEBUG("PHY update request.");
                ble_gap_phys_t const phys =
                {
                    .rx_phys = BLE_GAP_PHY_AUTO,
                    .tx_phys = BLE_GAP_PHY_AUTO,
                };
                err_code = sd_ble_gap_phy_update(p_ble_evt->evt.gap_evt.conn_handle, &phys);
                APP_ERROR_CHECK(err_code);
            } break;
                    
            case BLE_GATTS_EVT_SYS_ATTR_MISSING:
                // No system attributes have been stored.
                err_code = sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gap_evt.conn_handle, NULL, 0, 0);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTC_EVT_TIMEOUT:
                // Disconnect on GATT Client timeout event.
    //            NRF_LOG_DEBUG("GATT Client Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gattc_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GATTS_EVT_TIMEOUT:
                // Disconnect on GATT Server timeout event.
    //            NRF_LOG_DEBUG("GATT Server Timeout.");
                err_code = sd_ble_gap_disconnect(p_ble_evt->evt.gatts_evt.conn_handle,
                                                 BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
                APP_ERROR_CHECK(err_code);
                break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief Function for handling advertising events.
     *
     * @param[in] ble_adv_evt  Advertising event.
     */
    static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
    {
        switch (ble_adv_evt)
        {
            case BLE_ADV_EVT_FAST:
            {
    //            NRF_LOG_INFO("Fast advertising.");
            } break;
    
            case BLE_ADV_EVT_IDLE:
            {
                ret_code_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
                APP_ERROR_CHECK(err_code);
            } break;
    
            default:
                // No implementation needed.
                break;
        }
    }
    
    /**@brief Function for checking whether a bluetooth stack event is an advertising timeout.
     *
     * @param[in] p_ble_evt Bluetooth stack event.
     */
    static bool ble_evt_is_advertising_timeout(ble_evt_t const * p_ble_evt)
    {
        return (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_SET_TERMINATED);
    }
    
    /**@brief Function for handling BLE events.
     *
     * @param[in]   p_ble_evt   Bluetooth stack event.
     * @param[in]   p_context   Unused.
     */
    static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        
        uint16_t conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
        uint16_t role        = ble_conn_state_role(conn_handle);
    
        // Based on the role this device plays in the connection, dispatch to the right handler.
        if (role == BLE_GAP_ROLE_PERIPH || ble_evt_is_advertising_timeout(p_ble_evt))
        {
            on_ble_peripheral_evt(p_ble_evt);
        }
        else if ((role == BLE_GAP_ROLE_CENTRAL) || (p_ble_evt->header.evt_id == BLE_GAP_EVT_ADV_REPORT))
        {
            on_ble_central_evt(p_ble_evt);
        }
    }
    
    /**@brief LED Button client initialization.
     */
    static void lbs_c_init(void)
    {
        ret_code_t       err_code;
        ble_lbs_c_init_t lbs_c_init_obj;
    
        lbs_c_init_obj.evt_handler   = lbs_c_evt_handler;
        lbs_c_init_obj.p_gatt_queue  = &m_ble_gatt_queue;
        lbs_c_init_obj.error_handler = lbs_error_handler;
    
        err_code = ble_lbs_c_init(&m_ble_lbs_c, &lbs_c_init_obj);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing the BLE stack.
     *
     * @details Initializes the SoftDevice and the BLE event interrupts.
     */
    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, &ram_start);
        APP_ERROR_CHECK(err_code);
    
        // Enable BLE stack.
        err_code = nrf_sdh_ble_enable(&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);
    }
    
    /**@brief Function for initializing the GAP.
     *
     * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
     *          device, including the device name, appearance, and the preferred connection parameters.
     */
    static void gap_params_init(void)
    {
        ret_code_t              err_code;
        ble_gap_conn_params_t   gap_conn_params;
        ble_gap_conn_sec_mode_t sec_mode;
    
        BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode);
    
        err_code = sd_ble_gap_device_name_set(&sec_mode,
                                              (const uint8_t *)DEVICE_NAME,
                                              strlen(DEVICE_NAME));
        APP_ERROR_CHECK(err_code);
    
        memset(&gap_conn_params, 0, sizeof(gap_conn_params));
    
        gap_conn_params.min_conn_interval = m_scan.conn_params.min_conn_interval;
        gap_conn_params.max_conn_interval = m_scan.conn_params.max_conn_interval;
        gap_conn_params.slave_latency     = m_scan.conn_params.slave_latency;
        gap_conn_params.conn_sup_timeout  = m_scan.conn_params.conn_sup_timeout;
    
        err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing the GATT module.
     */
    static void gatt_init(void)
    {
        ret_code_t err_code = nrf_ble_gatt_init(&m_gatt, NULL);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing the Connection Parameters module.
     */
    static void conn_params_init(void)
    {
        ret_code_t             err_code;
        ble_conn_params_init_t cp_init;
    
        memset(&cp_init, 0, sizeof(cp_init));
    
        cp_init.p_conn_params                  = NULL;
        cp_init.first_conn_params_update_delay = FIRST_CONN_PARAMS_UPDATE_DELAY;
        cp_init.next_conn_params_update_delay  = NEXT_CONN_PARAMS_UPDATE_DELAY;
        cp_init.max_conn_params_update_count   = MAX_CONN_PARAMS_UPDATE_COUNT;
        cp_init.start_on_notify_cccd_handle    = BLE_CONN_HANDLE_INVALID; // Start upon connection.
        cp_init.disconnect_on_fail             = true;
        cp_init.evt_handler                    = NULL;  // Ignore events.
        cp_init.error_handler                  = conn_params_error_handler;
    
        err_code = ble_conn_params_init(&cp_init);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling database discovery events.
     *
     * @details This function is a callback function to handle events from the database discovery module.
     *          Depending on the UUIDs that are discovered, this function forwards the events
     *          to their respective services.
     *
     * @param[in] p_event  Pointer to the database discovery event.
     */
    static void db_disc_handler(ble_db_discovery_evt_t * p_evt)
    {
        ble_db_discovery_t const * p_db = (ble_db_discovery_t *)p_evt->params.p_db_instance;
    
            ble_lbs_on_db_disc_evt(&m_ble_lbs_c, p_evt);
    
        if (p_evt->evt_type == BLE_DB_DISCOVERY_AVAILABLE) {
    //        NRF_LOG_INFO("DB Discovery instance %p available on conn handle: %d",
    //                     p_db,
    //                     p_evt->conn_handle);
    //        NRF_LOG_INFO("Found %d services on conn_handle: %d",
    //                     p_db->srv_count,
    //                     p_evt->conn_handle);
        }
    }
    
    /**
     * @brief Database discovery initialization.
     */
    static void db_discovery_init(void)
    {
        ble_db_discovery_init_t db_init;
    
        memset(&db_init, 0, sizeof(ble_db_discovery_init_t));
    
        db_init.evt_handler  = db_disc_handler;
        db_init.p_gatt_queue = &m_ble_gatt_queue;
    
        ret_code_t err_code = ble_db_discovery_init(&db_init);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for handling Queued Write module errors.
     *
     * @details A pointer to this function is passed to each service that may need to inform the
     *          application about an error.
     *
     * @param[in]   nrf_error   Error code that contains information about what went wrong.
     */
    static void nrf_qwr_error_handler(uint32_t nrf_error)
    {
        APP_ERROR_HANDLER(nrf_error);
    }
    
    /**@brief Function for handling write events to the LED characteristic.
     *
     * @param[in] p_lbs     Instance of LED Button Service to which the write applies.
     * @param[in] led_state Written/desired state of the LED.
     */
    static void led_write_handler(uint16_t conn_handle, ble_lbs_t * p_lbs, uint8_t* cmd,uint8_t len)
    {
        
        packet_header* cmd_header;
        uint16_t crc_16 = 0;
        
        // Resets the System OFF sleep timeout
        nrf_pwr_mgmt_feed(); 
        
        cmd_header = (packet_header*)cmd;
        
        crc_16 = gen_crc16(cmd,len-2);
        
    //  NRF_LOG_INFO("CRC=%x",crc_16);
        
        if(cmd_header->start_byte == START_BYTE)
        { 
        
    //      NRF_LOG_INFO("Received start byte");
            
            Ikin_BLE_process_req_cmd(cmd_header,crc_16);      // Function defined outside main.c
        
        }
    
    }
    
    /**@brief Function for initializing services that are be used by the application.
     *
     * @details Initialize the Heart Rate, Battery and Device Information services.
     */
    static void services_init(void)
    {
    
        ret_code_t         err_code;
        ble_lbs_init_t     init;
        nrf_ble_qwr_init_t qwr_init = {0};
    
        // Initialize Queued Write Module instances.
        qwr_init.error_handler = nrf_qwr_error_handler;
    
        for (uint32_t i = 0; i < NRF_SDH_BLE_TOTAL_LINK_COUNT; i++)
        {
            err_code = nrf_ble_qwr_init(&m_qwr[i], &qwr_init);
            APP_ERROR_CHECK(err_code);
        }
    
        // Initialize LBS.
        init.led_write_handler = led_write_handler;
            
        err_code = ble_lbs_init(&m_lbs, &init);
        APP_ERROR_CHECK(err_code);
    
        ble_conn_state_init();
            
        ble_bas_init_t bas_init_obj;
    
        memset(&bas_init_obj, 0, sizeof(bas_init_obj));
    
        bas_init_obj.evt_handler          = on_bas_evt;
        bas_init_obj.support_notification = true;
        bas_init_obj.p_report_ref         = NULL;
        bas_init_obj.initial_batt_level   = 100;
    
        bas_init_obj.bl_rd_sec        = SEC_OPEN;
        bas_init_obj.bl_cccd_wr_sec   = SEC_OPEN;
        bas_init_obj.bl_report_rd_sec = SEC_OPEN;
    
        err_code = ble_bas_init(&m_bas, &bas_init_obj);
        APP_ERROR_CHECK(err_code);      
    }
    
    /**@brief Function for initializing the advertising functionality.
     */
    static void advertising_init(void)
    {
    
        ret_code_t           err_code;
        ble_advdata_t        advdata;
        ble_advdata_t        srdata;
        ble_gap_adv_params_t adv_params;
    
    
        ble_uuid_t adv_uuids[] = {{LBS_UUID_SERVICE, m_lbs.uuid_type}};
    
        // Build and set advertising data.
        memset(&advdata, 0, sizeof(advdata));
            
        advdata.name_type          = BLE_ADVDATA_FULL_NAME;
        advdata.include_appearance = true;
        advdata.flags              = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
        advdata.include_ble_device_addr = 1;
    
        memset(&srdata, 0, sizeof(srdata));
        srdata.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
        srdata.uuids_complete.p_uuids  = adv_uuids; 
    
        err_code = ble_advdata_encode(&advdata, m_adv_data.adv_data.p_data, &m_adv_data.adv_data.len);
        APP_ERROR_CHECK(err_code);
    
        err_code = ble_advdata_encode(&srdata, m_adv_data.scan_rsp_data.p_data, &m_adv_data.scan_rsp_data.len);
        APP_ERROR_CHECK(err_code);
    
        // Start advertising.
        memset(&adv_params, 0, sizeof(adv_params));
        adv_params.p_peer_addr   = NULL;
        adv_params.filter_policy = BLE_GAP_ADV_FP_ANY;
        adv_params.interval      = APP_ADV_INTERVAL;
    
        adv_params.properties.type = BLE_GAP_ADV_TYPE_CONNECTABLE_SCANNABLE_UNDIRECTED;
        adv_params.duration        = APP_ADV_DURATION;
        adv_params.primary_phy     = BLE_GAP_PHY_1MBPS;
    
        err_code = sd_ble_gap_adv_set_configure(&m_adv_handle, &m_adv_data, &adv_params);
        APP_ERROR_CHECK(err_code);
    }
    
    /**@brief Function for initializing power management.
     */
    static void power_management_init(void)
    {
        ret_code_t err_code;
        err_code = nrf_pwr_mgmt_init();
        APP_ERROR_CHECK(err_code);
        
    //  NRF_PWR_MGMT_HANDLER_REGISTER(shutdown_handler, 0);
    }
    
    /**@brief Function for handling the idle state (main loop). If there is no pending log operation,
              then sleeps until the next event occurs.
     */
    static void idle_state_handle(void)
    {
        if (NRF_LOG_PROCESS() == false)
        {
            nrf_pwr_mgmt_run();
        }
    }
    
    /**@brief Function for initializing the timer.
     */
    static void timer_init(void)
    {
        ret_code_t err_code = app_timer_init();
        APP_ERROR_CHECK(err_code);
    }
    
    /* User defined Static Function definitions */
    /**
     * @brief Handler for background timer events.
     * @author Sachin
     * @date 02-01-24
     */
    
    static void background_timer_event_handler(nrf_timer_event_t event_type, void* p_context)
    {
    
        switch (event_type)
        {
            case NRF_TIMER_EVENT_COMPARE0: {
                
                    /***  RESET SWITCH  ***/                
                    if(!read_GPIO_pin(RESET_SWITCH)) {
    
                        reset_delay_cnt++;
                                        
                        switch_state.reset_sensor_status = SWITCH_PRESSED;                      
    
                    }
                    else {
    
                        if(reset_delay_cnt != 0) {
                            reset_delay_cnt = 0;
                        }
                        switch_state.reset_sensor_status = SWITCH_RELEASED; 
                        
                    }           
                
                    break;
                }
    
            default:
                    break;
        }
    }
    
    void config_background_timer(void)
    {
    
        uint32_t time_ms = 1; //Time(in miliseconds) between consecutive compare events.
        uint32_t time_ticks;
        uint32_t err_code = NRF_SUCCESS;
    
        //Configure TIMER_LED for generating simple light effect - leds on board will invert his state one after the other.
        nrf_drv_timer_config_t custom_timer_cfg = NRF_DRV_TIMER_DEFAULT_CONFIG;
        err_code = nrf_drv_timer_init(&BACKGROUND_TIMER, &custom_timer_cfg, background_timer_event_handler);
        APP_ERROR_CHECK(err_code);
    
        time_ticks = nrf_drv_timer_ms_to_ticks(&BACKGROUND_TIMER, time_ms);
    
        nrf_drv_timer_extended_compare(&BACKGROUND_TIMER, NRF_TIMER_CC_CHANNEL0, time_ticks, NRF_TIMER_SHORT_COMPARE0_CLEAR_MASK, true);
    
        nrf_drv_timer_enable(&BACKGROUND_TIMER);
        
    }
    
    void wakeup_from_sleep_pin_init(void)
    {
        nrf_gpio_cfg_sense_input(NORMAL_WAKEUP_PIN, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_SENSE_LOW);
    }
    
    void reset_pin_init(void)
    {
        nrf_drv_gpiote_in_config_t reset_pin_config = NRFX_GPIOTE_RAW_CONFIG_IN_SENSE_HITOLO(true);
        reset_pin_config.pull = NRF_GPIO_PIN_NOPULL;    
    
        nrf_drv_gpiote_in_init(RESET_SWITCH, &reset_pin_config, NULL);
    
        nrf_drv_gpiote_in_event_enable(RESET_SWITCH, true);
        
        nrf_gpio_cfg_sense_input(RESET_SWITCH, NRF_GPIO_PIN_NOPULL, NRF_GPIO_PIN_NOSENSE);
    }
     
    static void reset_switch_handler(void)
    {
        /* If reset_delay_cnt is greater than 5000, that means the reset switch is pressed for 5 seconds.
             Then intiating the soft reset  */
        if(reset_delay_cnt >= 5000) {           // reset_delay_cnt is incremented in timer handler when switch is pressed once
    
            reset_delay_cnt = 0;
            power_led_toggle_PURPLE();
            NVIC_SystemReset();
    
        }
    }   
        
    /**@brief Function for initializing the application main entry.
     */
    int main(void)
    {
        // Initialize.
        timer_init();
        power_management_init();
        ble_stack_init();
        scan_init();
        gap_params_init();
        gatt_init();    
        services_init();
        advertising_init();
        conn_params_init();
        db_discovery_init();
        lbs_c_init();
    
        reset_pin_init();
        config_background_timer();
    
                
        for(;;)                                 // Loop for ever
        {
            reset_switch_handler();
    
            if(m_standby_counter >= (NRF_PWR_MGMT_CONFIG_STANDBY_TIMEOUT_S-1)) {
    
                system_off_sleep_pin_init();  
            }
        }
    }

    But here, sometimes that if condition is skipped and directly goes to sleep without configuring any wakeup pin. To overcome this problem I changed the hardware and added two pins. So we can configure wakeup pin as well as reset pin initially itself.

    Thanks

    Sachin

Related