This post is older than 2 years and might not be relevant anymore
More Info: Consider searching for newer posts

nRF52840 Pair with static password + Bond always be timeout disconnect

   My board is nRF52840 + S140 + nRF5_SDK_15.2.0_9412b96, my configue as below picture and file "ywk_bsp_ble.c" .

   When nRF Connect APP connect my device, it alway be disconnected, please see the log picture.

   I don't know which parameters is error, please help me! Thanks! 

/** - Start - Copyright (C), 2018-2038, YWKang Tech. Co., Ltd. 2018 *****************************
 *
 *  File Name: bsp_ble.c
 *
 *  Function: BLE �͹�������
 *
 *  Created: 2019-04-27
 *
 *  Author: Terry Tan
 *
 *  Modify:
 *
 *  <Date>          <Author>       <version >        <Desc>
 * 2019-04-27         XXXX           V01.00
 *
 **************************************************************************************************/
/** Include ***************************************************************************************/
#include "ywk_bsp_ble.h"

#include "boards.h"
#include "utils.h"
#include "app_timer.h"

#include "ble_advdata.h"
#include "ble_advertising.h"
#include "ble_conn_params.h"
#include "ble_conn_state.h"
#include "ble_nus.h"
#include "ble_dfu.h"

#include "nrf_power.h"
#include "nrf_sdh.h"
#include "nrf_sdh_soc.h"
#include "nrf_sdh_ble.h"
#include "nrf_ble_gatt.h"
#include "nrf_ble_qwr.h"
//#include "nrf_ble_bms.h"
//#include "nrf_ble_lesc.h"
#include "nrf_pwr_mgmt.h"
#include "nrf_dfu_ble_svci_bond_sharing.h"
#include "nrf_svci_async_function.h"
#include "nrf_svci_async_handler.h"
#include "nrf_bootloader_info.h"

//#include "peer_manager.h"
//#include "peer_manager_handler.h"

#include "ywk_private.h"

#include "nrf_log.h"
#include "nrf_log_ctrl.h"
#include "nrf_log_default_backends.h"

#include "ywk_bsp_debug.h"


/** Macro define **********************************************************************************/
/* --- ������nRF SDK ����ĺ� --- */
#define DEVICE_NAME                     "YWK_WD2B"                       /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE           BLE_UUID_TYPE_BLE//BLE_UUID_TYPE_VENDOR_BEGIN                  /**< UUID type for the Nordic UART Service (vendor specific). */

#define APP_BLE_CONN_CFG_TAG            1                                /**< A tag identifying the SoftDevice BLE configuration. */
#define APP_BLE_OBSERVER_PRIO           3                                /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_ADV_INTERVAL                1600                             /**< The advertising interval (in units of 0.625 ms. This value corresponds to 100 ms). */
#define APP_ADV_DURATION                0//18000                         /**< The advertising duration (180 seconds) in units of 10 milliseconds. */

#define MIN_CONN_INTERVAL               MSEC_TO_UNITS(500, UNIT_1_25_MS)  /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL               MSEC_TO_UNITS(1000, UNIT_1_25_MS) /**< Maximum acceptable connection interval (75 ms), Connection interval uses 1.25 ms units. */
#define SLAVE_LATENCY                   0                                /**< Slave latency. */
#define CONN_SUP_TIMEOUT                MSEC_TO_UNITS(4000, UNIT_10_MS)  /**< Connection supervisory timeout (4 seconds), Supervision Timeout uses 10 ms units. */
#define FIRST_CONN_PARAMS_UPDATE_DELAY  APP_TIMER_TICKS(5000)            /**< Time from initiating event ( connect or start of notification) to first time sd_ble_gap_conn_param_update is called (5 seconds). */
#define NEXT_CONN_PARAMS_UPDATE_DELAY   APP_TIMER_TICKS(30000)           /**< Time between each call to sd_ble_gap_conn_param_update after the first call (30 seconds). */
#define MAX_CONN_PARAMS_UPDATE_COUNT    3                                /**< Number of attempts before giving up the connection parameter negotiation. */

#define SEC_PARAM_BOND                  1                                /**< Perform bonding. */
#define SEC_PARAM_MITM                  1                                /**< Man In The Middle protection not required. */
#define SEC_PARAM_LESC                  0                                /**< LE Secure Connections not enabled. */
#define SEC_PARAM_KEYPRESS              0                                /**< Keypress notifications not enabled. */
#define SEC_PARAM_IO_CAPABILITIES       BLE_GAP_IO_CAPS_DISPLAY_ONLY     /**< No I/O capabilities. */
#define SEC_PARAM_OOB                   0                                /**< Out Of Band data not available. */
#define SEC_PARAM_MIN_KEY_SIZE          7                                /**< Minimum encryption key size. */
#define SEC_PARAM_MAX_KEY_SIZE          16                               /**< Maximum encryption key size. */

#define DEAD_BEEF                       0xDEADBEEF                       /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
#define BLE_OPT_PARAM_ENABLE            0


