sd_power_system_off is giving Gatt Connection Error instead of going in sleep

I am utilizing the nRF52811 with SDK version 16.00 for a project. However, I have encountered an issue related to the function sd_power_system_off, which is intended to put the device into a sleep mode. Instead of entering sleep mode, the function triggers an error labeled as "GATT_CONN_ERROR" on the nRF Connect mobile application.

I have taken the necessary steps to debug the issue, and through this process, I have confirmed that the sd_power_system_off function is indeed the source of the problem. To resolve this, I have conducted extensive research on various forums, but unfortunately, I have not yet identified a suitable solution to rectify this specific error.

In my pursuit of resolving the problem, I considered the potential influence of debugging on the deep sleep functionality. However, even after disconnecting the debugger and allowing the nRF52811 to run independently, the error persists unchanged.

For contextual clarity, I have provided a segment of the relevant code below, where I am implementing the deep sleep functionality:
Given the current situation, I am seeking assistance to address this issue and enable the intended sleep functionality on the nRF52811. Any insights, guidance, or recommendations that can be provided regarding this matter would be greatly appreciated. Thank you in advance for your help.

static void app_timer_callback(void* p_context)
{
    // Add your desired functionality here
}

static void timer_timeout_handler( void* p_context)
{ret_code_t err_code;

  UNUSED_PARAMETER(p_context);
nrf_timer_event_t event_type;

if(normalmode==false){
    timer_counter += 5000;
  NRF_LOG_DEBUG(" = timer_counter %d .",timer_counter );
  NRF_LOG_INFO(" = timer_counter %d.",timer_counter );
     
 if( timer_counter >= 120000)
   {

    
    NRF_LOG_DEBUG(" done;.");
  NRF_LOG_INFO(" done;.");

      app_timer_stop(m_app_timer);
 NRF_LOG_DEBUG(" cleared.");
  NRF_LOG_INFO(" cleared.");

// Configure the App Timer for the desired time interval (5 minutes)
interval_ms =  300 * 1000;  // 5 minutes
err_code = app_timer_start(m_app_timer, APP_TIMER_TICKS(interval_ms), NULL);
APP_ERROR_CHECK(err_code);
        
    NRF_LOG_DEBUG(" shifted.");
  NRF_LOG_INFO(" shifted.");
 }

    }

    else if (normalmode==true){
    if(f1<0.05 && f2<0.05 && f3<0.05 && f4<0.05){
    ds_counter+=5000;
    if(ds_counter>=5000){

  err_code = app_timer_stop(m_app_timer);
APP_ERROR_CHECK(err_code);
//sleep_mode_enter();
    // Go to system-off mode (this function will not return; wakeup will cause a reset).
    err_code = sd_power_system_off();
     if (err_code != NRF_SUCCESS) {
        NRF_LOG_WARNING("sd_power_system_off() failed, errCode=0x%x\n", err_code);
        return;
    //APP_ERROR_CHECK(err_code);

}}}}}
    

