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

Getting err_code = 12289 even though sd_ble_enable was already called before.

Hi. I am working with nrf52832 trying to get Bluetooth and UART and a I2C peripheral working at the same time. I had a working version of the I2C peripheral and UART working together and tried to merge Bluetooth in, referencing the experimental_ble_app_blinky example provided in nRF5_SDK_12.3.0.

Currently when I added ble_stack_init() into my existing program plus all the elements it needs for compiling, I have it in function without breaking any functions I had with UART. However, after I added gap_params_init() after ble_stack_init(), along with everything it needed to compile, of course, my device started to keep rebooting, after the program compiled and ran.

I changed APP_ERROR_CHECK(err_code) statements in my gap_params_init function into printf statements to print out the error code and I got err_code = 12289 for both sd_ble_gap_device_name_set and sd_ble_gap_ppcp_set.

I have already found out that this error code means that sd_ble_enable has not been called, however, I had also made sure that sd_ble_enable was actually called before it gets to gap_params_init(). The sd_ble_enable was called inside a function named softdevice_enable, and softdevice_enable was called inside ble_stack_init(). I have also added debugging printf statements inside my ble_stack_init function and made sure that softdevice_enable was indeed called successfully before the program gets to gap_params_init().

I am not sure why I am getting this error code.

  • Hi.

    Are you sure that you have not made any SoftDevice calls before you enabled it?

    Could I look at you code? I can make the case private if you don't wish to share your code public.

    Best regards.

    Andreas

  • Thank you for your reply. I have no problem sharing the code. It's just that, because I am really still a beginner with both BLE and Nordic, I am currently just in the stage of trying to merge the blinky example with our existing working version of an accelerometer program. You will see big chunks from the example commented out in this version because I wanted to add back the different initiation functions needed for Bluetooth one by one, when I know the previous one I already added does not break anything. I haven't started cleaning things out which I don't need from the examples yet so it might look like a mess. Hope you can still tell my order how the functions are call though.

    // =====================================================================
    // Accelerometer program UART -> BLE
    // main.c
    // Modified to comply with nRF5 SDK 12.3
    // 2018-12-07
    // Yilun Sheng
    // ITU
    // =====================================================================
    
    // Standard library includes
    #include <stdio.h>
    
    // nRF52 includes
    #include "nrf_delay.h" // busy wait functions
    #include "nrf_drv_gpiote.h" // nrf_drv_gpiote_evt_handler_t
    
    // Local includes
    #include "uart.h" // uart_init()
    #include "lis3dh.h" // lis3dh_init(), lis3dh_read_data()
    
    // BLE includes
    #include "nordic_common.h"
    #include "nrf.h"
    #include "app_error.h"
    #include "ble.h"
    #include "ble_hci.h"
    #include "ble_srv_common.h"
    #include "ble_advdata.h"
    #include "ble_conn_params.h"
    #include "ble_lbs.h"
    #include "bsp.h" // Board Support Package - Needed
    #include "ble_gap.h"
    #include "softdevice_handler.h"
    #include "app_timer.h"
    #include "app_button.h"
    #include "nrf_log.h"
    
    // =====================================================================
    
    #define CENTRAL_LINK_COUNT 0 /**< Number of central links used by the application. When changing this number remember to adjust the RAM settings*/
    #define PERIPHERAL_LINK_COUNT 1 /**< Number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
    
    #if (NRF_SD_BLE_API_VERSION == 3)
    #define NRF_BLE_MAX_MTU_SIZE GATT_MTU_SIZE_DEFAULT /**< MTU size used in the softdevice enabling and to reply to a BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event. */
    #endif
    
    #define APP_FEATURE_NOT_SUPPORTED BLE_GATT_STATUS_ATTERR_APP_BEGIN + 2 /**< Reply when unsupported features are requested. */
    #define ADVERTISING_LED_PIN BSP_BOARD_LED_0 /**< Is on when device is advertising. */
    #define CONNECTED_LED_PIN BSP_BOARD_LED_1 /**< Is on when device has connected. */
    
    #define LEDBUTTON_LED_PIN BSP_BOARD_LED_2 /**< LED to be toggled with the help of the LED Button Service. */
    
    #define DEVICE_NAME "Accelerometer_Modified"
    
    #define APP_ADV_INTERVAL 64 /**< The advertising interval (in units of 0.625 ms; this value corresponds to 40 ms). */
    #define APP_ADV_TIMEOUT_IN_SECONDS BLE_GAP_ADV_TIMEOUT_GENERAL_UNLIMITED /**< The advertising time-out (in units of seconds). When set to 0, we will never time out. */
    
    #define APP_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. */
    
    #define MIN_CONN_INTERVAL MSEC_TO_UNITS(100, UNIT_1_25_MS) /**< Minimum acceptable connection interval (0.5 seconds). */
    #define MAX_CONN_INTERVAL MSEC_TO_UNITS(200, UNIT_1_25_MS) /**< Maximum acceptable connection interval (1 second). */
    #define SLAVE_LATENCY 0 /**< Slave latency. */
    #define CONN_SUP_TIMEOUT MSEC_TO_UNITS(4000, UNIT_10_MS) /**< Connection supervisory time-out (4 seconds). */
    
    #define FIRST_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(20000, APP_TIMER_PRESCALER) /**< Time from initiating event (connect or start of notification) to first time sd_ble_gap_conn_param_update is called (15 seconds). */
    #define NEXT_CONN_PARAMS_UPDATE_DELAY APP_TIMER_TICKS(5000, APP_TIMER_PRESCALER) /**< Time between each call to sd_ble_gap_conn_param_update after the first call (5 seconds). */
    #define MAX_CONN_PARAMS_UPDATE_COUNT 3 /**< Number of attempts before giving up the connection parameter negotiation. */
    
    static uint16_t m_conn_handle = BLE_CONN_HANDLE_INVALID; /**< Handle of the current connection. */
    static ble_lbs_t m_lbs; /**< LED Button Service instance. */
    
    // =====================================================================
    /**@brief Function for the GAP initialization.
    *
    * @details This function sets up all the necessary GAP (Generic Access Profile) parameters of the
    * device including the device name, appearance, and the preferred connection parameters.
    */
    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);
    
    err_code = sd_ble_gap_device_name_set(&sec_mode,
    (const uint8_t *)DEVICE_NAME,
    strlen(DEVICE_NAME));
    if (err_code != NRF_SUCCESS)
    {
    printf("sd_ble_gap_device_name_set ERROR.\n");
    printf ("err_code = %ld\n", 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);
    if (err_code != NRF_SUCCESS)
    {
    printf("sd_ble_gap_ppcp_set ERROR.\n");
    printf ("err_code = %ld\n", err_code);
    }
    }
    
    //~ /**@brief Function for initializing the Advertising functionality.
    //~ *
    //~ * @details Encodes the required advertising data and passes it to the stack.
    //~ * Also builds a structure to be passed to the stack when starting advertising.
    //~ */
    //~ static void advertising_init(void)
    //~ {
    //~ uint32_t err_code;
    //~ ble_advdata_t advdata;
    //~ ble_advdata_t scanrsp;
    
    //~ ble_uuid_t adv_uuids[] = {{LBS_UUID_SERVICE, m_lbs.uuid_type}};
    
    //~ // Build and set advertising data
    //~ memset(&advdata, 0, sizeof(advdata));
    
    //~ advdata.name_type = BLE_ADVDATA_FULL_NAME;
    //~ advdata.include_appearance = true;
    //~ advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
    
    
    //~ memset(&scanrsp, 0, sizeof(scanrsp));
    //~ scanrsp.uuids_complete.uuid_cnt = sizeof(adv_uuids) / sizeof(adv_uuids[0]);
    //~ scanrsp.uuids_complete.p_uuids = adv_uuids;
    
    //~ err_code = ble_advdata_set(&advdata, &scanrsp);
    //~ APP_ERROR_CHECK(err_code);
    //~ }
    
    //~ /**@brief Function for handling write events to the LED characteristic.
    //~ *
    //~ * @param[in] p_lbs Instance of LED Button Service to which the write applies.
    //~ * @param[in] led_state Written/desired state of the LED.
    //~ */
    //~ static void led_write_handler(ble_lbs_t * p_lbs, uint8_t led_state)
    //~ {
    //~ if (led_state)
    //~ {
    //~ bsp_board_led_on(LEDBUTTON_LED_PIN);
    //~ NRF_LOG_INFO("Received LED ON!\r\n");
    //~ }
    //~ else
    //~ {
    //~ bsp_board_led_off(LEDBUTTON_LED_PIN);
    //~ NRF_LOG_INFO("Received LED OFF!\r\n");
    //~ }
    //~ }
    
    //~ /**@brief Function for initializing services that will be used by the application.
    //~ */
    //~ static void services_init(void)
    //~ {
    //~ uint32_t err_code;
    //~ ble_lbs_init_t init;
    
    //~ init.led_write_handler = led_write_handler;
    
    //~ err_code = ble_lbs_init(&m_lbs, &init);
    //~ APP_ERROR_CHECK(err_code);
    //~ }
    
    //~ /**@brief Function for handling the Connection Parameters Module.
    //~ *
    //~ * @details This function will be called for all events in the Connection Parameters Module that
    //~ * 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 a Connection Parameters error.
    //~ *
    //~ * @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 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 starting advertising.
    */
    static void advertising_start(void)
    {
    uint32_t err_code;
    ble_gap_adv_params_t adv_params;
    
    // Start advertising
    memset(&adv_params, 0, sizeof(adv_params));
    
    adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
    adv_params.p_peer_addr = NULL;
    adv_params.fp = BLE_GAP_ADV_FP_ANY;
    adv_params.interval = APP_ADV_INTERVAL;
    adv_params.timeout = APP_ADV_TIMEOUT_IN_SECONDS;
    
    err_code = sd_ble_gap_adv_start(&adv_params);
    APP_ERROR_CHECK(err_code);
    bsp_board_led_on(ADVERTISING_LED_PIN);
    }
    
    /**@brief Function for handling the Application's BLE stack events.
    *
    * @param[in] p_ble_evt Bluetooth stack event.
    */
    static void on_ble_evt(ble_evt_t * p_ble_evt)
    {
    uint32_t err_code;
    
    switch (p_ble_evt->header.evt_id)
    {
    case BLE_GAP_EVT_CONNECTED:
    NRF_LOG_INFO("Connected\r\n");
    bsp_board_led_on(CONNECTED_LED_PIN);
    bsp_board_led_off(ADVERTISING_LED_PIN);
    m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
    
    err_code = app_button_enable();
    APP_ERROR_CHECK(err_code);
    break; // BLE_GAP_EVT_CONNECTED
    
    case BLE_GAP_EVT_DISCONNECTED:
    NRF_LOG_INFO("Disconnected\r\n");
    bsp_board_led_off(CONNECTED_LED_PIN);
    m_conn_handle = BLE_CONN_HANDLE_INVALID;
    
    err_code = app_button_disable();
    APP_ERROR_CHECK(err_code);
    
    advertising_start();
    break; // BLE_GAP_EVT_DISCONNECTED
    
    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; // BLE_GAP_EVT_SEC_PARAMS_REQUEST
    
    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; // BLE_GATTS_EVT_SYS_ATTR_MISSING
    
    case BLE_GATTC_EVT_TIMEOUT:
    // Disconnect on GATT Client timeout event.
    NRF_LOG_DEBUG("GATT Client Timeout.\r\n");
    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; // BLE_GATTC_EVT_TIMEOUT
    
    case BLE_GATTS_EVT_TIMEOUT:
    // Disconnect on GATT Server timeout event.
    NRF_LOG_DEBUG("GATT Server Timeout.\r\n");
    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; // BLE_GATTS_EVT_TIMEOUT
    
    case BLE_EVT_USER_MEM_REQUEST:
    err_code = sd_ble_user_mem_reply(p_ble_evt->evt.gattc_evt.conn_handle, NULL);
    APP_ERROR_CHECK(err_code);
    break; // BLE_EVT_USER_MEM_REQUEST
    
    case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
    {
    ble_gatts_evt_rw_authorize_request_t req;
    ble_gatts_rw_authorize_reply_params_t auth_reply;
    
    req = p_ble_evt->evt.gatts_evt.params.authorize_request;
    
    if (req.type != BLE_GATTS_AUTHORIZE_TYPE_INVALID)
    {
    if ((req.request.write.op == BLE_GATTS_OP_PREP_WRITE_REQ) ||
    (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_NOW) ||
    (req.request.write.op == BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL))
    {
    if (req.type == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
    {
    auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
    }
    else
    {
    auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_READ;
    }
    auth_reply.params.write.gatt_status = APP_FEATURE_NOT_SUPPORTED;
    err_code = sd_ble_gatts_rw_authorize_reply(p_ble_evt->evt.gatts_evt.conn_handle,
    &auth_reply);
    APP_ERROR_CHECK(err_code);
    }
    }
    } break; // BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST
    
    #if (NRF_SD_BLE_API_VERSION == 3)
    case BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST:
    err_code = sd_ble_gatts_exchange_mtu_reply(p_ble_evt->evt.gatts_evt.conn_handle,
    NRF_BLE_MAX_MTU_SIZE);
    APP_ERROR_CHECK(err_code);
    break; // BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST
    #endif
    
    default:
    // No implementation needed.
    break;
    }
    }
    
    /**@brief Function for dispatching a BLE stack event to all modules with a BLE stack event handler.
    *
    * @details This function is called from the scheduler in the main loop after a BLE stack
    * event has been received.
    *
    * @param[in] p_ble_evt Bluetooth stack event.
    */
    static void ble_evt_dispatch(ble_evt_t * p_ble_evt)
    {
    on_ble_evt(p_ble_evt);
    ble_conn_params_on_ble_evt(p_ble_evt);
    ble_lbs_on_ble_evt(&m_lbs, p_ble_evt);
    }
    
    static void ble_stack_init(void)
    {
    uint32_t err_code;
    
    nrf_clock_lf_cfg_t clock_lf_cfg = NRF_CLOCK_LFCLKSRC;
    
    // Initialize the SoftDevice handler module.
    SOFTDEVICE_HANDLER_INIT(&clock_lf_cfg, NULL);
    
    ble_enable_params_t ble_enable_params;
    err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
    PERIPHERAL_LINK_COUNT,
    &ble_enable_params);
    APP_ERROR_CHECK(err_code);
    
    //Check the ram settings against the used number of links
    CHECK_RAM_START_ADDR(CENTRAL_LINK_COUNT, PERIPHERAL_LINK_COUNT);
    
    // Enable BLE stack.
    #if (NRF_SD_BLE_API_VERSION == 3)
    ble_enable_params.gatt_enable_params.att_mtu = NRF_BLE_MAX_MTU_SIZE;
    #endif
    
    err_code = softdevice_enable(&ble_enable_params);
    APP_ERROR_CHECK(err_code);
    printf("Softdevice Enabled.\n");
    
    // Subscribe for BLE events.
    err_code = softdevice_ble_evt_handler_set(ble_evt_dispatch);
    APP_ERROR_CHECK(err_code);
    }
    
    int main(void)
    {
    ret_code_t err_code = NRF_SUCCESS;
    
    nrf_delay_ms(1000);
    err_code = uart_init();
    printf("Testing UART\n");
    ble_stack_init();
    gap_params_init();
    //~ services_init();
    //~ advertising_init();
    //~ conn_params_init();
    //~ advertising_start();
    // If it is hard to remove functions such as leds_init() and 
    // buttons_init(), consider keeping them. timers_init() may be a
    // problem because the accelerometer runs its own timer.
    // NRF_LOG_INIT() is a substitue for the UART. You may want to use
    // it until you have Bluetooth working to print messages from your
    // program.
    if (err_code == NRF_SUCCESS)
    {
    printf("<< Accelerometer_Modified, SDK 12.3, 2018-12-07. >>\n");
    err_code = lis3dh_init((nrf_drv_gpiote_evt_handler_t) lis3dh_read_data);
    if (err_code == NRF_SUCCESS)
    {
    printf("Data transmission (in binary) begins in ten seconds.\n");
    nrf_delay_ms(9000);
    transmit_delimiter();
    nrf_delay_ms(1000);
    lis3dh_enable_interrupt();
    while(true)
    __WFI(); // infinite loop, wait for interrupts. Is power_manage() different? Is it specific to Bluetooth?
    }
    puts("Exiting.");
    }
    return 0;
    }

  • Hi.

    I don't see any immediate faults, could you perhaps share the project, so that I can compile it and step through it?

    Best regards,

    Andreas

  • Accelerometer SDK 12.3 Modified.zip

    Here you go. Let me know if this works. Thank you very much for being willing to help.

  • Hi.

    I think there is a issue with your Makefile, it did not work (same problem as you had) with the Makefile in your project.

    I took and stripped a UART example and used your code with the Makefile provided by this example, and it worked without any issues.

    ble_uart_stripped.zip

    I suggest you take a look at that Makefile, found in ble_app_uart_stripped\pca10040\s132\armgcc

    Best regards,

    Andreas

Related