/* --- �������Լ��ڲ�����ĺ� --- */
#define BLE_STATIC_PASSKEY_EN           1
#define BLE_ADV_NAME_SN_NUM				4			// �㲥�������豸���к�ĩNλ
#define BLE_PAIRING_PASSKEY    			"888888" 	// ��Ծ�̬����

/** Type define ***********************************************************************************/
typedef struct
{
	struct
	{
		uint8_t rx_done  :1;	// ������ɱ��
		uint8_t reserve  :7;
	}flag;

	uint8_t* buf;
	uint16_t buf_size;
	uint16_t buf_ptr;
}tBleRxBlk;

typedef struct
{
	struct
	{
		uint8_t txing	 :1;	// ���ڷ��ͱ��
		uint8_t reserve  :7;
	}flag;

	uint8_t* buf;
	uint16_t tx_len;
	uint16_t tx_buf_ptr;
}tBleTxBlk;


/** Constant **************************************************************************************/
/** Variable **************************************************************************************/
BLE_NUS_DEF(m_nus, NRF_SDH_BLE_TOTAL_LINK_COUNT);                                   /**< BLE NUS service instance. */
NRF_BLE_GATT_DEF(m_gatt);                                                           /**< GATT module instance. */
NRF_BLE_QWR_DEF(m_qwr);                                                             /**< Context for the Queued Write module.*/
BLE_ADVERTISING_DEF(m_advertising);                                                 /**< Advertising module instance. */

//static ble_conn_state_user_flag_id_t m_bms_bonds_to_delete;                         //!< Flags used to identify bonds that should be deleted.
static uint16_t   m_conn_handle          = BLE_CONN_HANDLE_INVALID;                 /**< Handle of the current connection. */
static uint16_t   m_ble_nus_max_data_len = BLE_GATT_ATT_MTU_DEFAULT - 3;            /**< Maximum length of data (in bytes) that can be transmitted to the peer by the Nordic UART service module. */
static ble_uuid_t m_adv_uuids[]          =                                          /**< Universally unique service identifier. */
{
	//{BLE_UUID_DEVICE_INFORMATION_SERVICE, BLE_UUID_TYPE_BLE    },
    {BLE_UUID_NUS_SERVICE,                NUS_SERVICE_UUID_TYPE},
};

#if BLE_ADV_NAME_SN_NUM > 0
static uint8_t BleDevNameStr[30];	// �洢�����Ĺ㲥��
#endif

#if SEC_PARAM_BOND || SEC_PARAM_MITM
static ble_gap_sec_params_t m_sec_param;
static ble_gap_sec_keyset_t m_sec_keyset;
#endif

#if SEC_PARAM_BOND
static ble_gap_enc_key_t sOwnEncKey;
//static ble_gap_enc_key_t sPeerEncKey;
//static ble_gap_id_key_t  sOwnIdKey;
//static ble_gap_id_key_t  sPeerIdKey;
#endif


static tBleRxBlk BleRxBlk;
static tBleTxBlk BleTxBlk;
/** Private Function ******************************************************************************/
/*
 * Action:    ��ȡ�㲥�豸��
 * Input:     no
 * Output:    no
 * Return:    no
 */
#if BLE_ADV_NAME_SN_NUM > 0
static uint8_t* ble_adv_name_str_get(void)
{
	tProductInfo* pInfo;
	uint8_t* p = &BleDevNameStr[1];

	// ��ȡ�㲥��ͷ
	BleDevNameStr[0] = strlen(DEVICE_NAME);
	my_memcpy(p, DEVICE_NAME, BleDevNameStr[0]);
	p += BleDevNameStr[0];

	// ��Ӽ���
	*p++ = '_';
	BleDevNameStr[0] += 1;

	// ��ȡ�㲥��SN��δBLE_ADV_NAME_SN_NUMλ
	pInfo = PRIV_ProductInfoGet();
	if(pInfo->t.device_id[0] == DEVICE_SN_LEN)
	{
		my_memcpy(p, &(pInfo->t.device_id[1 + DEVICE_SN_LEN - BLE_ADV_NAME_SN_NUM]), BLE_ADV_NAME_SN_NUM);
	}
	else
	{
		my_memset(p, '0', BLE_ADV_NAME_SN_NUM);
	}
	BleDevNameStr[0] += BLE_ADV_NAME_SN_NUM;

	return BleDevNameStr;
}
#endif
/*
 * Action:    ʵ�ʷ��͵ĺ���
 * Input:     no
 * Output:    no
 * Return:    no
 */
