Switch RF OOK and BLE scan causes BLE_ERROR_NOT_ENABLED.

Hi Friend,

We have a project using SDK16 and softdevice S140. We want to generate a looping output of 60ms 2.4GHz OOK and 500ms BLE scan. Ported 2.4GHz OOK from radio_test project.
Now I get an error message BLE_ERROR_NOT_ENABLED. Is it because BLE is not properly enabled? But I have called ble_stack_init in the resume_ble function, I don't know why the enable is not successful? I trace program ble_stack_init and found the program execute to nrf_sdh_enable_request to softdevices_evt_irq_enable(); program will execute nrf_sdh_ble_evts_poll() and cause ret_code == BLE_ERROR_NOT_ENABLED and crash.
1: Is this the remaining MESSAGE of RF switching BLE STACK and OOK? (Because it alternates between enabling and disabling.) so after softdevices_evt_irq_enable, execute nrf_sdh_ble_evts_poll. Is there a function to clear the remaining MESSAGE before ble_stack_init?
2: Or other reasons?

How to solve it? Can anyone help me? Thank you in advance.

Best wishes

Ted Wu

main.c
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);
}

void ble_app_stop(void)
{
    uint32_t err_code;

    // Stop any impending connection parameters update.
    err_code = ble_conn_params_stop();
    APP_ERROR_CHECK(err_code);
}

void ble_stack_stop(void)
{
    uint32_t err_code;

    err_code = nrf_sdh_disable_request();
    APP_ERROR_CHECK(err_code);

    ASSERT(!nrf_sdh_is_enabled());
}

void ble_app_start(void)
{
    ble_stack_init();
    scan_init();
    db_discovery_init();
    gap_params_init();
    gatt_init();
    nus_c_init();
    buffer_init();
    conn_params_init();
    peer_manager_init();
    services_init();
    advertising_init();
}

void resume_ble(void)
{
    if(ble_enable_flag == false)
    {
        ble_enable_flag = true;
        ble_app_start();
        APP_ERROR_CHECK(nrf_ble_scan_start(&m_scan));
    }
}

void ook_start(void)
{
    if(ble_enable_flag == true)
    {
        ble_enable_flag = false;
        // Stop scanning.
        nrf_ble_scan_stop();
        ble_app_stop();
        ble_stack_stop();
        // Use 32MHz from external crystal
        // This could be customized for RC/Xtal, or even to use a 32 kHz crystal
        NRF_CLOCK->EVENTS_HFCLKSTARTED = 0;
        NRF_CLOCK->TASKS_HFCLKSTART    = 1;
        while (NRF_CLOCK->EVENTS_HFCLKSTARTED == 0)
        {
            // Do nothing while waiting for the clock to start
        }
    }
    manchester_data_frame(&RfTriggerCmdBuf[1], RfTriggerCmdBuf[0]);
}

nrf_sdh.c
ret_code_t nrf_sdh_enable_request(void)
{
    ret_code_t ret_code;

    if (m_nrf_sdh_enabled)
    {
        return NRF_ERROR_INVALID_STATE;
    }

    m_nrf_sdh_continue = true;

    // Notify observers about SoftDevice enable request.
    if (sdh_request_observer_notify(NRF_SDH_EVT_ENABLE_REQUEST) == NRF_ERROR_BUSY)
    {
        // Enable process was stopped.
        return NRF_SUCCESS;
    }

    // Notify observers about starting SoftDevice enable process.
    sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLE_PREPARE);

    nrf_clock_lf_cfg_t const clock_lf_cfg =
    {
        .source       = NRF_SDH_CLOCK_LF_SRC,
        .rc_ctiv      = NRF_SDH_CLOCK_LF_RC_CTIV,
        .rc_temp_ctiv = NRF_SDH_CLOCK_LF_RC_TEMP_CTIV,
        .accuracy     = NRF_SDH_CLOCK_LF_ACCURACY
    };

    CRITICAL_REGION_ENTER();
#ifdef ANT_LICENSE_KEY
    ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler, ANT_LICENSE_KEY);
