Good morning,
I'm developing an app for NRF52832 SDK 15.3, SD 132 6.1.1 with NUS service. Moreover my app has DFU and Peer Manager with LESC JustWorks security and other FDS records, although now I'm in a more basic branch without these features so that I keep it simple in order to solve this issue. There is more information about my app in this link.
This is the issue:
My app is BLE Peripheral using NUS. It starts advertising and I can put the device to "sleep" (I just disconnect BLE, stop advertising and disable some features) with a long press of my button. This is the relevant code I'm using for disconnection:
#define APP_BLE_CONN_CFG_TAG 1 /**< A tag identifying the SoftDevice BLE configuration. */
#define DEVICE_NAME "XXX_Device v0.3" /**< Name of device. Will be included in the advertising data. */
#define NUS_SERVICE_UUID_TYPE BLE_UUID_TYPE_VENDOR_BEGIN /**< UUID type for the Nordic UART Service (vendor specific). */
#define APP_BLE_OBSERVER_PRIO 3 /**< Application's BLE observer priority. You shouldn't need to modify this value. */
#define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms. This value corresponds to 40 ms). */
#define APP_ADV_DURATION 18000 /**< The advertising duration (180 seconds) in units of 10 milliseconds. */
#define MIN_CONN_INTERVAL MSEC_TO_UNITS(20, UNIT_1_25_MS) /**< Minimum acceptable connection interval (20 ms), Connection interval uses 1.25 ms units. */
#define MAX_CONN_INTERVAL MSEC_TO_UNITS(75, 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 DEAD_BEEF 0xDEADBEEF /**< Value used as error code on stack dump, can be used to identify stack location on stack unwind. */
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 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_NUS_SERVICE, NUS_SERVICE_UUID_TYPE}
};
/**@brief Function for stopping advertising.
*/
void ble_app_advertising_stop(void)
{
ret_code_t err_code = NRF_SUCCESS;
if (m_advertising.adv_handle != (uint8_t)BLE_GAP_ADV_SET_HANDLE_NOT_SET)
{
err_code = sd_ble_gap_adv_stop(m_advertising.adv_handle);
if (err_code == NRF_SUCCESS){
NRF_LOG_INFO("BLE advertising stopped");
} else if (err_code != NRF_ERROR_INVALID_STATE){
NRF_LOG_INFO("BLE not previously advertising");
APP_ERROR_CHECK(err_code);
}
m_advertising.adv_handle = (uint8_t)BLE_GAP_ADV_SET_HANDLE_NOT_SET;
}
}
/**@brief Function for to disconnect from central.
*/
void ble_app_disconnect(void){
ret_code_t err_code;
if (m_conn_handle != BLE_CONN_HANDLE_INVALID)
{
err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION);
if (err_code == NRF_SUCCESS){
NRF_LOG_INFO("BLE Disconnected");
} else if (err_code != NRF_ERROR_INVALID_STATE){
APP_ERROR_CHECK(err_code);
NRF_LOG_INFO("BLE Not previously connected");
}
}
ble_app_advertising_stop();
}
void button_off(){
NRF_LOG_INFO("Device to Sleep");
ble_app_disconnect();
led_red_off();
led_blue_off();
}
This part is working. The device disconnects and advertismen stops.
The next part is to start advertising again (or reconnect to device if possible) after another long press of the button. This is the code:
void ble_app_advertising_restart(void){
ret_code_t ret;
ret = ble_advertising_start(&m_advertising, BLE_ADV_MODE_FAST);
if(ret != NRF_SUCCESS))
{
APP_ERROR_CHECK(err_code);
}
}
void button_press_reconnect(){
ble_app_advertising_restart();
}
This code doesn't work and I've tracked the error to following lines of ble_advertising.c:
uint32_t ble_advertising_start(ble_advertising_t * const p_advertising,
ble_adv_mode_t advertising_mode)
{
uint32_t ret;
//{...}
if (p_advertising->adv_mode_current != BLE_ADV_MODE_IDLE)
{
ret = sd_ble_gap_adv_set_configure(&p_advertising->adv_handle, p_advertising->p_adv_data, &p_advertising->adv_params);
if (ret != NRF_SUCCESS)
{
return ret;
}
ret = sd_ble_gap_adv_start(p_advertising->adv_handle, p_advertising->conn_cfg_tag);
if (ret != NRF_SUCCESS)
{
return ret;
}
}
if (p_advertising->evt_handler != NULL)
{
p_advertising->evt_handler(p_advertising->adv_evt);
}
return NRF_SUCCESS;
}
Function sd_ble_gap_adv_set_configure in line 7 returns error 0x04, what I think is NRF_ERROR_NO_MEM. I've search all around the forum but I've found no related solution, only some about two advertisement sets. Documentation says: Not enough memory to configure a new advertising handle. Update an existing advertising handle instead.
What is weird is that, when it's connected to a central device (e.g. nRF Connect DK) and I disconnect from that central device, the module restarts advertisement by itself through "on_disconnected" function:
static void on_disconnected(ble_advertising_t * const p_advertising, ble_evt_t const * p_ble_evt)
{
uint32_t ret;
p_advertising->whitelist_temporarily_disabled = false;
if (p_ble_evt->evt.gap_evt.conn_handle == p_advertising->current_slave_link_conn_handle &&
p_advertising->adv_modes_config.ble_adv_on_disconnect_disabled == false)
{
ret = ble_advertising_start(p_advertising, BLE_ADV_MODE_DIRECTED_HIGH_DUTY);
if ((ret != NRF_SUCCESS) && (p_advertising->error_handler != NULL))
{
p_advertising->error_handler(ret);
}
}
}
void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt, void * p_context)
{
//{...}
// Upon disconnection, whitelist will be activated and direct advertising is started.
case BLE_GAP_EVT_DISCONNECTED:
on_disconnected(p_advertising, p_ble_evt);
break;
//{...}
}
Since this function works, and it's not about "update an existing advertising handle" as the documentation says. I've tried to modify my ble_app_advertisement_restart with the code from the on_disconnected function but didn't work. So far, my only solution was to reset the module so that I can start advertising again.
What is the problem with the 0x4 error from sd_ble_gap_adv_set_configure? Thanks in advance.