static uint32_t ble_send_data(void)
{
	uint32_t err_code = NRF_SUCCESS;
    uint16_t remain;

	if(m_conn_handle == BLE_CONN_HANDLE_INVALID) return NRF_ERROR_SVC_HANDLER_MISSING;

	//ѭ�����ͣ�ֻҪ����ֵ��ȷ�ͷ������÷��ͺ���
    do{
		remain = BleTxBlk.tx_len - BleTxBlk.tx_buf_ptr;
		if(remain > BSP_BLE_SINGLE_MAX_LEN) { remain = BSP_BLE_SINGLE_MAX_LEN; }

		//err_code = ble_nus_string_send(&m_nus, BleTxBlk.buf + BleTxBlk.tx_buf_ptr, (uint8_t)remain);
		err_code = ble_nus_data_send(&m_nus, BleTxBlk.buf + BleTxBlk.tx_buf_ptr, &remain, m_conn_handle);
		if(NRF_SUCCESS == err_code)
		{
        	NRF_LOG_HEXDUMP_DEBUG(BleTxBlk.buf + BleTxBlk.tx_buf_ptr, remain);

			//ֻ�з���ֵ��ȷ�Ÿ���ƫ�ƣ�
			//����Ҫ������BUSY������NO BUFF����
		    BleTxBlk.tx_buf_ptr += remain;
		}
    //���ú����ɹ����һ��������Ǿͼ�������
    }while((NRF_SUCCESS == err_code) && (BleTxBlk.tx_buf_ptr < BleTxBlk.tx_len));

	if((BleTxBlk.tx_buf_ptr >= BleTxBlk.tx_len)
	|| (NRF_ERROR_INVALID_STATE == err_code))
	{
		BleTxBlk.flag.txing = FALSE; // �������������
	}

    return err_code;
}

/*
 * Action:    ���ͺ���ʣ���ֽ�
 * Input:     no
 * Output:    no
 * Return:    no
 */
static uint32_t ble_send_more_data(void)
{
    uint32_t remain;

    remain = BleTxBlk.tx_len - BleTxBlk.tx_buf_ptr;

    if(0 == remain || NULL == BleTxBlk.buf)
	{
        return NRF_SUCCESS;    //��������ȫ��������ֱ�ӷ���
    }

    return ble_send_data();
}

/**@brief Function for handling an event from the Connection Parameters Module.
 *
 * @details This function will be called for all events in the Connection Parameters Module
 *          which are passed to the application.
 *
 * @note All this function does is to disconnect. This could have been done by simply setting
 *       the disconnect_on_fail config parameter, but instead we use the event handler
 *       mechanism to demonstrate its use.
 *
 * @param[in] p_evt  Event received from the Connection Parameters Module.
 */
static void on_conn_params_evt(ble_conn_params_evt_t * p_evt)
{
    uint32_t err_code;

    if (p_evt->evt_type == BLE_CONN_PARAMS_EVT_FAILED)
    {
        err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_CONN_INTERVAL_UNACCEPTABLE);
        APP_ERROR_CHECK(err_code);
    }
}

/**@brief Function for handling Queued Write Module errors.
 *
 * @details A pointer to this function will be passed to each service which may need to inform the
 *          application about an error.
 *
 * @param[in]   nrf_error   Error code containing information about what went wrong.
 */
static void nrf_qwr_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 Function for handling Service errors.
 *
 * @details A pointer to this function will be passed to each service which may need to inform the
 *          application about an error.
 *
 * @param[in]   nrf_error   Error code containing information about what went wrong.
 */
#if 0
static void service_error_handler(uint32_t nrf_error)
{
    APP_ERROR_HANDLER(nrf_error);
}
#endif

/**@brief Function for handling advertising events.
 *
 * @details This function will be called for advertising events which are passed to the application.
 *
 * @param[in] ble_adv_evt  Advertising event.
 */
static void on_adv_evt(ble_adv_evt_t ble_adv_evt)
{
    //uint32_t err_code;

    switch (ble_adv_evt)
    {
        case BLE_ADV_EVT_FAST:
			NRF_LOG_INFO("BLE_ADV_EVT_FAST");
			/*****��������2��,���Ӵ�ӡ*************************/
            //err_code = bsp_indication_set(BSP_INDICATE_ADVERTISING);
            //APP_ERROR_CHECK(err_code);
            break;
        case BLE_ADV_EVT_IDLE:
			NRF_LOG_INFO("BLE_ADV_EVT_IDLE");
		    /*****��������1��,���Ӵ�ӡ*************************/
            //sleep_mode_enter();
            break;
        default:
            break;
    }
}

