/* * 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 processing ANTFS upload request data event. * * @param[in] p_event The event extracted from the queue to be processed. */ static void antfs_event_upload_request_handle(const antfs_event_return_t * p_event) { uint32_t err_code = RESPONSE_MESSAGE_OK; uint8_t new_request = false; if ((m_antfs_dfu_state == ANTFS_DFU_STATE_FLASH_ERASE) || (m_antfs_dfu_state == ANTFS_DFU_STATE_FLASH_PENDING)) { return; } /*reset*/ m_response_info.file_index.data = p_event->file_index; m_response_info.max_burst_block_size.data = 0; m_response_info.max_file_size = 0; m_response_info.file_size.data = 0; m_response_info.file_crc = 0; // Evaluate File Index first if (m_current_file_index != p_event->file_index ) { m_current_file_index = p_event->file_index; m_current_offset = 0; m_current_crc = 0; } if (p_event->offset == MAX_ULONG) { // This is a request to continue upload. } else if (p_event->offset == 0x00) { new_request = true; } else if(p_event->offset != m_current_offset) { // Something is wrong. UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_INVALID_OPERATION, &m_response_info)); m_antfs_dfu_state = ANTFS_DFU_STATE_STALL; } else { // no implementation. } switch (m_current_file_index) { #if !defined (S210_V3_STACK) case ANTFS_FILE_INDEX_UPDATE_STACK: case ANTFS_FILE_INDEX_UPDATE_BOOTLOADER: case ANTFS_FILE_INDEX_UPDATE_STACK_BOOTLOADER: #endif // S210_V3_STACK case ANTFS_FILE_INDEX_UPDATE_APPLICATION: { // Current valid file size is the last offset written to the file. m_response_info.file_size.data = m_current_offset; // Intentionally report maximum allowed upload file size as max writeable file size + header and crc. // Writeable size check will be performed by dfu_start_pkt_handle() after parsing uploaded header m_response_info.max_file_size = ANTFS_FILE_SIZE_MAX_DFU_IMAGE + OTA_IMAGE_HEADER_SIZE_MAX; // Maximum burst block should be maximum allowable downloadable file size. m_response_info.max_burst_block_size.data = ANTFS_FILE_SIZE_MAX_DFU_IMAGE + OTA_IMAGE_HEADER_SIZE_MAX; // Last valid CRC. m_response_info.file_crc = m_current_crc; // Will only handle upload request while at ANTFS_DFU_STATE_READY if (m_antfs_dfu_state == ANTFS_DFU_STATE_VALIDATED) { if (new_request) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_AVAILABLE, &m_response_info)); } else { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_OK, &m_response_info)); // To handle resume at end of data. } return; } else if (m_antfs_dfu_state != ANTFS_DFU_STATE_READY) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_AVAILABLE, &m_response_info)); return; } // Check File Size if it can still fit. Uploaded file size may be larger than the total writeable space because it includes header // and CRC that do not get written to flash. Writeable size check will be performed by dfu_start_pk_handle() after // parsing uploaded header if ((p_event->offset + p_event->bytes) > (ANTFS_FILE_SIZE_MAX_DFU_IMAGE + OTA_IMAGE_HEADER_SIZE_MAX + OTA_IMAGE_CRC_SIZE_MAX)) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_ENOUGH_SPACE, &m_response_info)); return; } m_data_buffered = 0; if (new_request) { m_current_offset = 0; m_current_crc = 0; m_pending_offset = 0; antfs_ota_init(); // Only supports offset starting at 0; if (p_event->offset != 0) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_FAIL, &m_response_info)); return; } // boot_return_set(PARAM_RETURN_BOOT_STATUS_Entered); // Store file size, m_current_file_size = p_event->bytes; if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_STACK) { m_update_mode = DFU_UPDATE_SD; } else if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_BOOTLOADER) { m_update_mode = DFU_UPDATE_BL; } else if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_APPLICATION) { m_update_mode = DFU_UPDATE_APP; } else if (m_current_file_index == ANTFS_FILE_INDEX_UPDATE_STACK_BOOTLOADER) { m_update_mode = DFU_UPDATE_SD; m_update_mode |= DFU_UPDATE_BL;//lint !e655 suppress Lint Warning 655: Bit-wise operations } m_dfu_pkt.packet_type = INIT_PACKET; if ((*ANT_BOOT_APP_SIZE > DFU_IMAGE_MAX_SIZE_BANKED) || (*ANT_BOOT_APP_SIZE == 0xFFFFFFFF) || (*ANT_BOOT_APP_SIZE == 0x00000000) || (m_update_mode & DFU_UPDATE_SD))/*lint !e655 suppress Lint Warning 655: Bit-wise operations*/ { m_dfu_pkt.params.init_packet.total_image_size = DFU_IMAGE_MAX_SIZE_FULL; } else { m_dfu_pkt.params.init_packet.total_image_size = m_current_file_size; } if (m_upload_swap_space_prepared == true) { // Prepare no flash, except the states m_dfu_pkt.params.init_packet.total_image_size = 0; } err_code = dfu_init_pkt_handle(&m_dfu_pkt); if (err_code) { if (err_code == NRF_ERROR_INVALID_STATE) { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_INVALID_OPERATION, &m_response_info)); } else { UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_FAIL, &m_response_info)); } return; } m_ota_image_header_parsed = false; m_image_data_complete = false; m_image_data_offset = 0; m_data_buffered = 0; // A flash erase is expected at this time. postpone response if there is. if (flash_busy()) { m_upload_request_in_progress = true; m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_ERASE; return; } } else { // Check if there are still pending writes scheduled in Flash. if (flash_busy()) { m_upload_request_in_progress = true; m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_PENDING; return; } } m_antfs_dfu_state = ANTFS_DFU_STATE_READY; UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_OK, &m_response_info)); } break; default: m_antfs_dfu_state = ANTFS_DFU_STATE_READY; UNUSED_VARIABLE(antfs_upload_req_resp_transmit(RESPONSE_MESSAGE_NOT_EXIST, &m_response_info)); } }
/**@brief Function for processing ANTFS upload request data event. * * @param[in] p_event The event extracted from the queue to be processed. */ static void event_upload_request_handle(const antfs_event_return_t * p_event) { uint8_t response = RESPONSE_MESSAGE_OK; if ((p_event->offset == MAX_ULONG)) { // Requesting to resume an upload. if (m_file_index != p_event->file_index) { // We do not have a save point for this file. m_file_offset = 0; m_current_crc = 0; } } else { // This is a new upload. // Use requested offset and reset CRC. m_file_offset = p_event->offset; m_current_crc = 0; } m_file_index = p_event->file_index; // Read file information from directory. if (mem_file_info_get(m_file_index, &m_temp_dir_structure)) { // Check permissions. if (!(m_temp_dir_structure.general_flags & ANTFS_DIR_WRITE_MASK)) { response = RESPONSE_MESSAGE_NOT_AVAILABLE; printf("Upload request denied: file n/a for writing\n"); } // Set response parameters. m_response_info.file_index.data = m_file_index; // Current valid file size is the last offset written to the file. m_response_info.file_size.data = m_file_offset; // Space available for writing is the file size, as specified on directory. m_response_info.max_file_size = m_temp_dir_structure.file_size_in_bytes; // Get the entire file in a single burst if possible. m_response_info.max_burst_block_size.data = m_temp_dir_structure.file_size_in_bytes; // Last valid CRC. m_response_info.file_crc = m_current_crc; } else { // Index not found. response = RESPONSE_MESSAGE_NOT_EXIST; m_response_info.file_index.data = m_file_index; m_response_info.file_size.data = 0; m_response_info.max_file_size = 0; m_response_info.max_burst_block_size.data = 0; m_response_info.file_crc = 0; printf("Upload request denied: file does not exist\n"); } m_upload_success = true; // @note: Suppress return value as no use case for handling it exists. UNUSED_VARIABLE(antfs_upload_req_resp_transmit(response, &m_response_info)); }