#else
    ret_code = sd_softdevice_enable(&clock_lf_cfg, app_error_fault_handler);
#endif
    m_nrf_sdh_enabled = (ret_code == NRF_SUCCESS);
    CRITICAL_REGION_EXIT();

    if (ret_code != NRF_SUCCESS)
    {
        return ret_code;
    }

    m_nrf_sdh_continue  = false;
    m_nrf_sdh_suspended = false;

    // Enable event interrupt.
    // Interrupt priority has already been set by the stack.
    softdevices_evt_irq_enable();

    // Notify observers about a finished SoftDevice enable process.
    sdh_state_observer_notify(NRF_SDH_EVT_STATE_ENABLED);

    return NRF_SUCCESS;
}

nrf_sdh_ble.c
static void nrf_sdh_ble_evts_poll(void * p_context)
{
    UNUSED_VARIABLE(p_context);

    ret_code_t ret_code;

    if (!m_stack_is_enabled)
    {
        return;
    }

    while (true)
    {
        /*lint -save -e(587) */
        __ALIGN(4) uint8_t evt_buffer[NRF_SDH_BLE_EVT_BUF_SIZE];
        /*lint -restore */

        ble_evt_t * p_ble_evt;
        uint16_t    evt_len = (uint16_t)sizeof(evt_buffer);

        ret_code = sd_ble_evt_get(evt_buffer, &evt_len);
        if (ret_code != NRF_SUCCESS)
        {
            break;
        }

        p_ble_evt = (ble_evt_t *)evt_buffer;

        NRF_LOG_DEBUG("BLE event: 0x%x.", p_ble_evt->header.evt_id);

        // Forward the event to BLE observers.
        nrf_section_iter_t  iter;
        for (nrf_section_iter_init(&iter, &sdh_ble_observers);
             nrf_section_iter_get(&iter) != NULL;
             nrf_section_iter_next(&iter))
        {
            nrf_sdh_ble_evt_observer_t * p_observer;
            nrf_sdh_ble_evt_handler_t    handler;

            p_observer = (nrf_sdh_ble_evt_observer_t *)nrf_section_iter_get(&iter);
            handler    = p_observer->handler;

            handler(p_ble_evt, p_observer->p_context);
        }
    }

    if (ret_code != NRF_ERROR_NOT_FOUND)
    {
        APP_ERROR_HANDLER(ret_code);
    }
}

Parents
  • I think it's a bug with the sdh library. We thought that we fixed the issue since SDK v15 where we introduced the check:

    if (!m_stack_is_enabled)
    {
    return;
    }

    inside nrf_sdh_ble_evts_poll() but it seems that we never turn that flag to false when the softdevice is disabled.

    Workaround?

    You need to add a function inside nrf_sdh_ble.c, for example named nrf_sdh_softdevice_disabled(), inside that you assign m_stack_is_enabled = false.

    In your state observer when you receive NRF_SDH_EVT_STATE_DISABLED, you can just call that function to switch off the m_stack_is_enabled flag. This is very similar to what we do inside nrf_fstorage_sdh_state_handler(). The flag will be turned on again when you call nrf_sdh_ble_enable(). This should solve the BLE_ERROR_NOT_ENABLED issue.

    Best regards,
    Kenneth

Reply
  • I think it's a bug with the sdh library. We thought that we fixed the issue since SDK v15 where we introduced the check:

    if (!m_stack_is_enabled)
    {
    return;
    }

    inside nrf_sdh_ble_evts_poll() but it seems that we never turn that flag to false when the softdevice is disabled.

    Workaround?

    You need to add a function inside nrf_sdh_ble.c, for example named nrf_sdh_softdevice_disabled(), inside that you assign m_stack_is_enabled = false.

    In your state observer when you receive NRF_SDH_EVT_STATE_DISABLED, you can just call that function to switch off the m_stack_is_enabled flag. This is very similar to what we do inside nrf_fstorage_sdh_state_handler(). The flag will be turned on again when you call nrf_sdh_ble_enable(). This should solve the BLE_ERROR_NOT_ENABLED issue.

    Best regards,
    Kenneth

Children
Related