/**@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)
{
    uint32_t err_code;

    switch (p_ble_evt->header.evt_id)
    {
        case BLE_GAP_EVT_CONNECTED:
        {
            NRF_LOG_INFO("Connected");

            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);

			#if SEC_PARAM_MITM
			err_code =  sd_ble_gap_authenticate(m_conn_handle, &m_sec_param);  //������֮����ʾ����������
            APP_ERROR_CHECK(err_code);
			#endif

			//IND_LedCtrl(IND_LED_B_BLUE, LED_BL_S, 3);
        }break;

        case BLE_GAP_EVT_DISCONNECTED:
        {
            NRF_LOG_INFO("Disconnected");

			ble_gap_evt_disconnected_t disc;



            m_conn_handle = BLE_CONN_HANDLE_INVALID;
        }break;

		#if BSP_BLE_DLE_ON
		case BLE_GAP_EVT_DATA_LENGTH_UPDATE_REQUEST:
        {
            NRF_LOG_DEBUG("DLE update request.");
            ble_gap_data_length_params_t dle_param;
			my_memset(&dle_param, 0, sizeof(ble_gap_data_length_params_t));   //0 means auto select DLE
            err_code = sd_ble_gap_data_length_update(p_ble_evt->evt.gap_evt.conn_handle, &dle_param, NULL);
            APP_ERROR_CHECK(err_code);
        } break;
		#endif

        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:
        {
            NRF_LOG_DEBUG("BLE_GAP_EVT_SEC_PARAMS_REQUEST");

			#if (SEC_PARAM_BOND && SEC_PARAM_MITM) //�յ�����������󣬰��Լ�����԰�ȫ������Ӧ������
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_SUCCESS, &m_sec_param, &m_sec_keyset);
			NRF_LOG_INFO("sd_ble_gap_sec_params_reply - err_code: %d", err_code);
			#else // Pairing not supported
            err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, NULL, NULL);
            #endif

			APP_ERROR_CHECK(err_code);
		}break;

		case BLE_GAP_EVT_SEC_INFO_REQUEST:
		{
			NRF_LOG_DEBUG("BLE_GAP_EVT_SEC_INFO_REQUEST");

			err_code = sd_ble_gap_sec_info_reply(m_conn_handle,  &(sOwnEncKey.enc_info), NULL, NULL);
			NRF_LOG_INFO("sd_ble_gap_sec_info_reply - err_code: %d", err_code);
			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.
            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;

		#if (SEC_PARAM_BOND || SEC_PARAM_MITM)
		case BLE_GAP_EVT_AUTH_STATUS:
		{
             NRF_LOG_INFO("BLE_GAP_EVT_AUTH_STATUS: status=0x%x bond=0x%x lv4: %d kdist_own:0x%x kdist_peer:0x%x",
                          p_ble_evt->evt.gap_evt.params.auth_status.auth_status,
                          p_ble_evt->evt.gap_evt.params.auth_status.bonded,
                          p_ble_evt->evt.gap_evt.params.auth_status.sm1_levels.lv4,
                          *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_own),
                          *((uint8_t *)&p_ble_evt->evt.gap_evt.params.auth_status.kdist_peer));
			//�����Բ��ɹ����������ֱ�ӶϿ�����
			if(p_ble_evt->evt.gap_evt.params.auth_status.auth_status != BLE_GAP_SEC_STATUS_SUCCESS)
			{
				sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
			}
			else
			{
				NRF_LOG_INFO("BLE Pair success!");
			}
        }break;
		#endif

        default:
            // No implementation needed.
            //NRF_LOG_INFO("----<ble_evt_handler> Other Evt: 0x%02X", p_ble_evt->header.evt_id);
            break;
    }
}

/**@brief Function for handling events from the GATT library. */
void gatt_evt_handler(nrf_ble_gatt_t * p_gatt, nrf_ble_gatt_evt_t const * p_evt)
{
    if ((m_conn_handle == p_evt->conn_handle) && (p_evt->evt_id == NRF_BLE_GATT_EVT_ATT_MTU_UPDATED))
    {
        m_ble_nus_max_data_len = p_evt->params.att_mtu_effective - OPCODE_LENGTH - HANDLE_LENGTH;
        NRF_LOG_INFO("Data len is set to 0x%X(%d)", m_ble_nus_max_data_len, m_ble_nus_max_data_len);
    }
    NRF_LOG_DEBUG("ATT MTU exchange completed. central 0x%x peripheral 0x%x",
                  p_gatt->att_mtu_desired_central,
                  p_gatt->att_mtu_desired_periph);
}

/**@brief Function for handling the data from the Nordic UART Service.
 *
 * @details This function will process the data received from the Nordic UART BLE Service and send
 *          it to the UART module.
 *
 * @param[in] p_evt       Nordic UART Service event.
 */
