/**@brief Function for activating received Application image. * * @details This function will move the received application image fram swap (bank 1) to * application area (bank 0). * * @return NRF_SUCCESS on success. Error code otherwise. */ static uint32_t dfu_activate_app(void) { uint32_t err_code; // Erase BANK 0. err_code = pstorage_clear(&m_storage_handle_app, m_start_packet.app_image_size); APP_ERROR_CHECK(err_code); err_code = pstorage_store(&m_storage_handle_app, (uint8_t *)m_storage_handle_swap.block_id, m_start_packet.app_image_size, 0); if (err_code == NRF_SUCCESS) { dfu_update_status_t update_status; memset(&update_status, 0, sizeof(dfu_update_status_t )); update_status.status_code = DFU_UPDATE_APP_COMPLETE; update_status.app_crc = m_image_crc; update_status.app_size = m_start_packet.app_image_size; bootloader_dfu_update_process(update_status); } return err_code; }
uint32_t bootloader_dfu_ap_update_continue(void) { uint32_t err_code = NRF_SUCCESS; const bootloader_settings_t * p_bootloader_settings; bootloader_util_settings_get(&p_bootloader_settings); /* Ignore update attempts on invalid src_image_address */ if( (p_bootloader_settings->src_image_address == SRC_IMAGE_ADDRESS_EMPTY) || (p_bootloader_settings->src_image_address == SRC_IMAGE_ADDRESS_INVALID)) { return NRF_SUCCESS; } if( (p_bootloader_settings->ap_image.st.bank == NEW_IMAGE_BANK_0) || (p_bootloader_settings->ap_image.st.bank == NEW_IMAGE_BANK_1)) { /* If updating application only, we can start the copy right now*/ if ((p_bootloader_settings->sd_image.st.size == NEW_IMAGE_SIZE_EMPTY) && (p_bootloader_settings->bl_image.st.size == NEW_IMAGE_SIZE_EMPTY)) { err_code = dfu_ap_image_swap(); dfu_update_status_t update_status = {DFU_UPDATE_AP_SWAPPED, }; bootloader_dfu_update_process(update_status); wait_for_events(); } } return err_code; }
uint32_t dfu_init(void) { uint32_t err_code; bootloader_settings_t bootloader_settings; dfu_update_status_t update_status; m_storage_module_param.cb = pstorage_callback_handler; // Clear swap area. uint32_t * p_bank_start_address = (uint32_t *)DFU_BANK_1_REGION_START; m_init_packet_length = 0; m_image_crc = 0; err_code = pstorage_raw_register(&m_storage_module_param, &m_storage_handle_app); if (err_code != NRF_SUCCESS) { m_dfu_state = DFU_STATE_INIT_ERROR; return err_code; } m_storage_handle_app.block_id = CODE_REGION_1_START; m_storage_handle_swap = m_storage_handle_app; m_storage_handle_swap.block_id += DFU_IMAGE_MAX_SIZE_BANKED; bootloader_settings_get(&bootloader_settings); if ((bootloader_settings.bank_1 != BANK_ERASED) || (*p_bank_start_address != EMPTY_FLASH_MASK)) { err_code = pstorage_raw_clear(&m_storage_handle_swap, DFU_IMAGE_MAX_SIZE_BANKED); if (err_code != NRF_SUCCESS) { m_dfu_state = DFU_STATE_INIT_ERROR; return err_code; } update_status.status_code = DFU_BANK_1_ERASED; bootloader_dfu_update_process(update_status); } // Create the timer to monitor the activity by the peer doing the firmware update. err_code = app_timer_create(&m_dfu_timer_id, APP_TIMER_MODE_SINGLE_SHOT, dfu_timeout_handler); APP_ERROR_CHECK(err_code); // Start the DFU timer. err_code = app_timer_start(m_dfu_timer_id, DFU_TIMEOUT_INTERVAL, NULL); APP_ERROR_CHECK(err_code); // Size which indicates how large application DFU are able to handle. // The area is not erased but has been locked by the running application, and is considered // to be application data save space. m_new_app_max_size = DFU_IMAGE_MAX_SIZE_BANKED; m_app_data_received = 0; m_dfu_state = DFU_STATE_IDLE; return NRF_SUCCESS; }
void dfu_reset(void) { dfu_update_status_t update_status; update_status.status_code = DFU_RESET; bootloader_dfu_update_process(update_status); }
/**@brief Function for handling the DFU timeout. * * @param[in] p_context The timeout context. */ static void dfu_timeout_handler(void * p_context) { UNUSED_PARAMETER(p_context); dfu_update_status_t update_status; m_dfu_timed_out = true; update_status.status_code = DFU_TIMEOUT; bootloader_dfu_update_process(update_status); }
uint32_t bootloader_dfu_sd_update_finalize(void) { dfu_update_status_t update_status = {DFU_UPDATE_SD_SWAPPED, }; bootloader_dfu_update_process(update_status); wait_for_events(); return NRF_SUCCESS; }
uint32_t dfu_image_activate (void) { uint32_t err_code = NRF_SUCCESS; dfu_update_status_t update_status; switch (m_dfu_state) { case DFU_STATE_WAIT_4_ACTIVATE: // Stop the DFU Timer because the peer activity need not be monitored any longer. err_code = app_timer_stop(m_dfu_timer_id); APP_ERROR_CHECK(err_code); if (IS_UPDATING_SD()) //lint !e655 suppress Lint Warning 655: Bit-wise operations { update_status.sd_image_size = m_start_packet.sd_image_size; } else { update_status.sd_image_size = NEW_IMAGE_SIZE_EMPTY; } if (IS_UPDATING_BL()) //lint !e655 suppress Lint Warning 655: Bit-wise operations { update_status.bl_image_size = m_start_packet.bl_image_size; } else { update_status.bl_image_size = NEW_IMAGE_SIZE_EMPTY; } if (IS_UPDATING_APP()) //lint !e655 suppress Lint Warning 655: Bit-wise operations { update_status.ap_image_size = m_start_packet.app_image_size; } else { update_status.ap_image_size = NEW_IMAGE_SIZE_EMPTY; } update_status.status_code = DFU_UPDATE_NEW_IMAGES; update_status.bank_used = m_active_bank; update_status.src_image_address = dfu_storage_start_address_get(); bootloader_dfu_update_process(update_status); break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
uint32_t dfu_init_pkt_handle(dfu_update_packet_t * p_packet) { uint32_t err_code; uint32_t total_image_size = p_packet->params.init_packet.total_image_size; dfu_update_status_t update_status; switch (m_dfu_state) { case DFU_STATE_IDLE: case DFU_STATE_RDY: case DFU_STATE_RX_DATA_PKT: m_dfu_state = DFU_STATE_RX_INIT_PKT; /* fall-through */ case DFU_STATE_RX_INIT_PKT: // Valid peer activity detected. Hence restart the DFU timer. err_code = dfu_timer_restart(); if (err_code != NRF_SUCCESS) { return err_code; } // Reset the number of data received and the original m_storage_handle_app's start address. m_data_received = 0; m_storage_handle_app.block_id = CODE_REGION_1_START; // Prepare the flash buffer for the upcoming image. if (total_image_size > DFU_IMAGE_MAX_SIZE_BANKED) { update_status.status_code = DFU_UPDATE_AP_INVALIDATED; bootloader_dfu_update_process(update_status); err_code = pstorage_raw_clear(&m_storage_handle_app, DFU_IMAGE_MAX_SIZE_FULL); m_active_bank = NEW_IMAGE_BANK_0; } else if ((total_image_size < DFU_IMAGE_MAX_SIZE_BANKED) && (total_image_size != 0)) { err_code = pstorage_raw_clear(&m_storage_handle_swap, DFU_IMAGE_MAX_SIZE_BANKED); m_active_bank = NEW_IMAGE_BANK_1; } else { // do nothing } break; default: // Either the start packet was not received or dfu_init function was not called before. err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
/**@brief Function for activating received Bootloader image. * * @note This function will not move the bootloader image. * The bootloader settings will be marked as Bootloader update complete and the swapping of * current bootloader will occur after system reset. * * @return NRF_SUCCESS on success. */ static uint32_t dfu_activate_bl(void) { dfu_update_status_t update_status; update_status.status_code = DFU_UPDATE_BOOT_COMPLETE; update_status.app_crc = m_image_crc; update_status.sd_size = m_start_packet.sd_image_size; update_status.bl_size = m_start_packet.bl_image_size; update_status.app_size = m_start_packet.app_image_size; bootloader_dfu_update_process(update_status); return NRF_SUCCESS; }
/**@brief Function for activating received Application image. * * @details This function will move the received application image fram swap (bank 1) to * application area (bank 0). * * @return NRF_SUCCESS on success. Error code otherwise. */ static uint32_t dfu_activate_app(void) { uint32_t err_code = NRF_SUCCESS; dfu_update_status_t update_status; memset(&update_status, 0, sizeof(dfu_update_status_t )); update_status.status_code = DFU_UPDATE_APP_COMPLETE; update_status.app_crc = m_image_crc; update_status.app_size = m_start_packet.app_image_size; bootloader_dfu_update_process(update_status); return err_code; }
uint32_t dfu_image_size_set(uint32_t image_size) { uint32_t err_code; dfu_update_status_t update_status; err_code = NRF_ERROR_INVALID_STATE; if (image_size > DFU_IMAGE_MAX_SIZE_FULL) { return NRF_ERROR_DATA_SIZE; } if ((image_size & (sizeof(uint32_t) - 1)) != 0) { // Image_size is not a multiple of 4 (word size). return NRF_ERROR_NOT_SUPPORTED; } switch (m_dfu_state) { case DFU_STATE_IDLE: err_code = pstorage_raw_clear(&m_storage_handle_app, image_size); if (err_code != NRF_SUCCESS) { return err_code; } m_received_data = 0; m_image_size = image_size; update_status.status_code = DFU_BANK_0_ERASED; //SINGLEBANK PATCH err_code = 0; //m_dfu_state = DFU_STATE_RDY; //END PATCH bootloader_dfu_update_process(update_status); break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
uint32_t dfu_image_activate() { uint32_t err_code; dfu_update_status_t update_status; switch (m_dfu_state) { case DFU_STATE_WAIT_4_ACTIVATE: update_status.status_code = DFU_UPDATE_COMPLETE; update_status.app_crc = m_image_crc; update_status.app_size = m_image_size; bootloader_dfu_update_process(update_status); err_code = NRF_SUCCESS; break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
uint32_t dfu_image_activate() { uint32_t err_code; switch (m_dfu_state) { case DFU_STATE_WAIT_4_ACTIVATE: // Stop the DFU Timer because the peer activity need not be monitored any longer. err_code = app_timer_stop(m_dfu_timer_id); APP_ERROR_CHECK(err_code); // Erase BANK 0. err_code = pstorage_raw_clear(&m_storage_handle_app, m_image_size); APP_ERROR_CHECK(err_code); err_code = pstorage_raw_store(&m_storage_handle_app, (uint8_t*) m_storage_handle_swap.block_id, m_image_size, 0); if (err_code == NRF_SUCCESS) { dfu_update_status_t update_status; update_status.status_code = DFU_UPDATE_COMPLETE; update_status.app_crc = m_image_crc; update_status.app_size = m_image_size; bootloader_dfu_update_process(update_status); } break; default: err_code = NRF_ERROR_INVALID_STATE; break; } return err_code; }
/**@brief Function for handling behaviour when clear operation has completed. */ static void dfu_cleared_func_app(void) { dfu_update_status_t update_status = {DFU_BANK_0_ERASED, }; bootloader_dfu_update_process(update_status); }
/**@brief Function for the Application's S110 SoftDevice event handler. * * @param[in] p_ble_evt S110 SoftDevice event. */ static void on_ble_evt(ble_evt_t * p_ble_evt) { uint32_t err_code; ble_gatts_rw_authorize_reply_params_t auth_reply; switch (p_ble_evt->header.evt_id) { case BLE_GAP_EVT_CONNECTED: nrf_gpio_pin_clear(CONNECTED_LED_PIN_NO); PUTS("Connected"); m_conn_handle = p_ble_evt->evt.gap_evt.conn_handle; m_is_advertising = false; break; case BLE_GAP_EVT_DISCONNECTED: { uint8_t sys_attr[128]; uint16_t sys_attr_len = sizeof(sys_attr); PUTS("Disconnected"); nrf_gpio_pin_set(CONNECTED_LED_PIN_NO); m_direct_adv_cnt = APP_DIRECTED_ADV_TIMEOUT; err_code = sd_ble_gatts_sys_attr_get(m_conn_handle, sys_attr, &sys_attr_len, BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS); if ((err_code != NRF_SUCCESS) && (err_code != NRF_ERROR_NOT_FOUND)) { APP_ERROR_CHECK(err_code); } } if (!m_tear_down_in_progress) { // The Disconnected event is because of an external event. (Link loss or // disconnect triggered by the DFU Controller before the firmware update was // complete). // Restart advertising so that the DFU Controller can reconnect if possible. advertising_start(); } m_conn_handle = BLE_CONN_HANDLE_INVALID; break; case BLE_GAP_EVT_SEC_PARAMS_REQUEST: { ble_gap_sec_keyset_t keys; ble_gap_enc_key_t enc_key; ble_gap_id_key_t id_key; id_key.id_addr_info = m_ble_peer_data.addr; id_key.id_info = m_ble_peer_data.irk; enc_key = m_ble_peer_data.enc_key; keys.keys_central.p_id_key = &id_key; keys.keys_central.p_enc_key = &enc_key; err_code = sd_ble_gap_sec_params_reply(m_conn_handle, BLE_GAP_SEC_STATUS_PAIRING_NOT_SUPP, &m_sec_params, &keys); APP_ERROR_CHECK(err_code); } break; case BLE_GATTS_EVT_TIMEOUT: if (p_ble_evt->evt.gatts_evt.params.timeout.src == BLE_GATT_TIMEOUT_SRC_PROTOCOL) { err_code = sd_ble_gap_disconnect(m_conn_handle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION); APP_ERROR_CHECK(err_code); } break; case BLE_GAP_EVT_TIMEOUT: if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISING) { m_is_advertising = false; m_direct_adv_cnt--; if (m_direct_adv_cnt == 0) { dfu_update_status_t update_status = {.status_code = DFU_TIMEOUT}; bootloader_dfu_update_process(update_status); } else {