static void process_dfu_packet(void * p_event_data, uint16_t event_size) { uint32_t retval; uint32_t index; dfu_update_packet_t * packet; while (false == DATA_QUEUE_EMPTY()) { // Fetch the element to be processed. for (index = 0; index < MAX_BUFFERS ; index++) { packet = &m_data_queue.data_packet[index]; if (INVALID_PACKET != packet->packet_type) { switch (DATA_QUEUE_ELEMENT_GET_PTYPE(index)) { case DATA_PACKET: (void)dfu_data_pkt_handle(packet); break; case START_PACKET: packet->params.start_packet = (dfu_start_packet_t*)packet->params.data_packet.p_data_packet; retval = dfu_start_pkt_handle(packet); APP_ERROR_CHECK(retval); break; case STOP_DATA_PACKET: (void)dfu_image_validate(); (void)dfu_image_activate(); // Break the loop by returning. return; case INIT_PACKET: // Validate init packet. // We expect to receive the init packet in two rounds of 512 bytes. // If that fails, we abort, and boot the application. // @note: Current release doesn't handle an init packet. break; default: // No implementation needed. break; } // Free the processed element. retval = data_queue_element_free(index); APP_ERROR_CHECK(retval); } } } }
static void process_dfu_packet(void * p_event_data, uint16_t event_size) { uint32_t retval; uint32_t index; dfu_update_packet_t * packet; while (false == DATA_QUEUE_EMPTY()) { // Fetch the element to be processed. for (index = 0; index < MAX_BUFFERS ; index++) { packet = &m_data_queue.data_packet[index]; if (INVALID_PACKET != packet->packet_type) { switch (DATA_QUEUE_ELEMENT_GET_PTYPE(index)) { case DATA_PACKET: (void)dfu_data_pkt_handle(packet); break; case START_PACKET: packet->params.start_packet = (dfu_start_packet_t*)packet->params.data_packet.p_data_packet; retval = dfu_start_pkt_handle(packet); APP_ERROR_CHECK(retval); break; case INIT_PACKET: (void)dfu_init_pkt_handle(packet); retval = dfu_init_pkt_complete(); APP_ERROR_CHECK(retval); break; case STOP_DATA_PACKET: (void)dfu_image_validate(); (void)dfu_image_activate(); // Break the loop by returning. return; default: // No implementation needed. break; } // Free the processed element. retval = data_queue_element_free(index); APP_ERROR_CHECK(retval); } } } }
static void antfs_event_upload_complete_handle(const antfs_event_return_t * p_event) { uint32_t err_code; if (m_antfs_dfu_state == ANTFS_DFU_STATE_VALIDATED) { // only send this response if we have validated the upload UNUSED_VARIABLE(antfs_upload_data_resp_transmit(true)); } else if (m_antfs_dfu_state == ANTFS_DFU_STATE_READY) { if (flash_busy()) { m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_PENDING; // Image completed but still busy writing, postpone it on flash call back. return; } if (m_image_data_complete == true) { err_code = dfu_image_validate(m_header_crc_seed); if (err_code == NRF_SUCCESS) { m_antfs_dfu_state = ANTFS_DFU_STATE_VALIDATED; UNUSED_VARIABLE(antfs_upload_data_resp_transmit(true)); } else { upload_data_response_fail_reset(); } } else { UNUSED_VARIABLE(antfs_upload_data_resp_transmit(true)); // This is expected on block transfers. } } else { // no implementation } }
/**@brief Function for the Device Firmware Update Service event handler. * * @details This function will be called for all Device Firmware Update Service events which * are passed to the application. * * @param[in] p_dfu Device Firmware Update Service structure. * @param[in] p_evt Event received from the Device Firmware Update Service. */ static void on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; switch (p_evt->ble_dfu_evt_type) { case BLE_DFU_VALIDATE: err_code = dfu_image_validate(); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_err_code_translate(err_code, BLE_DFU_VALIDATE_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_VALIDATE_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); break; case BLE_DFU_ACTIVATE_N_RESET: err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); // With the S110 Flash API it is safe to initiate the activate before connection is // fully closed. err_code = dfu_image_activate(); if (err_code != NRF_SUCCESS) { dfu_reset(); } break; case BLE_DFU_SYS_RESET: err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); dfu_reset(); break; case BLE_DFU_START: m_pkt_type = PKT_TYPE_START; if (p_evt->evt.ble_dfu_pkt_write.len == 0) { m_update_mode = DFU_UPDATE_APP; } else { m_update_mode = (uint8_t)p_evt->evt.ble_dfu_pkt_write.p_data[0]; } break; case BLE_DFU_RECEIVE_INIT_DATA: m_pkt_type = PKT_TYPE_INIT; break; case BLE_DFU_RECEIVE_APP_DATA: m_pkt_type = PKT_TYPE_FIRMWARE_DATA; break; case BLE_DFU_PACKET_WRITE: on_dfu_pkt_write(p_dfu, p_evt); break; case BLE_DFU_PKT_RCPT_NOTIF_ENABLED: m_pkt_rcpt_notif_enabled = true; m_pkt_notif_target = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; m_pkt_notif_target_cnt = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; break; case BLE_DFU_PKT_RCPT_NOTIF_DISABLED: m_pkt_rcpt_notif_enabled = false; m_pkt_notif_target = 0; break; case BLE_DFU_BYTES_RECEIVED_SEND: err_code = ble_dfu_bytes_rcvd_report(p_dfu, m_num_of_firmware_bytes_rcvd); APP_ERROR_CHECK(err_code); break; default: // Unsupported event received from DFU Service. Ignore. break; } }
/* * NOTE: This callback is only called by the following * - Storing done operation by dfu_data_pkt_handle * - And all clearing done operation. */ static void dfu_cb_handler(uint32_t result, uint8_t * p_data) { uint32_t err_code; uint16_t rxd_buffer_len = 0; uint16_t ram_crc = 0; uint16_t flash_crc = 0; #if defined (DBG_DFU_UART_OUT_PIN) DEBUG_UART_OUT(0xFF); DEBUG_UART_OUT(m_antfs_dfu_state); #endif switch (m_antfs_dfu_state) { case ANTFS_DFU_STATE_INIT_DELAYED: // This is when upon initialization, a pre-erase operation have occured i.e. bank1 pre clearing. services_init(); break; case ANTFS_DFU_STATE_FLASH_ERASE: // Handles upload and download request response delay when there is ongoing flash activities // Generally we need to avoid flash activities and burst activities to happen at the same time. // ANTFS request response are delayed and when flash is done response are handled here. if (m_upload_request_in_progress) { m_upload_request_in_progress = false; // Make sure we got all the latest values. m_response_info.file_size.data = m_current_offset; m_response_info.file_crc = m_current_crc; if (result == NRF_SUCCESS) { m_upload_swap_space_prepared = true; UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_OK, &m_response_info)); } else { /* Not ready */ UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_UPLOAD_NOT_READY, &m_response_info)); } } if (m_download_request_in_progress) { m_download_request_in_progress = false; UNUSED_VARIABLE(antfs_download_req_resp_prepare(RESPONSE_MESSAGE_OK, &m_response_info)); } m_antfs_dfu_state = ANTFS_DFU_STATE_READY; break; case ANTFS_DFU_STATE_FLASH_PENDING: case ANTFS_DFU_STATE_READY: // Handles Flash write call back queued by Upload Data. if (result != NRF_SUCCESS) { upload_data_response_fail_reset(); return; } if ((m_mem_pool_1.a_mem_pool <= p_data) && (p_data <= (m_mem_pool_1.a_mem_pool + ANTFS_UPLOAD_DATA_BUFFER_MAX_SIZE))) { rxd_buffer_len = m_mem_pool_1.size; ram_crc = m_mem_pool_1.crc; m_mem_pool_1.size = 0; } else if ((m_mem_pool_2.a_mem_pool <= p_data) && (p_data <= (m_mem_pool_2.a_mem_pool + ANTFS_UPLOAD_DATA_BUFFER_MAX_SIZE))) { rxd_buffer_len = m_mem_pool_2.size; ram_crc = m_mem_pool_2.crc; m_mem_pool_2.size = 0; } else { upload_data_response_fail_reset(); return; } // Verify the data written to flash. flash_crc = crc_crc16_update(0, (uint8_t*)(dfu_storage_start_address_get() + m_image_data_offset), rxd_buffer_len); if (flash_crc != ram_crc) { upload_data_response_fail_reset(); return; } //update current offsets and crc m_current_offset += rxd_buffer_len; m_current_crc = crc_crc16_update(m_current_crc, (uint8_t*)(dfu_storage_start_address_get() + m_image_data_offset), rxd_buffer_len); m_image_data_offset += rxd_buffer_len; if (m_antfs_dfu_state == ANTFS_DFU_STATE_FLASH_PENDING) { m_antfs_dfu_state = ANTFS_DFU_STATE_READY; // Update it with the latest values; m_response_info.file_size.data = m_current_offset; m_response_info.file_crc = m_current_crc; if (m_upload_request_in_progress) { m_upload_request_in_progress = false; UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_OK, &m_response_info)); } else // data response { if (m_image_data_complete == true) { if (m_image_data_max == m_image_data_offset) { err_code = dfu_image_validate(m_header_crc_seed); if (err_code == NRF_SUCCESS) { UNUSED_VARIABLE(antfs_upload_data_resp_transmit(true)); m_antfs_dfu_state = ANTFS_DFU_STATE_VALIDATED; return; } else { upload_data_response_fail_reset(); } } if ((m_mem_pool_1.size != 0) || (m_mem_pool_2.size != 0)) { m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_PENDING; } } else //m_image_data_complete == false { if ((m_mem_pool_1.size == 0) && (m_mem_pool_2.size == 0)) { UNUSED_VARIABLE(antfs_upload_data_resp_transmit(true)); // Handles block transfers } else { m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_PENDING; } } } } break; default: break; } }
/**@brief Function for the Device Firmware Update Service event handler. * * @details This function will be called for all Device Firmware Update Service events which * are passed to the application. * * @param[in] p_dfu Device Firmware Update Service structure. * @param[in] p_evt Event received from the Device Firmware Update Service. */ static void on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) { uint32_t err_code; switch (p_evt->ble_dfu_evt_type) { case BLE_DFU_VALIDATE: err_code = dfu_image_validate(); // Translate the err_code returned by the above function to DFU Response Value. ble_dfu_resp_val_t resp_val; resp_val = nrf_error_to_dfu_resp_val(err_code, BLE_DFU_VALIDATE_PROCEDURE); err_code = ble_dfu_response_send(p_dfu, BLE_DFU_VALIDATE_PROCEDURE, resp_val); APP_ERROR_CHECK(err_code); break; case BLE_DFU_ACTIVATE_N_RESET: // Final state of DFU is reached. m_activate_img_after_tear_down = true; err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); break; case BLE_DFU_SYS_RESET: err_code = dfu_transport_close(); APP_ERROR_CHECK(err_code); break; case BLE_DFU_START: m_pkt_type = PKT_TYPE_START; break; case BLE_DFU_RECEIVE_INIT_DATA: m_pkt_type = PKT_TYPE_INIT; break; case BLE_DFU_RECEIVE_APP_DATA: m_pkt_type = PKT_TYPE_FIRMWARE_DATA; break; case BLE_DFU_PACKET_WRITE: on_dfu_pkt_write(p_dfu, p_evt); break; case BLE_DFU_PKT_RCPT_NOTIF_ENABLED: m_pkt_rcpt_notif_enabled = true; m_pkt_notif_target = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; m_pkt_notif_target_cnt = p_evt->evt.pkt_rcpt_notif_req.num_of_pkts; break; case BLE_DFU_PKT_RCPT_NOTIF_DISABLED: m_pkt_rcpt_notif_enabled = false; m_pkt_notif_target = 0; break; case BLE_DFU_BYTES_RECEIVED_SEND: err_code = ble_dfu_bytes_rcvd_report(p_dfu, m_num_of_firmware_bytes_rcvd); APP_ERROR_CHECK(err_code); break; default: // Unsupported event received from DFU Service. Ignore. break; } }