Parents
  • Hi,

    First, I would like to point out, that if you put the nRF52811 into system off sleep while it's in a connection, then it's natural to expect the other side of the connection to result in a GATT_CONN_ERROR as the connection will be disrupted. Before you go to sleep, you should send a disconnect event, by disconnecting from the peer. 

    Another important point is that nRF52811 will only emulate deep sleep when the debugger is connected, you need to disconnect the debugger for it to actually enter deep sleep.

     

    regards

    Jared 

  • Hi Jared,
    Thank you so much for your time and help.
    I have another question or favor to ask. Can you please explain how can I send a disconnect event by disconnecting from peer.

  • Hi Jared,
    Results are still same, is there any solution of this problem?

  • Hi,

    Can you show me how you implemented it?

    regards

    Jared 

  • static void ble_evt_handler(ble_evt_t const * p_ble_evt, void * p_context)
    {
        uint32_t err_code;
    
        switch (p_ble_evt->header.evt_id)
        {
            case BLE_GAP_EVT_CONNECTED:
                NRF_LOG_INFO("Connected");
                err_code = bsp_indication_set(BSP_INDICATE_CONNECTED);
                APP_ERROR_CHECK(err_code);
                m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
                err_code = nrf_ble_qwr_conn_handle_assign(&m_qwr, m_conn_handle);
                APP_ERROR_CHECK(err_code);
                break;
    
            case BLE_GAP_EVT_DISCONNECTED:
            NRF_LOG_INFO("Disconnected, reason %d.",
                              p_ble_evt->evt.gap_evt.params.disconnected.reason);
        
                m_conn_handle = BLE_CONN_HANDLE_INVALID;
                sd_power_system_off();
                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_GAP_EVT_SEC_PARAMS_REQUEST:
                // Pairing not supported
                err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
                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(m_conn_handle, NULL, 0, 0);
                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.
                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;
        }
    }

  • Hi,

    Can you use the nRF Sniffer and provide a sniffer trace of the communication when you go to system off sleep?

    regards
    Jared 

  • I don't know how to use nRF Sniffer, and i don't have USB dongle either

Reply Children
  • Hi,

    So I tried reproducing this by using a devkit and the ble_app_hrs example from the nRF5SDK.

    I tried:

    1. Disconnecting gracefully by sending a disconnection event to the mobile phone. This is done by pressing button 1, which will disconnect by calling sd_ble_gap_disconnect(). See the BSP_EVENT_DISCONNECT case in the ble_app_hrs example to see how it's implemented.
    2. Disconnecting by turning off the device, this will simulate a device crashing. No disconnecting event is then sent to the peer.

    In the first case the DK sent a disconnect event to the peer and the connection was disconnected gracefully, no error reported.

    In the second case, the DK never sends a disconnection event and the log is terminated after a connection TIMEOUT which will result in an error,.

    The picture below shows first a connection then case 1 where I disconnect gracefully, no error reported. Next, it shows another connection event and the device "crashing" resulting in an timeout error.

    What kind of phone are you using? How a disconnection event is handled can be dependent on the specific phone used.

    If you have an extra DK then you could use it for nRF Sniffer, I think the only way of actually knowing what happens is to take a sniffer trace.  

    regards

    Jared
     

  • Hi Jared, 
    Thank you for your help, 
    The error is gone now but i can't wake up the device with a GPIO(pin 18) now , Please see if you can let me know where I am wrong .
    Here is my code for sleep mode

    static void sleep_mode_enter(void)
    {
     nrf_gpio_cfg_input(18, NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_sense_input(18, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
    
     uint32_t err_code;
        sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    
        while(m_conn_handle != BLE_CONN_HANDLE_INVALID)
        {
       
          app_sched_execute();
        }
    
     // Go to system-off mode (this function will not return; wakeup will cause a reset).
        err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);
    
    }

  • I also tried this,

    static void sleep_mode_enter(void)
    {
     nrf_gpio_cfg_input(18, NRF_GPIO_PIN_PULLUP);
    nrf_gpio_cfg_sense_input(18, NRF_GPIO_PIN_PULLUP, NRF_GPIO_PIN_SENSE_LOW);
    
     uint32_t err_code;
        sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    
        if(m_conn_handle != BLE_CONN_HANDLE_INVALID)
        {
          // Poll the application scheduler to execute the main loop 
          // This will ensure that the disconnect event is handled properly by lower levels of the application
         // app_sched_execute();
     sd_app_evt_wait();
        }
    
     // Go to system-off mode (this function will not return; wakeup will cause a reset).
       err_code = sd_power_system_off();
        APP_ERROR_CHECK(err_code);
    
    }

    but it gives the same error ERROR(0X8) GATT CONN TIMEOUT
    but wakes up on GPIO sensing low

  • Hi,

    You should also add nrf_gpio_cfg_sense_set(),

    regards

    Jared 

  • Hi, 
    I tried adding this but same situation is persisting. Any other suggestions that i can try?

Related