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

Reenable BLE after disabling fails in ble_conn_params_init() on freertos

Hi, 
I'd like to describe an issue i faced during project development. 
My setup is: nRF52840 + s140 + sdk15+FreeRtos

When i disable BLE I call: 

1) sd_ble_gap_disconnect () .  if connected
2) 
ble_conn_params_stop()

3)nrf_sdh_disable_request();

When I reenable BLE I call: 

nrf_sdh_enable_request()

nrf_sdh_ble_enable()

ble_conn_params_init()

....

The problem is that  ble_conn_params_init() returns NRF_ERROR_INTERNAL at if initing this way. It caused by call 

        err_code = app_timer_create(&p_instance->timer_id,
                            APP_TIMER_MODE_SINGLE_SHOT,
                            update_timeout_handler);
        if (err_code != NRF_SUCCESS)
        {
            return NRF_ERROR_INTERNAL;
        }
 

For FREERTOS i use app_timer implementation from app_timer_freertos.c 
inside it the function 

app_timer_create()
has next lines: 

if (pinfo->osHandle == NULL)
    {
        /* New timer is created */
        memset(pinfo, 0, sizeof(app_timer_info_t));

        timer_mode = (mode == APP_TIMER_MODE_SINGLE_SHOT) ? pdFALSE : pdTRUE;
        pinfo->single_shot = (mode == APP_TIMER_MODE_SINGLE_SHOT);
        pinfo->func = timeout_handler;
        pinfo->osHandle = xTimerCreate(" ", 1000, timer_mode, pinfo, app_timer_callback);

        if (pinfo->osHandle == NULL)
            err_code = NRF_ERROR_NULL;
    }
    else
    {
        /* Timer cannot be reinitialized using FreeRTOS API */
        return NRF_ERROR_INVALID_STATE;
    }

and else case is executed. The comment explains why I get an error. 

/* Timer cannot be reinitialized using FreeRTOS API */

For now I added workaround and skipped error at upper layer but it would be better to get this case fixed in next SDK version. 
I suggest  adding app_timer_remove() and updating ble_conn_params_stop() might be a good option. Or just skip call 

app_timer_create in case if it already created. 

Regards,

 

  • Hi,

    Thank you for the feedback. I have created an internal request for this improvement.

  • I am also facing the same error with Nordic NRF5 SDK 15.2.0 and FreeRTOS based timer implementation, while disabling and renabling BLE following the same sequence of steps as mentioned above.

    One of the fix I did was to check if the FreeRTOS timer is not active, then delete and recreate the timer within app_timer_create() function. This will make sure new timer will have a new handler if app_timer_create() is called second time with a new handler.

    Also app_timer_remove() function as suggested above should fix the issue as well.

    Looking forward for a fix in the NRF5 SDK.

  • Hello -

    We too are bumping into this problem with SDK v17.0.0. Skipping the error when re-initializing BLE doesn't seem to work for us. @rsb.29 - would you be able to share the code you used to resolve this issue?

    Regards,

    Brian

  • Hello -

    In case it is helpful for anyone else bumping into this issue, here is what we did to resolve the problem. These changes were applied to SDK v17.0.0.

    In ble_conn_params.c, we modified the code to call a new app_timer_delete() function:

    ret_code_t ble_conn_params_stop(void)
    {
        ret_code_t err_code;
    
        //lint -save -e681 "Loop not entered" when NRF_BLE_CONN_PARAMS_INSTANCE_COUNT is 0
        for (uint32_t i = 0; i < NRF_BLE_CONN_PARAMS_INSTANCE_COUNT; i++)
            {
            err_code = app_timer_stop(m_conn_params_instances[i].timer_id);
    
            switch (err_code)
                {
                case NRF_SUCCESS:
    				app_timer_delete(m_conn_params_instances[i].timer_id);
                    break;
    
                case NRF_ERROR_INVALID_STATE:
                    /* do nothing */
                    break;
    
                case NRF_ERROR_NO_MEM:
                    return NRF_ERROR_BUSY;
    
                case NRF_ERROR_INVALID_PARAM:
                    /* fallthrough */
                default:
                    return NRF_ERROR_INTERNAL;
                }
            }
        //lint -restore
        return NRF_SUCCESS;
    }
    

    Then we added a simple implementation of app_timer_delete() to app_timer_freertos.c:

    uint32_t app_timer_delete(app_timer_id_t timer_id)
    {
        app_timer_info_t * pinfo = (app_timer_info_t*)(timer_id);
        TimerHandle_t hTimer = pinfo->osHandle;
        if (hTimer == NULL)
        {
            return NRF_ERROR_INVALID_STATE;
        }
    
    	if (xTimerDelete(hTimer, APP_TIMER_WAIT_FOR_QUEUE) != pdPASS)
    	{
    		return NRF_ERROR_NO_MEM;
    	}
    	
    	pinfo->osHandle = NULL;
    
        return NRF_SUCCESS;
    }
    

    The app_timer_delete() function sets the pInfo->osHandle to NULL, which allows a new timer to be created after BLE is reenabled.

    Regards,

    Brian

  • Thanks a lot for this patch! This fixed the same issue for me on FreeRTOS with v15.3.0 Smiley

Related