/**@brief Function for preparing the reset, disabling SoftDevice, and jumping to the bootloader. * * @param[in] conn_handle Connection handle for peer requesting to enter DFU mode. */ static void bootloader_start(uint16_t conn_handle) { uint32_t err_code; uint16_t sys_serv_attr_len = sizeof(m_peer_data.sys_serv_attr); err_code = sd_ble_gatts_sys_attr_get(conn_handle, m_peer_data.sys_serv_attr, &sys_serv_attr_len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); if (err_code != NRF_SUCCESS) { // Any error at this stage means the system service attributes could not be fetched. // This means the service changed indication cannot be sent in DFU mode, but connection // is still possible to establish. } m_reset_prepare(); err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START); APP_ERROR_CHECK(err_code); err_code = sd_softdevice_disable(); APP_ERROR_CHECK(err_code); err_code = sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR); APP_ERROR_CHECK(err_code); dfu_app_peer_data_set(conn_handle); NVIC_ClearPendingIRQ(SWI2_IRQn); interrupts_disable(); bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR); }
void sd_maskBootloader(uint8_t mask) { uint32_t boot_set = 0; sd_power_gpregret_get(&boot_set); boot_set = boot_set |(uint32_t)mask; sd_power_gpregret_set(boot_set); sd_nvic_SystemReset(); }
/*! @brief Handler for general errors above the SoftDevice layer. Typically we can' recover from this so we do a reset. */ void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name) { ASSERT_STATUS_RET_VOID( error_code ); // Set info that reboot occurred due to soft error sd_power_gpregret_clr(0xFFFFFFFF); sd_power_gpregret_set(0xFADE0002/*GP_REG_RET_APP_ERROR_CAUSE_REBOOT*/); NVIC_SystemReset(); }
uint32_t ble_dfu_buttonless_bootloader_start_finalize(void) { uint32_t err_code; NRF_LOG_DEBUG("In ble_dfu_buttonless_bootloader_start_finalize\r\n"); err_code = sd_power_gpregret_clr(0, 0xffffffff); VERIFY_SUCCESS(err_code); err_code = sd_power_gpregret_set(0, BOOTLOADER_DFU_START); VERIFY_SUCCESS(err_code); // Indicate that the Secure DFU bootloader will be entered m_dfu.evt_handler(BLE_DFU_EVT_BOOTLOADER_ENTER); // Signal that DFU mode is to be enter to the power management module nrf_pwr_mgmt_shutdown(NRF_PWR_MGMT_SHUTDOWN_GOTO_DFU); return NRF_SUCCESS; }
/**@brief Function for preparing the reset, disabling SoftDevice and jump to the bootloader. */ static void bootloader_start(void) { m_reset_prepare(); uint32_t err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START); APP_ERROR_CHECK(err_code); err_code = sd_softdevice_disable(); APP_ERROR_CHECK(err_code); err_code = sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR); APP_ERROR_CHECK(err_code); if (m_dm_handle_valid) { dfu_app_set_peer_data(); } NVIC_ClearPendingIRQ(SWI2_IRQn); interrupts_disable(); bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR); }
uint32_t dfu_jump_to_bootloader(void) { if (NRF_UICR->BOOTLOADERADDR != 0xFFFFFFFF) { interrupts_disable(); #ifdef SOFTDEVICE_PRESENT sd_power_reset_reason_clr(0x0F000F); sd_power_gpregret_set(RBC_MESH_GPREGRET_CODE_FORCED_REBOOT); sd_nvic_SystemReset(); #else NRF_POWER->RESETREAS = 0x0F000F; /* erase reset-reason to avoid wrongful state-readout on reboot */ NRF_POWER->GPREGRET = RBC_MESH_GPREGRET_CODE_FORCED_REBOOT; NVIC_SystemReset(); //TODO: Wait for serial commands and flash? #endif return NRF_SUCCESS; /* unreachable */ } else { /* the UICR->BOOTLOADERADDR isn't set, and we have no way to find the bootloader-address. */ return NRF_ERROR_FORBIDDEN; } }
/**@brief Function for preparing the reset, disabling SoftDevice and jump to the bootloader. */ void bootloader_start(void) { m_reset_prepare(); uint32_t err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START); APP_ERROR_CHECK(err_code); err_code = sd_softdevice_disable(); APP_ERROR_CHECK(err_code); err_code = sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR); APP_ERROR_CHECK(err_code); // Commenting out the following block because it brings in unwanted dependencies from bonding. // TODO: discuss this with Nordic. // if (m_dm_handle_valid) // { // dfu_app_set_peer_data(); // } NVIC_ClearPendingIRQ(SWI2_IRQn); interrupts_disable(); bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR); }
void sd_triggerBootloader(void) { uint32_t boot_set = 0xFF; sd_power_gpregret_set(boot_set); sd_nvic_SystemReset(); }
static void flash_bank_entry(void) { bl_info_bank_t* p_bank_entry = mp_bank_entry; /* make local copy to avoid race conditions */ if (p_bank_entry == NULL) { return; } bl_info_entry_t bank_entry_replacement; memcpy(&bank_entry_replacement, p_bank_entry, sizeof(bl_info_bank_t)); switch (p_bank_entry->state) { case BL_INFO_BANK_STATE_IDLE: { m_waiting_for_idle = true; bank_entry_replacement.bank.state = BL_INFO_BANK_STATE_FLASH_FW; bootloader_info_entry_overwrite((bl_info_type_t) (BL_INFO_TYPE_BANK_BASE + m_dfu_type), &bank_entry_replacement); /* Wait for this to take effect before moving on, as the potential mbr commands in the flash_fw state may trigger sudden reboots. */ return; } case BL_INFO_BANK_STATE_FLASH_FW: switch (m_dfu_type) { case DFU_TYPE_BOOTLOADER: /* Check to see if the bank transfer has been executed */ if (memcmp(p_bank_entry->p_bank_addr, (uint32_t*) bootloader_info_entry_get(BL_INFO_TYPE_SEGMENT_BL)->segment.start, p_bank_entry->length) != 0) { /* move the bank with MBR. BOOTLOADERADDR() must have been set. */ sd_mbr_command_t sd_mbr_cmd; sd_mbr_cmd.command = SD_MBR_COMMAND_COPY_BL; sd_mbr_cmd.params.copy_bl.bl_src = p_bank_entry->p_bank_addr; sd_mbr_cmd.params.copy_bl.bl_len = p_bank_entry->length / sizeof(uint32_t); APP_ERROR_CHECK(sd_mbr_command(&sd_mbr_cmd)); return; /* Can't be reached, only here for readability. */ } else { bank_entry_replacement.bank.state = BL_INFO_BANK_STATE_FLASH_META; bootloader_info_entry_overwrite(BL_INFO_TYPE_BANK_BL, &bank_entry_replacement); } break; case DFU_TYPE_SD: /* Check to see if the bank transfer has been executed */ if (memcmp(p_bank_entry->p_bank_addr, (uint32_t*) bootloader_info_entry_get(BL_INFO_TYPE_SEGMENT_SD)->segment.start, p_bank_entry->length) != 0) { /* move the bank with MBR. */ sd_mbr_command_t sd_mbr_cmd; sd_mbr_cmd.command = SD_MBR_COMMAND_COPY_SD; sd_mbr_cmd.params.copy_sd.src = p_bank_entry->p_bank_addr; sd_mbr_cmd.params.copy_sd.len = p_bank_entry->length / sizeof(uint32_t); sd_mbr_cmd.params.copy_sd.dst = (uint32_t*) 0x1000; APP_ERROR_CHECK(sd_mbr_command(&sd_mbr_cmd)); return; /* Can't be reached, only here for readability. */ } else { bank_entry_replacement.bank.state = BL_INFO_BANK_STATE_FLASH_META; bootloader_info_entry_overwrite((bl_info_type_t) (BL_INFO_TYPE_BANK_BASE + m_dfu_type), &bank_entry_replacement); } break; case DFU_TYPE_APP: /* This nukes the call stack and any flash-callbacks on the app side. If we're in the application, we have to jump to bootloader. */ if (bootloader_is_in_application()) { /* All paths leading to this call warns about this reset. We'll come back to finalize the transfer after the reset. */ __LOG("IN APP MODE. RESET!\n"); #if 1 //def SOFTDEVICE_PRESENT sd_power_reset_reason_clr(0x0F000F); #if NORDIC_SDK_VERSION >= 11 sd_power_gpregret_set(0, RBC_MESH_GPREGRET_CODE_GO_TO_APP); #else sd_power_gpregret_set(RBC_MESH_GPREGRET_CODE_GO_TO_APP); #endif sd_nvic_SystemReset(); #else NRF_POWER->RESETREAS = 0x0F000F; /* erase reset-reason to avoid wrongful state-readout on reboot */ NRF_POWER->GPREGRET = RBC_MESH_GPREGRET_CODE_GO_TO_APP; NVIC_SystemReset(); #endif } else { /* Erase, Flash the FW, flash FW flag, flash the signature, erase the bank entry. */ bl_info_entry_t* p_app_entry = bootloader_info_entry_get(BL_INFO_TYPE_SEGMENT_APP); APP_ERROR_CHECK_BOOL(p_app_entry != NULL); APP_ERROR_CHECK_BOOL(IS_PAGE_ALIGNED(p_app_entry->segment.start)); /* Erase existing FW */ bl_evt_t flash_evt; flash_evt.type = BL_EVT_TYPE_FLASH_ERASE; flash_evt.params.flash.erase.start_addr = p_app_entry->segment.start; flash_evt.params.flash.erase.length = ((p_bank_entry->length + (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1)); /* Pad the rest of the page */ if (bootloader_evt_send(&flash_evt) != NRF_SUCCESS) { m_waiting_for_idle = true; return; } /* Flash bank */ flash_evt.type = BL_EVT_TYPE_FLASH_WRITE; flash_evt.params.flash.write.p_data = (uint8_t*) p_bank_entry->p_bank_addr; flash_evt.params.flash.write.length = p_bank_entry->length; flash_evt.params.flash.write.start_addr = p_app_entry->segment.start; if (bootloader_evt_send(&flash_evt) != NRF_SUCCESS) { m_waiting_for_idle = true; return; } /* Update state */ bank_entry_replacement.bank.state = BL_INFO_BANK_STATE_FLASH_META; bootloader_info_entry_overwrite((bl_info_type_t) (BL_INFO_TYPE_BANK_BASE + m_dfu_type), &bank_entry_replacement); } break; default: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); break; } /* deliberate fallthrough */ case BL_INFO_BANK_STATE_FLASH_META: { bl_info_entry_t fwid_entry; bl_info_type_t signature_type; bl_info_entry_t flags_entry; bl_info_entry_t* p_old_fwid_entry = bootloader_info_entry_get(BL_INFO_TYPE_VERSION); bl_info_entry_t* p_old_flags_entry = bootloader_info_entry_get(BL_INFO_TYPE_FLAGS); APP_ERROR_CHECK_BOOL(p_old_fwid_entry); APP_ERROR_CHECK_BOOL(p_bank_entry); memcpy(&fwid_entry, p_old_fwid_entry, sizeof(bl_info_version_t)); memcpy(&flags_entry, p_old_flags_entry, sizeof(bl_info_flags_t)); switch (m_dfu_type) { case DFU_TYPE_SD: fwid_entry.version.sd = p_bank_entry->fwid.sd; signature_type = BL_INFO_TYPE_SIGNATURE_SD; flags_entry.flags.sd_intact = true; break; case DFU_TYPE_BOOTLOADER: fwid_entry.version.bootloader.id = p_bank_entry->fwid.bootloader.id; fwid_entry.version.bootloader.ver = p_bank_entry->fwid.bootloader.ver; signature_type = BL_INFO_TYPE_SIGNATURE_BL; flags_entry.flags.bl_intact = true; break; case DFU_TYPE_APP: fwid_entry.version.app.company_id = p_bank_entry->fwid.app.company_id; fwid_entry.version.app.app_id = p_bank_entry->fwid.app.app_id; fwid_entry.version.app.app_version = p_bank_entry->fwid.app.app_version; signature_type = BL_INFO_TYPE_SIGNATURE_APP; flags_entry.flags.app_intact = true; break; default: APP_ERROR_CHECK(NRF_ERROR_INVALID_DATA); return; } if (!bootloader_info_entry_put(BL_INFO_TYPE_VERSION, &fwid_entry, BL_INFO_LEN_FWID)) { m_waiting_for_idle = true; return; } if (p_bank_entry->has_signature) { if (!bootloader_info_entry_put(signature_type, (bl_info_entry_t*) p_bank_entry->signature, BL_INFO_LEN_SIGNATURE)) { m_waiting_for_idle = true; return; } } if (!bootloader_info_entry_put(BL_INFO_TYPE_FLAGS, &flags_entry, BL_INFO_LEN_FLAGS)) { m_waiting_for_idle = true; return; } /* Update state */ __LOG("Bank: Set state to FLASHED\n"); bank_entry_replacement.bank.state = BL_INFO_BANK_STATE_FLASHED; bootloader_info_entry_overwrite((bl_info_type_t) (BL_INFO_TYPE_BANK_BASE + m_dfu_type), &bank_entry_replacement); } /* deliberate fallthrough */ case BL_INFO_BANK_STATE_FLASHED: /* We may invalidate the bank entry in the device page now, it's all redundant. */ __LOG("Bank: Invalidate.\n"); if (bootloader_info_entry_invalidate((bl_info_type_t) (BL_INFO_TYPE_BANK_BASE + m_dfu_type)) == NRF_SUCCESS) { __LOG("Bank invalidated.\n"); mp_bank_entry = NULL; /* reset the static bank pointer, as we no longer need it. */ } else { m_waiting_for_idle = true; } break; } }