uint32_t dfu_transport_update_start(void) { uint32_t err_code; m_antfs_dfu_state = ANTFS_DFU_STATE_RESET; err_code = softdevice_ant_evt_handler_set(ant_evt_dispatch); if (err_code != NRF_SUCCESS) { return err_code; } // DFU flash activity call back. dfu_register_callback(dfu_cb_handler); // initialize mem_pools m_mem_pool_1.size = 0; m_mem_pool_2.size = 0; // It is expected that there was no ANTFS related activities before this point. // Check if flash is busy pre-initializing. // If Flash is still initializing wait until it is done. if (flash_busy()) { // Postpone services init and ANTFS init until flash is done. m_antfs_dfu_state = ANTFS_DFU_STATE_INIT_DELAYED; return NRF_SUCCESS; } // Start services right away if flash not busy services_init(); return NRF_SUCCESS; }
//Byte Page Program allows 1 to 256 bytes of data to be programmed into previously erased memory locations //Erased locations have a logical state fo 1 void flash_program(uint8_t address[3], uint8_t *data, int len) { int i; //First we need to enable write write_enable(); //Bring CSN low flash_csn_low(); //Write OPCODE flash_transfer_byte(BP_PROGRAM); //Write the three addresses flash_transfer_byte(address[2]); flash_transfer_byte(address[1]); flash_transfer_byte(address[0]); for(i=0;i<len;i++) { flash_transfer_byte(data[i]); } //Bring CSN high flash_csn_high(); //Loop until write actually has taken place. while(flash_busy() == 1); }
/**@brief Function for processing ANTFS download request event. * * @param[in] p_event The event extracted from the queue to be processed. */ static void antfs_event_download_request_handle(const antfs_event_return_t * p_event) { uint8_t response = RESPONSE_MESSAGE_OK; // Grab request info. m_current_file_index = p_event->file_index; // We only have one file in the directory. if (m_current_file_index == 0) // directory download { // Set response parameters. m_response_info.file_index.data = 0; // File size (per directory). m_response_info.file_size.data = sizeof(m_directory); // File is being read, so maximum size is the file size. m_response_info.max_file_size = sizeof(m_directory); // Send the entire file in a single block if possible. m_response_info.max_burst_block_size.data = sizeof(m_directory); } else if (m_current_file_index == ANTFS_FILE_INDEX_OTA_UPDATE_INFO) { // Set response parameters. m_response_info.file_index.data = ANTFS_FILE_INDEX_OTA_UPDATE_INFO; // File size (per directory). m_response_info.file_size.data = OTA_UPDATE_INFO_FILE_SIZE; // File is being read, so maximum size is the file size. m_response_info.max_file_size = OTA_UPDATE_INFO_FILE_SIZE; // Send the entire file in a single block if possible. m_response_info.max_burst_block_size.data = OTA_UPDATE_INFO_FILE_SIZE; } // Index not found. else { response = RESPONSE_MESSAGE_NOT_EXIST; m_response_info.file_index.data = 0; m_response_info.file_size.data = 0; m_response_info.max_file_size = 0; m_response_info.max_burst_block_size.data = 0; } if (response == RESPONSE_MESSAGE_OK) { // Check if there was scheduled in Flash. // TODO need to track flash activity better if (flash_busy()) { m_download_request_in_progress = 1; m_antfs_dfu_state = ANTFS_DFU_STATE_FLASH_ERASE; return; } antfs_download_req_resp_prepare(response, &m_response_info); } else { antfs_download_req_resp_prepare(response, &m_response_info); } }
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 } }
void block_erase(uint8_t address[3], uint8_t byte) { //First we need to enable write write_enable(); //Bring CSN low flash_csn_low(); //Write OPCODE flash_transfer_byte(byte); //Write the three addresses flash_transfer_byte(address[2]); flash_transfer_byte(address[1]); flash_transfer_byte(address[0]); //Bring CSN high flash_csn_high(); //Loop until erase actually has taken place. while(flash_busy() == 1); }
/**@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)); } }