/**@snippet [Handling the data received over BLE] */
static void nus_data_handler(ble_nus_evt_t * p_evt)
{

    if(p_evt->type == BLE_NUS_EVT_RX_DATA)
    {
        //uint32_t err_code;

        NRF_LOG_DEBUG("C->S:");
        NRF_LOG_HEXDUMP_DEBUG(p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);

		my_memcpy(BleRxBlk.buf, p_evt->params.rx_data.p_data, p_evt->params.rx_data.length);
		BleRxBlk.buf_ptr = p_evt->params.rx_data.length;
		BleRxBlk.flag.rx_done = TRUE;

		#if 0 // Uart ��������ģ��
        for (uint32_t i = 0; i < p_evt->params.rx_data.length; i++)
        {
            do
            {
                err_code = app_uart_put(p_evt->params.rx_data.p_data[i]);
                if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_BUSY))
                {
                    NRF_LOG_ERROR("Failed receiving NUS message. Error 0x%x. ", err_code);
                    APP_ERROR_CHECK(err_code);
                }
            } while (err_code == NRF_ERROR_BUSY);
        }
        if (p_evt->params.rx_data.p_data[p_evt->params.rx_data.length - 1] == '\r')
        {
            while (app_uart_put('\n') == NRF_ERROR_BUSY);
        }
		#endif
    }
	else if(p_evt->type == BLE_NUS_EVT_RX_DATA)
	{
		ble_send_more_data();
	}
	else if(p_evt->type == BLE_NUS_EVT_COMM_STARTED)
    {
		NRF_LOG_INFO("BLE_NUS_EVT_COMM_STARTED");
    }
	else if(p_evt->type == BLE_NUS_EVT_COMM_STOPPED)
    {
		NRF_LOG_INFO("BLE_NUS_EVT_COMM_STOPPED");
    }
}
/**@snippet [Handling the data received over BLE] */

/**@brief Handler for shutdown preparation.
 *
 * @details During shutdown procedures, this function will be called at a 1 second interval
 *          untill the function returns true. When the function returns true, it means that the
 *          app is ready to reset to DFU mode.
 *
 * @param[in]   event   Power manager event.
 *
 * @retval  True if shutdown is allowed by this power manager handler, otherwise false.
 */
static bool app_shutdown_handler(nrf_pwr_mgmt_evt_t event)
{
    switch (event)
    {
        case NRF_PWR_MGMT_EVT_PREPARE_DFU:
            NRF_LOG_INFO("Power management wants to reset to DFU mode.");
            // YOUR_JOB: Get ready to reset into DFU mode
            //
            // If you aren't finished with any ongoing tasks, return "false" to
            // signal to the system that reset is impossible at this stage.
            //
            // Here is an example using a variable to delay resetting the device.
            //
            // if (!m_ready_for_reset)
            // {
            //      return false;
            // }
            // else
            //{
            //
            //    // Device ready to enter
            //    uint32_t err_code;
            //    err_code = sd_softdevice_disable();
            //    APP_ERROR_CHECK(err_code);
            //    err_code = app_timer_stop_all();
            //    APP_ERROR_CHECK(err_code);
            //}
            break;

        default:
            // YOUR_JOB: Implement any of the other events available from the power management module:
            //      -NRF_PWR_MGMT_EVT_PREPARE_SYSOFF
            //      -NRF_PWR_MGMT_EVT_PREPARE_WAKEUP
            //      -NRF_PWR_MGMT_EVT_PREPARE_RESET
            return true;
    }

    NRF_LOG_INFO("Power management allowed to reset to DFU mode.");
    return true;
}

//lint -esym(528, m_app_shutdown_handler)
/**@brief Register application shutdown handler with priority 0.
 */
NRF_PWR_MGMT_HANDLER_REGISTER(app_shutdown_handler, 0);


static void buttonless_dfu_sdh_state_observer(nrf_sdh_state_evt_t state, void * p_context)
{
    if (state == NRF_SDH_EVT_STATE_DISABLED)
    {
        // Softdevice was disabled before going into reset. Inform bootloader to skip CRC on next boot.
        nrf_power_gpregret2_set(BOOTLOADER_DFU_SKIP_CRC);

        //Go to system off.
        nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_SYSOFF);
    }
}

/* nrf_sdh state observer. */
NRF_SDH_STATE_OBSERVER(m_buttonless_dfu_state_obs, 0) =
{
    .handler = buttonless_dfu_sdh_state_observer,
};

static void advertising_config_get(ble_adv_modes_config_t * p_config)
{
    memset(p_config, 0, sizeof(ble_adv_modes_config_t));

    p_config->ble_adv_fast_enabled  = true;
    p_config->ble_adv_fast_interval = APP_ADV_INTERVAL;
    p_config->ble_adv_fast_timeout  = APP_ADV_DURATION;
}

