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

DFU Fail,error_code = 12292

I am trying DFU with:

  • BOARD_PCA10040,
  • nRF52_SDK_0.9.2_dbc28c9
  • s132_nrf52_1.0.0-3.alpha

One interesting thing is the SDK_0.9.2_dbc28c9 can not work with s132_nrf52_2.0.0-7.alpha and s132_nrf52_2.0.0-4.alpha, which suppose to be newer!

I use dual_bank_ble_s132 project in examples\dfu\bootloader, change the support board to BOARD_PCA10040. I can see the advertisement of DfuTarg in the Master Control Panel of my smart phone. When I choose the application hex dfu_test_app_hrm_s132.hex file in the \examples\dfu\ble_dfu_send_hex and start the DFU. The Master Control Panel shows:

  • "Connecting"
  • "Starting DFU..."
  • "0%"

and then the BOARD_PCA10040 restart !!! I debug the bootloader and catch the message:

0> m_error_code = 12292
0> m_line_num = 291
0> m_p_file_name=............\components\libraries\bootloader_dfu\dfu_transport_ble.c

The error take place in the file: ble_dfu.c the function: uint32_t ble_dfu_response_send(...) line 665: return sd_ble_gatts_hvx(p_dfu->conn_handle, &hvx_params);

and the uint32_t ble_dfu_response_send(...) function was called in the static void dfu_cb_handler(...) functon:

    case START_PACKET:
        // Translate the err_code returned by the above function to DFU Response Value.
        resp_val = nrf_err_code_translate(result, BLE_DFU_START_PROCEDURE);

        err_code = ble_dfu_response_send(&m_dfu,
                                         BLE_DFU_START_PROCEDURE,
                                         resp_val);
        APP_ERROR_CHECK(err_code);
        break;

What does it mean? Something wrong in the hex file? But it is the test file provide in the sdk. How can I modify to make it run?

  • There is an API change in for S132_nRF52_2.0.0-7 and in the release notes it says.

    GATTS Write Commands (Write Without Response) are now subject to attribute authorization. The incoming data will not be writteninto the Attribute Table, requiring the application to do so itself by using sd_ble_gatts_value_set() (DRGN-2460).

    This means that we have to explicitly put the requested data back to softdevice, using APIs:

    - sd_ble_gatts_value_set()
    - sd_ble_gatts_rw_authorize_reply()
    

    This means that the application has to set the value of attribute which has authorize flags in it. Some internal documentation about it which we are allowed to share is below .. This information will be public soon


    GATT Server Authorizable Write Commands:

    Whenever the application enables write authorization for a characteristic value or a descriptor in the attribute table (ble_gatts_attr_md_t::wr_auth) all incoming write operations will now require application authorization. In particular this now includes Write Commands (also called Write Without Request) which will arrive in the same event form (BLE_GATTS_EVT_WRITE) but with a new field set (ble_gatts_evt_write_t::auth_required) to indicate to the application that the data has not been written into the Attribute Table. Upon handling of the event the application is then free to parse the incoming data and decide whether it wants to write it to the Attribute Table or discard it.

    Handling incoming authorizable Write Commands case BLE_GATTS_EVT_WRITE:

    uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
    uint16_t attr_handle = p_ble_evt->evt.gatts_evt.params.write.handle;
    uint16_t offset = p_ble_evt->evt.gatts_evt.params.write.offset;
    uint8_t *p_data = p_ble_evt->evt.gatts_evt.params.write.data;
    uint16_t dlen = p_ble_evt->evt.gatts_evt.params.write.len;
    if(p_ble_evt->evt.gatts_evt.params.write.auth_required)
    {
        /* incoming write command on an attribute requiring authorization, validate the data */
        if(app_data_authorize(p_data, offset, len))
        {
            ble_gatts_value_t value;
            value.len = dlen;
            value.offset = offset;
            value.p_value = p_data;
            sd_ble_gatts_value_set(conn_handle, attr_handle, value);
        }
    }  
    break; 
    

    GATT Server Write Authorization and peer data:

    Applications making use of authorization to handle incoming write operations, and in particular for Write Request and app-handled Queued Writes, will now have to store the incoming data to be provided later to the SoftDevice. Depending on how the application handles the authorization procedure this can be done by simply providing the same pointer contained in the event field, or actually copying the data into a temporary storage area if required.

    Authorizing directly in the event handler: case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:

        if(p_ble_evt->evt.gatts_evt.params.authorize_request.type
    == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
        {
            uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
            uint16_t attr_handle = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.handle;
            uint16_t offset = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.offset;
            uint16_t dlen = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
            uint8_t *p_data = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data;
            /* incoming write command on an attribute requiring authorization, validate the data */
            if(app_data_authorize(p_data, offset, len))
            {
                ble_gatts_rw_authorize_reply_params_t auth_reply;
                auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
                auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
                auth_reply.params.write.update = 1;
                auth_reply.params.write.offset = offset;
                auth_reply.params.write.len = dlen;
                auth_reply.params.write.p_data = p_data;
     
                sd_ble_gatts_rw_authorize_reply(conn_handle, &auth_reply);
            }
        }  
        break;
    

    Authorizing outside of the event handler:

    /* global variable storing the authorization data */ struct  {
        uint16_t offset;
        uint16_t dlen;
        uint8_t data[MAX_DATA]; } auth_write;   [..]   case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
        if(p_ble_evt->evt.gatts_evt.params.authorize_request.type
    == BLE_GATTS_AUTHORIZE_TYPE_WRITE)
        {
            uint16_t conn_handle = p_ble_evt->evt.gatts_evt.conn_handle;
            /* store the metadata */
            auth_write.offset = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.offset;
            auth_write.dlen = p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.len;
            /* store the actual incoming data */
            memcpy(&auth_write.data, &p_ble_evt->evt.gatts_evt.params.authorize_request.request.write.data, auth_write.len);
        }  
        break;   [..]  
    
    /* authorization complete */
    ble_gatts_rw_authorize_reply_params_t auth_reply;
    auth_reply.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE;
    auth_reply.params.write.gatt_status = BLE_GATT_STATUS_SUCCESS;
    auth_reply.params.write.update = 1;
    /* obtain the data */
    auth_reply.params.write.offset = auth_write.offset;
    auth_reply.params.write.len = auth_write.dlen;
    auth_reply.params.write.p_data = auth_write.data;
     
    sd_ble_gatts_rw_authorize_reply(conn_handle, &auth_reply);
    

    my friends have proven me that my english is bad, so let me know if I surprisingly managed to make you understand this :)

Related