static void start_target(void) { set_timeout(STATE_TIMEOUT_TARGET); m_state = BL_STATE_DFU_TARGET; uint32_t segment_size = 0; bl_info_entry_t flags_entry; memset(&flags_entry, 0xFF, (BL_INFO_LEN_FLAGS + 3) & ~0x03UL); switch (m_transaction.type) { case DFU_TYPE_SD: segment_size = m_bl_info_pointers.p_segment_sd->length; flags_entry.flags.sd_intact = false; break; case DFU_TYPE_APP: segment_size = m_bl_info_pointers.p_segment_app->length; flags_entry.flags.app_intact = false; break; case DFU_TYPE_BOOTLOADER: segment_size = m_bl_info_pointers.p_segment_bl->length; flags_entry.flags.bl_intact = false; break; default: segment_size = 0; } /* Tag the transfer as incomplete in device page if we're about to overwrite it. */ if (m_transaction.p_start_addr == m_transaction.p_bank_addr) { if (m_bl_info_pointers.p_flags == NULL) { m_bl_info_pointers.p_flags = &bootloader_info_entry_put(BL_INFO_TYPE_FLAGS, &flags_entry, BL_INFO_LEN_FLAGS)->flags; } else { /* update inline */ nrf_flash_store((uint32_t*) m_bl_info_pointers.p_flags, (uint8_t*) &flags_entry, (BL_INFO_LEN_FLAGS + 3) & ~0x03UL, 0); } } if (dfu_start( m_transaction.p_start_addr, m_transaction.p_bank_addr, m_transaction.length, segment_size, m_transaction.segment_is_valid_after_transfer) != NRF_SUCCESS) { start_req(m_transaction.type, true); } else { transport_tx_abort(mp_beacon); /* stop beaconing */ } }
static void bootloader_settings_save(bootloader_settings_t * p_settings) { nrf_flash_erase(m_bootsettings_handle,sizeof(bootloader_settings_t)); nrf_flash_store(m_bootsettings_handle, (uint8_t *)p_settings, sizeof(bootloader_settings_t), 0); if (m_update_status == BOOTLOADER_SETTINGS_SAVING) { m_update_status = BOOTLOADER_COMPLETE; } }
static void operation_execute(operation_t* p_op) { switch (p_op->type) { case FLASH_OP_TYPE_ERASE: nrf_flash_erase((uint32_t*) p_op->operation.erase.start_addr, p_op->operation.erase.length); break; case FLASH_OP_TYPE_WRITE: nrf_flash_store((uint32_t*) p_op->operation.write.start_addr, p_op->operation.write.p_data, p_op->operation.write.length, 0); break; default: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); } }
uint32_t dfu_data_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t data_length; uint32_t err_code; uint32_t * p_data; if (p_packet == NULL) { return NRF_ERROR_NULL; } // Check pointer alignment. if (!is_word_aligned(p_packet->params.data_packet.p_data_packet)) { // The p_data_packet is not word aligned address. return NRF_ERROR_INVALID_ADDR; } switch (m_dfu_state) { case DFU_STATE_RDY: case DFU_STATE_RX_INIT_PKT: return NRF_ERROR_INVALID_STATE; case DFU_STATE_RX_DATA_PKT: data_length = p_packet->params.data_packet.packet_length * sizeof(uint32_t); if ((m_data_received + data_length) > m_image_size) { // The caller is trying to write more bytes into the flash than the size provided to // the dfu_image_size_set function. This is treated as a serious error condition and // an unrecoverable one. Hence point the variable mp_app_write_address to the top of // the flash area. This will ensure that all future application data packet writes // will be blocked because of the above check. m_data_received = 0xFFFFFFFF; return NRF_ERROR_DATA_SIZE; } // Valid peer activity detected. Hence restart the DFU timer. err_code = dfu_timer_restart(); if (err_code != NRF_SUCCESS) { return err_code; } p_data = (uint32_t *)p_packet->params.data_packet.p_data_packet; nrf_flash_store(mp_storage_handle_active, (uint8_t *)p_data, data_length, m_data_received); m_data_received += data_length; if (m_data_received != m_image_size) { // The entire image is not received yet. More data is expected. err_code = NRF_ERROR_INVALID_LENGTH; } else { // The entire image has been received. Return NRF_SUCCESS. err_code = NRF_SUCCESS; } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
/** Interrupt handling Flash operations. */ void FLASH_HANDLER_IRQHandler(void) { flash_queue_entry_t flash_entry; uint32_t op_count = 0; while (fifo_pop(&m_flash_fifo, &flash_entry) == NRF_SUCCESS) { op_count++; bl_cmd_t rsp_cmd; if (flash_entry.type == FLASH_OP_TYPE_WRITE) { APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.start_addr)); APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.length)); APP_ERROR_CHECK_BOOL(IS_WORD_ALIGNED(flash_entry.op.write.p_data)); __LOG("WRITING to 0x%x.(len %d)\n", flash_entry.op.write.start_addr, flash_entry.op.write.length); if (flash_entry.op.write.start_addr >= 0x20000000) { uint8_t* p_dst = ((uint8_t*) flash_entry.op.write.start_addr); for (uint32_t i = 0; i < flash_entry.op.write.length; ++i, p_dst++) { *p_dst = (*p_dst & flash_entry.op.write.p_data[i]); } } else { nrf_flash_store((uint32_t*) flash_entry.op.write.start_addr, flash_entry.op.write.p_data, flash_entry.op.write.length, 0); } rsp_cmd.type = BL_CMD_TYPE_FLASH_WRITE_COMPLETE; rsp_cmd.params.flash.write.p_data = flash_entry.op.write.p_data; } else { __LOG("ERASING 0x%x.\n", flash_entry.op.erase.start_addr); if (flash_entry.op.erase.start_addr >= 0x20000000) { memset((uint32_t*) flash_entry.op.erase.start_addr, 0xFF, flash_entry.op.erase.length); } else { nrf_flash_erase((uint32_t*) flash_entry.op.erase.start_addr, flash_entry.op.erase.length); } rsp_cmd.type = BL_CMD_TYPE_FLASH_ERASE_COMPLETE; rsp_cmd.params.flash.erase.p_dest = (uint32_t*) flash_entry.op.erase.start_addr; } bl_cmd_handler(&rsp_cmd); } if (op_count > 0) { bl_cmd_t idle_cmd; idle_cmd.type = BL_CMD_TYPE_FLASH_ALL_COMPLETE; bl_cmd_handler(&idle_cmd); } if (fifo_is_empty(&m_flash_fifo) && m_go_to_app) { bl_info_entry_t* p_segment_entry = bootloader_info_entry_get(BL_INFO_TYPE_SEGMENT_APP); bootloader_util_app_start(p_segment_entry->segment.start); } }