static void disconnect(uint16_t conn_handle, void * p_context)
{
    UNUSED_PARAMETER(p_context);

    ret_code_t err_code = sd_ble_gap_disconnect(conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
    if (err_code != NRF_SUCCESS)
    {
        NRF_LOG_WARNING("Failed to disconnect connection. Connection handle: %d Error: %d", conn_handle, err_code);
    }
    else
    {
        NRF_LOG_DEBUG("Disconnected connection handle %d", conn_handle);
    }
}


// YOUR_JOB: Update this code if you want to do anything given a DFU event (optional).
/**@brief Function for handling dfu events from the Buttonless Secure DFU service
 *
 * @param[in]   event   Event from the Buttonless Secure DFU service.
 */
void ble_dfu_evt_handler(ble_dfu_buttonless_evt_type_t event)
{
    switch (event)
    {
        case BLE_DFU_EVT_BOOTLOADER_ENTER_PREPARE:
        {
            NRF_LOG_INFO("Device is preparing to enter bootloader mode.");

            // Prevent device from advertising on disconnect.
            ble_adv_modes_config_t config;
            advertising_config_get(&config);
            config.ble_adv_on_disconnect_disabled = true;
            ble_advertising_modes_config_set(&m_advertising, &config);

            // Disconnect all other bonded devices that currently are connected.
            // This is required to receive a service changed indication
            // on bootup after a successful (or aborted) Device Firmware Update.
            uint32_t conn_count = ble_conn_state_for_each_connected(disconnect, NULL);
            NRF_LOG_INFO("Disconnected %d links.", conn_count);
            break;
        }

        case BLE_DFU_EVT_BOOTLOADER_ENTER:
            // YOUR_JOB: Write app-specific unwritten data to FLASH, control finalization of this
            //           by delaying reset by reporting false in app_shutdown_handler
            NRF_LOG_INFO("Device will enter bootloader mode.");
            break;

        case BLE_DFU_EVT_BOOTLOADER_ENTER_FAILED:
            NRF_LOG_ERROR("Request to enter bootloader mode failed asynchroneously.");
            // YOUR_JOB: Take corrective measures to resolve the issue
            //           like calling APP_ERROR_CHECK to reset the device.
            break;

        case BLE_DFU_EVT_RESPONSE_SEND_ERROR:
            NRF_LOG_ERROR("Request to send a response to client failed.");
            // YOUR_JOB: Take corrective measures to resolve the issue
            //           like calling APP_ERROR_CHECK to reset the device.
            APP_ERROR_CHECK(false);
            break;

        default:
            NRF_LOG_ERROR("Unknown event from ble_dfu_buttonless.");
            break;
    }
}

/**@brief Function for the SoftDevice initialization.
 *
 * @details This function initializes the SoftDevice and the BLE event interrupt.
 */
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 the GAP initialization.
 *
 * @details This function will set up all the necessary GAP (Generic Access Profile) parameters of
 *          the device. It also sets the permissions and appearance.
 */
static void gap_params_init(void)
{
    uint32_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);

	#if BLE_ADV_NAME_SN_NUM == 0
    err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          (const uint8_t *) DEVICE_NAME,
                                          strlen(DEVICE_NAME));
	#else
	const uint8_t * adv_name_str = ble_adv_name_str_get();
	err_code = sd_ble_gap_device_name_set(&sec_mode,
                                          &adv_name_str[1],
                                          adv_name_str[0]);
	#endif
    APP_ERROR_CHECK(err_code);

    memset(&gap_conn_params, 0, sizeof(gap_conn_params));

    gap_conn_params.min_conn_interval = MIN_CONN_INTERVAL;
    gap_conn_params.max_conn_interval = MAX_CONN_INTERVAL;
    gap_conn_params.slave_latency     = SLAVE_LATENCY;
    gap_conn_params.conn_sup_timeout  = CONN_SUP_TIMEOUT;

    err_code = sd_ble_gap_ppcp_set(&gap_conn_params);
    APP_ERROR_CHECK(err_code);


	// Set TX Power
	#if 0
	err_code = sd_ble_gap_tx_power_set(TX_POWER_LEVEL);
	APP_ERROR_CHECK(err_code);
	#endif

	/* Satic password set */
	#if BLE_STATIC_PASSKEY_EN

	static ble_opt_t sStaticKeyOption;
	uint8_t passkey[] = BLE_PAIRING_PASSKEY;

	sStaticKeyOption.gap_opt.passkey.p_passkey = (uint8_t const*)passkey;
	err_code = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &sStaticKeyOption);
	APP_ERROR_CHECK(err_code);

	NRF_LOG_INFO("err_code: %d; Device Password: %s.", err_code
													 , sStaticKeyOption.gap_opt.passkey.p_passkey);
	#endif
}

/**@brief Function for initializing the GATT library. */
void gatt_init(void)
{
    ret_code_t err_code;

    err_code = nrf_ble_gatt_init(&m_gatt, gatt_evt_handler);
    APP_ERROR_CHECK(err_code);

	// ����MTU����󳤶�
	#if 0 // nrf_ble_gatt_init()�������Ѿ�������
    err_code = nrf_ble_gatt_att_mtu_periph_set(&m_gatt, NRF_SDH_BLE_GATT_MAX_MTU_SIZE);
    APP_ERROR_CHECK(err_code);
	#endif
}

/**@brief Function for initializing services that will be used by the application.
 */
