David Kester / nRF51822

Dependents:   GonioTrainer

Fork of nRF51822 by Nordic Semiconductor

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers dfu_app_handler.c Source File

dfu_app_handler.c

00001 /* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
00002  *
00003  * The information contained herein is property of Nordic Semiconductor ASA.
00004  * Terms and conditions of usage are described in detail in NORDIC
00005  * SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
00006  *
00007  * Licensees are granted free, non-transferable use of the information. NO
00008  * WARRANTY of ANY KIND is provided. This heading must NOT be removed from
00009  * the file.
00010  *
00011  */
00012 
00013 #include <string.h>
00014 #include "dfu_app_handler.h "
00015 #include "bootloader_util.h "
00016 #include "nrf.h"
00017 #include "nrf_sdm.h"
00018 #include "ble_gatts.h"
00019 #include "app_error.h"
00020 #include "dfu_ble_svc.h "
00021 #include "device_manager.h "
00022 
00023 #define IRQ_ENABLED            0x01                                            /**< Field identifying if an interrupt is enabled. */
00024 #define MAX_NUMBER_INTERRUPTS  32                                              /**< Maximum number of interrupts available. */
00025 
00026 static void                    dfu_app_reset_prepare(void);                    /**< Forward declare of default reset handler. */
00027 static dfu_app_reset_prepare_t m_reset_prepare = dfu_app_reset_prepare;        /**< Callback function to application to prepare for system reset. Allows application to cleanup of service and memory prior to reset. */
00028 #if NEEDED
00029 static dfu_ble_peer_data_t     m_peer_data;                                    /**< Peer data to be used for data exchange when reseting into DFU mode. */
00030 static dm_handle_t             m_dm_handle;                                    /**< Device Manager handle with instance id's of current BLE connection. */
00031 static bool                    m_dm_handle_valid = false;                      /**< Variable indicating if the Device Manager handle is valid. */
00032 #endif /* NEEDED */
00033 
00034 
00035 /**@brief Default reset prepare handler if application hasn't registered a handler.
00036  */
00037 static void dfu_app_reset_prepare(void)
00038 {
00039     // Reset prepare should be handled by application.
00040     // This function can be extended to include default handling if application does not implement
00041     // own handler.
00042 }
00043 
00044 
00045 /**@brief Function for disabling all interrupts before jumping from bootloader to application.
00046  */
00047 static void interrupts_disable(void)
00048 {
00049     uint32_t interrupt_setting_mask;
00050     uint32_t irq = 0; // We start from first interrupt, i.e. interrupt 0.
00051 
00052     // Fetch the current interrupt settings.
00053     interrupt_setting_mask = NVIC->ISER[0];
00054 
00055     for (; irq < MAX_NUMBER_INTERRUPTS; irq++)
00056     {
00057         if (interrupt_setting_mask & (IRQ_ENABLED << irq))
00058         {
00059             // The interrupt was enabled, and hence disable it.
00060             NVIC_DisableIRQ((IRQn_Type )irq);
00061         }
00062     }
00063 }
00064 
00065 #if NEEDED
00066 /**@brief Function for providing peer information to DFU for re-establishing bonded connection in
00067  *        DFU mode.
00068  */
00069 static void dfu_app_set_peer_data(void)
00070 {
00071     uint32_t        err_code;
00072     dm_sec_keyset_t key_set;
00073 
00074 /** [DFU bond sharing] */
00075     err_code = dm_distributed_keys_get(&m_dm_handle, &key_set);
00076     APP_ERROR_CHECK(err_code);
00077 
00078     m_peer_data.addr    = key_set.keys_central.p_id_key->id_addr_info;
00079     m_peer_data.enc_key = *((ble_gap_enc_key_t *)(key_set.keys_central.enc_key.p_enc_key));
00080     m_peer_data.irk     = key_set.keys_central.p_id_key->id_info;
00081 
00082     err_code = dfu_ble_svc_set_peer_data(&m_peer_data);
00083     APP_ERROR_CHECK(err_code);
00084 /** [DFU bond sharing] */
00085 }
00086 #endif /* NEEDED */
00087 
00088 
00089 /**@brief Function for preparing the reset, disabling SoftDevice and jump to the bootloader.
00090  */
00091 void bootloader_start(void)
00092 {
00093     m_reset_prepare();
00094 
00095     uint32_t err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START);
00096     APP_ERROR_CHECK(err_code);
00097 
00098     err_code = sd_softdevice_disable();
00099     APP_ERROR_CHECK(err_code);
00100 
00101     err_code = sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR);
00102     APP_ERROR_CHECK(err_code);
00103 
00104     // Commenting out the following block because it brings in unwanted dependencies from bonding.
00105     // TODO: discuss this with Nordic.
00106     // if (m_dm_handle_valid)
00107     // {
00108     //     dfu_app_set_peer_data();
00109     // }
00110 
00111     NVIC_ClearPendingIRQ(SWI2_IRQn );
00112     interrupts_disable();
00113     bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR);
00114 }
00115 
00116 
00117 void dfu_app_on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
00118 {
00119     switch (p_evt->ble_dfu_evt_type)
00120     {
00121         case BLE_DFU_START:
00122             // Starting the bootloader - will cause reset.
00123             bootloader_start();
00124             break;
00125 
00126         case BLE_DFU_VALIDATE:
00127         case BLE_DFU_ACTIVATE_N_RESET:
00128         case BLE_DFU_SYS_RESET:
00129         case BLE_DFU_RECEIVE_INIT_DATA:
00130         case BLE_DFU_RECEIVE_APP_DATA:
00131         case BLE_DFU_PACKET_WRITE:
00132         case BLE_DFU_PKT_RCPT_NOTIF_ENABLED:
00133         case BLE_DFU_PKT_RCPT_NOTIF_DISABLED:
00134         case BLE_DFU_BYTES_RECEIVED_SEND:
00135         default:
00136             {
00137                 // Unsupported event received from DFU Service.
00138                 // Send back BLE_DFU_RESP_VAL_NOT_SUPPORTED message to peer.
00139                 uint32_t err_code = ble_dfu_response_send(p_dfu,
00140                                                           BLE_DFU_START_PROCEDURE,
00141                                                           BLE_DFU_RESP_VAL_NOT_SUPPORTED);
00142                 APP_ERROR_CHECK(err_code);
00143             }
00144             break;
00145     }
00146 }
00147 
00148 
00149 void dfu_app_reset_prepare_set(dfu_app_reset_prepare_t reset_prepare_func)
00150 {
00151     m_reset_prepare = reset_prepare_func;
00152 }
00153 
00154 #if NEEDED
00155 void dfu_app_set_dm_handle(dm_handle_t const * p_dm_handle)
00156 {
00157     m_dm_handle_valid = false;
00158 
00159     if (p_dm_handle != NULL)
00160     {
00161         m_dm_handle       = *p_dm_handle;
00162         m_dm_handle_valid = true;
00163     }
00164 }
00165 #endif /* NEEDED */