/**@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);
}
Example #2
0
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();
}
Example #3
0
/*!
    @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();
}
Example #4
0
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;
}
Example #5
0
/**@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);
}
Example #8
0
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;

    }
}