static void services_init(void)
{
    uint32_t           err_code;
    ble_nus_init_t     nus_init;
	//ble_dis_init_t     dis_init;
    nrf_ble_qwr_init_t qwr_init = {0};
	ble_dfu_buttonless_init_t dfus_init = {0};

    // Initialize Queued Write Module.
	memset(&qwr_init, 0, sizeof(qwr_init));
    qwr_init.error_handler = nrf_qwr_error_handler;

    err_code = nrf_ble_qwr_init(&m_qwr, &qwr_init);
    APP_ERROR_CHECK(err_code);

    // Initialize NUS.
    memset(&nus_init, 0, sizeof(nus_init));
    nus_init.data_handler = nus_data_handler;

    err_code = ble_nus_init(&m_nus, &nus_init);
    APP_ERROR_CHECK(err_code);

	// Initialize the async SVCI interface to bootloader.
	err_code = ble_dfu_buttonless_async_svci_init();
	APP_ERROR_CHECK(err_code);

    dfus_init.evt_handler = ble_dfu_evt_handler;

    err_code = ble_dfu_buttonless_init(&dfus_init);
    APP_ERROR_CHECK(err_code);

	// Initialize Device Information Service.
	#if 0
    memset(&dis_init, 0, sizeof(dis_init));

    ble_srv_ascii_to_utf8(&dis_init.manufact_name_str, MANUFACTURER_NAME);
    ble_srv_ascii_to_utf8(&dis_init.model_num_str, MODEL_NUM);

    sys_id.manufacturer_id            = MANUFACTURER_ID;
    sys_id.organizationally_unique_id = ORG_UNIQUE_ID;
    dis_init.p_sys_id                 = &sys_id;

    dis_init.dis_char_rd_sec = SEC_OPEN;

    err_code = ble_dis_init(&dis_init);
    APP_ERROR_CHECK(err_code);
	#endif
}

/**@brief Function for initializing the Advertising functionality.
 */
static void advertising_init(void)
{
    uint32_t               err_code;
    ble_advertising_init_t init;
	//int8_t bt_tx_power_level = 8;

    memset(&init, 0, sizeof(init));

    init.advdata.name_type               = BLE_ADVDATA_FULL_NAME;
    init.advdata.include_appearance      = false;
    init.advdata.flags                   = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;// BLE_GAP_ADV_FLAGS_LE_ONLY_LIMITED_DISC_MODE;
	init.advdata.uuids_complete.uuid_cnt = sizeof(m_adv_uuids) / sizeof(m_adv_uuids[0]);
    init.advdata.uuids_complete.p_uuids  = m_adv_uuids;
	//init.advdata.p_tx_power_level        = &bt_tx_power_level;

    advertising_config_get(&init.config);

    init.evt_handler = on_adv_evt;

    err_code = ble_advertising_init(&m_advertising, &init);
    APP_ERROR_CHECK(err_code);

    ble_advertising_conn_cfg_tag_set(&m_advertising, APP_BLE_CONN_CFG_TAG);
}

/**@brief Function for initializing the Connection Parameters module.
 */
static void conn_params_init(void)
{
    uint32_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_GATT_HANDLE_INVALID;
    cp_init.disconnect_on_fail             = false;
    cp_init.evt_handler                    = on_conn_params_evt;
    cp_init.error_handler                  = conn_params_error_handler;

    err_code = ble_conn_params_init(&cp_init);
    APP_ERROR_CHECK(err_code);
}

/**@brief Function for the Peer Manager initialization.
 */
#if (SEC_PARAM_BOND || SEC_PARAM_MITM)
static void dev_sec_param_init(void)
{
	/* ���Ӳ������� */
    memset(&m_sec_param, 0, sizeof(ble_gap_sec_params_t));

    // Security parameters to be used for all security procedures.
    m_sec_param.bond           = SEC_PARAM_BOND;
    m_sec_param.mitm           = SEC_PARAM_MITM;
    m_sec_param.lesc           = SEC_PARAM_LESC;
    m_sec_param.keypress       = SEC_PARAM_KEYPRESS;
    m_sec_param.io_caps        = SEC_PARAM_IO_CAPABILITIES;
    m_sec_param.oob            = SEC_PARAM_OOB;
    m_sec_param.min_key_size   = SEC_PARAM_MIN_KEY_SIZE;
    m_sec_param.max_key_size   = SEC_PARAM_MAX_KEY_SIZE;
	#if SEC_PARAM_BOND
    m_sec_param.kdist_own.enc  = 1;
    m_sec_param.kdist_own.id   = 0;
    m_sec_param.kdist_peer.enc = 0;
    m_sec_param.kdist_peer.id  = 0;
	#endif

	/* ��Կ�������� */
	#if SEC_PARAM_BOND
	memset(&m_sec_keyset, 0, sizeof(ble_gap_sec_keys_t));
	m_sec_keyset.keys_own.p_enc_key  = &sOwnEncKey;
	//m_sec_keyset.keys_own.p_id_key   = &sOwnIdKey;
	//m_sec_keyset.keys_peer.p_enc_key = &sPeerEncKey;
	//m_sec_keyset.keys_peer.p_id_key  = &sPeerIdKey;
	#endif
}
#endif


#if BLE_OPT_PARAM_ENABLE
static void opt_params_init(void)
{
    uint32_t err_code;
	ble_opt_t  opt;

    my_memset(&opt, 0x00, sizeof(opt));

    opt.common_opt.conn_evt_ext.enable = true;

    err_code = sd_ble_opt_set(BLE_COMMON_OPT_CONN_EVT_EXT, &opt);

    APP_ERROR_CHECK(err_code);
}
#endif
/** Function **************************************************************************************/
/*
 * Action:    ��ʼ��
 * Input:     no
 * Output:    no
 * Return:    no
 */
void bspBle_Init(void)
{
	ble_stack_init();
	gap_params_init();
	gatt_init();
    services_init();
    advertising_init();
    conn_params_init();
	#if (SEC_PARAM_BOND || SEC_PARAM_MITM)
	dev_sec_param_init();
	#endif

	#if BLE_OPT_PARAM_ENABLE
	opt_params_init();
	#endif
}

/*
 * Action:    ��ʼ�㲥
 * Input:     no
 * Output:    no
 * Return:    no
 */
void bspBle_AdvStart(void)
{
    uint32_t err_code = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
    APP_ERROR_CHECK(err_code);
}


/*
 * Action:    �򿪽��տ�
 * Input:     no
 * Output:    no
 * Return:    no
 */
bool bspBle_Open(uint8_t* rx_buf, uint16_t size)
{
	if(rx_buf != NULL && size != 0)
	{
		BleRxBlk.buf = rx_buf;
		BleRxBlk.buf_size = size;

		return TRUE;
	}

	return FALSE;
}

/*
 * Action:    ��ȡ���յ��ֽڸ���
 * Input:     no
 * Output:    no
 * Return:    no
 */
uint16_t bspBle_Recv(void)
{
	uint16_t size = 0;

	if(BleRxBlk.flag.rx_done)
	{
		BleRxBlk.flag.rx_done = FALSE;

		size = BleRxBlk.buf_ptr;

		BleRxBlk.buf_ptr = 0;

        return size;
	}

	return 0;
}

/*
 * Action:    ����
 * Input:     no
 * Output:    no
 * Return:    ����ֵӦ�������洦�������ֵ�����NRF_SUCCESS��
 			  ����NRF_ERROR_BUSY����BLE_ERROR_NO_TX_BUFFERS��Ӧ����Ϊ��ȷ
 			  ��Ϊ�����ִ�����Ȼ�����ˣ��������Dz�û��ȥ����tx_buf_ptrƫ�ƣ������Ժ�
 			  �ķ��ͻ��ǻ���ȷ���С�
 			  ��������ϲ�Ӧ�ø����������
 */
uint32_t bspBle_Send(const void* pbuf, uint16_t len)
{
	uint32_t error;
	if(NULL == pbuf || len <= 0)  return FALSE;
	if(BleTxBlk.flag.txing) return FALSE;

	BleTxBlk.flag.txing = TRUE; // ���ڷ��ͱ��
    BleTxBlk.buf        = (uint8_t*)pbuf;
    BleTxBlk.tx_len     = len;
	BleTxBlk.tx_buf_ptr = 0;

	NRF_LOG_DEBUG("C<-S:");

	error = ble_send_data();
	if(error == NRF_SUCCESS
	|| error == NRF_ERROR_BUSY
	|| error == NRF_ERROR_RESOURCES)
	{
		return TRUE;
	}

	return FALSE;
}

/** - End - YWKang Tech. Co., Ltd. 2018 *********************************************************/

Parents
  • Here are some suggestions:

    • Could you try to adjust the minimum and maximum connection intervals, as described here
    • Set the LF accuracy to 1 and lower ..LF_RC_TEMP_CTIV, as described here
    • A reason for the disconnect could also be that some error occurred on your nRF52840, could you try to debug your chip and see where it happens

    Best regards,

    Simon

  • Hi Simon,

         I had closed my question, because my parameters is incorrect. But now I get another question as below.

    I see the example from nordic SDK bag, I fond that these examples of project almost use the peer_manager_init(), but my project don't use this function. So I want to know what advantage does use the peer_manager_init() than not? In other word, what is the core function about the "peer manager" module?

    Best regards,

    Terry Tan

  • The Peer Manager handles everything related to bonding and pairing, and also simplifies the process of storing keys and bonding information to flash. You could achieve this yourself by using the SVCalls and the lower level drivers directly, but that would require much work, and you have to know what you're doing.

    This is very well documented in the infocenter, take a look yourself. If anything is unclear or you want me to elaborate on something particular, please tell me.

    Best regards,

    Simon

Reply
  • The Peer Manager handles everything related to bonding and pairing, and also simplifies the process of storing keys and bonding information to flash. You could achieve this yourself by using the SVCalls and the lower level drivers directly, but that would require much work, and you have to know what you're doing.

    This is very well documented in the infocenter, take a look yourself. If anything is unclear or you want me to elaborate on something particular, please tell me.

    Best regards,

    Simon

Children
No Data
Related