Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Fork of nRF51822 by
nordic-sdk/components/libraries/bootloader_dfu/experimental/dfu_app_handler.c@386:3253b512fb24, 2015-07-21 (annotated)
- Committer:
- rgrover1
- Date:
- Tue Jul 21 13:23:43 2015 +0100
- Revision:
- 386:3253b512fb24
- Parent:
- source/nordic-sdk/components/libraries/bootloader_dfu/experimental/dfu_app_handler.c@381:c997e9717fb7
Synchronized with git rev 928a5e63
Author: Rohit Grover
Release 0.4.1
=============
This is a minor release.
Enhancements
~~~~~~~~~~~~
* Hide duplicate symbol definitions in ble_types.h. These have already been
brought into ble/blecommon.h.
* Replace DiscoveredCharacteristic::setupOnDataRead() with
GattClient::onDataRead().
* Implement new API GattServer::areUpdatesEnabled() to determine notification
status for a characteristic.
Bugfixes
~~~~~~~~
* fix for #20: GattServer::addService() incorrectly initialized value
attribute-handles. These were getting confused with characteristicIndex.
Event handlers also return attribute handles correctly now; they were also
previously returning characteristic indices.
Who changed what in which revision?
| User | Revision | Line number | New contents of line |
|---|---|---|---|
| rgrover1 | 371:8f7d2137727a | 1 | /* |
| rgrover1 | 371:8f7d2137727a | 2 | * Copyright (c) Nordic Semiconductor ASA |
| rgrover1 | 371:8f7d2137727a | 3 | * All rights reserved. |
| rgrover1 | 371:8f7d2137727a | 4 | * |
| rgrover1 | 371:8f7d2137727a | 5 | * Redistribution and use in source and binary forms, with or without modification, |
| rgrover1 | 371:8f7d2137727a | 6 | * are permitted provided that the following conditions are met: |
| rgrover1 | 371:8f7d2137727a | 7 | * |
| rgrover1 | 371:8f7d2137727a | 8 | * 1. Redistributions of source code must retain the above copyright notice, this |
| rgrover1 | 371:8f7d2137727a | 9 | * list of conditions and the following disclaimer. |
| rgrover1 | 371:8f7d2137727a | 10 | * |
| rgrover1 | 371:8f7d2137727a | 11 | * 2. Redistributions in binary form must reproduce the above copyright notice, this |
| rgrover1 | 371:8f7d2137727a | 12 | * list of conditions and the following disclaimer in the documentation and/or |
| rgrover1 | 371:8f7d2137727a | 13 | * other materials provided with the distribution. |
| rgrover1 | 185:28d8c818d84f | 14 | * |
| rgrover1 | 371:8f7d2137727a | 15 | * 3. Neither the name of Nordic Semiconductor ASA nor the names of other |
| rgrover1 | 371:8f7d2137727a | 16 | * contributors to this software may be used to endorse or promote products |
| rgrover1 | 371:8f7d2137727a | 17 | * derived from this software without specific prior written permission. |
| rgrover1 | 371:8f7d2137727a | 18 | * |
| rgrover1 | 185:28d8c818d84f | 19 | * |
| rgrover1 | 371:8f7d2137727a | 20 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND |
| rgrover1 | 371:8f7d2137727a | 21 | * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| rgrover1 | 371:8f7d2137727a | 22 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| rgrover1 | 371:8f7d2137727a | 23 | * DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR |
| rgrover1 | 371:8f7d2137727a | 24 | * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| rgrover1 | 371:8f7d2137727a | 25 | * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| rgrover1 | 371:8f7d2137727a | 26 | * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| rgrover1 | 371:8f7d2137727a | 27 | * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| rgrover1 | 371:8f7d2137727a | 28 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| rgrover1 | 371:8f7d2137727a | 29 | * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| rgrover1 | 185:28d8c818d84f | 30 | * |
| rgrover1 | 185:28d8c818d84f | 31 | */ |
| rgrover1 | 185:28d8c818d84f | 32 | |
| rgrover1 | 185:28d8c818d84f | 33 | #include <string.h> |
| rgrover1 | 185:28d8c818d84f | 34 | #include "dfu_app_handler.h" |
| rgrover1 | 185:28d8c818d84f | 35 | #include "bootloader_util.h" |
| rgrover1 | 185:28d8c818d84f | 36 | #include "nrf.h" |
| rgrover1 | 185:28d8c818d84f | 37 | #include "nrf_sdm.h" |
| rgrover1 | 185:28d8c818d84f | 38 | #include "ble_gatts.h" |
| rgrover1 | 185:28d8c818d84f | 39 | #include "app_error.h" |
| rgrover1 | 185:28d8c818d84f | 40 | #include "dfu_ble_svc.h" |
| rgrover1 | 185:28d8c818d84f | 41 | #include "device_manager.h" |
| rgrover1 | 185:28d8c818d84f | 42 | |
| rgrover1 | 185:28d8c818d84f | 43 | #define IRQ_ENABLED 0x01 /**< Field identifying if an interrupt is enabled. */ |
| rgrover1 | 185:28d8c818d84f | 44 | #define MAX_NUMBER_INTERRUPTS 32 /**< Maximum number of interrupts available. */ |
| rgrover1 | 185:28d8c818d84f | 45 | |
| rgrover1 | 185:28d8c818d84f | 46 | static void dfu_app_reset_prepare(void); /**< Forward declare of default reset handler. */ |
| rgrover1 | 185:28d8c818d84f | 47 | 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. */ |
| rgrover1 | 185:28d8c818d84f | 48 | #if NEEDED |
| rgrover1 | 185:28d8c818d84f | 49 | static dfu_ble_peer_data_t m_peer_data; /**< Peer data to be used for data exchange when reseting into DFU mode. */ |
| rgrover1 | 185:28d8c818d84f | 50 | static dm_handle_t m_dm_handle; /**< Device Manager handle with instance id's of current BLE connection. */ |
| rgrover1 | 185:28d8c818d84f | 51 | static bool m_dm_handle_valid = false; /**< Variable indicating if the Device Manager handle is valid. */ |
| rgrover1 | 185:28d8c818d84f | 52 | #endif /* NEEDED */ |
| rgrover1 | 185:28d8c818d84f | 53 | |
| rgrover1 | 185:28d8c818d84f | 54 | |
| rgrover1 | 185:28d8c818d84f | 55 | /**@brief Default reset prepare handler if application hasn't registered a handler. |
| rgrover1 | 185:28d8c818d84f | 56 | */ |
| rgrover1 | 185:28d8c818d84f | 57 | static void dfu_app_reset_prepare(void) |
| rgrover1 | 185:28d8c818d84f | 58 | { |
| rgrover1 | 185:28d8c818d84f | 59 | // Reset prepare should be handled by application. |
| rgrover1 | 185:28d8c818d84f | 60 | // This function can be extended to include default handling if application does not implement |
| rgrover1 | 185:28d8c818d84f | 61 | // own handler. |
| rgrover1 | 185:28d8c818d84f | 62 | } |
| rgrover1 | 185:28d8c818d84f | 63 | |
| rgrover1 | 185:28d8c818d84f | 64 | |
| rgrover1 | 185:28d8c818d84f | 65 | /**@brief Function for disabling all interrupts before jumping from bootloader to application. |
| rgrover1 | 185:28d8c818d84f | 66 | */ |
| rgrover1 | 185:28d8c818d84f | 67 | static void interrupts_disable(void) |
| rgrover1 | 185:28d8c818d84f | 68 | { |
| rgrover1 | 185:28d8c818d84f | 69 | uint32_t interrupt_setting_mask; |
| rgrover1 | 185:28d8c818d84f | 70 | uint32_t irq = 0; // We start from first interrupt, i.e. interrupt 0. |
| rgrover1 | 185:28d8c818d84f | 71 | |
| rgrover1 | 185:28d8c818d84f | 72 | // Fetch the current interrupt settings. |
| rgrover1 | 185:28d8c818d84f | 73 | interrupt_setting_mask = NVIC->ISER[0]; |
| rgrover1 | 185:28d8c818d84f | 74 | |
| rgrover1 | 185:28d8c818d84f | 75 | for (; irq < MAX_NUMBER_INTERRUPTS; irq++) |
| rgrover1 | 185:28d8c818d84f | 76 | { |
| rgrover1 | 185:28d8c818d84f | 77 | if (interrupt_setting_mask & (IRQ_ENABLED << irq)) |
| rgrover1 | 185:28d8c818d84f | 78 | { |
| rgrover1 | 185:28d8c818d84f | 79 | // The interrupt was enabled, and hence disable it. |
| rgrover1 | 185:28d8c818d84f | 80 | NVIC_DisableIRQ((IRQn_Type)irq); |
| rgrover1 | 185:28d8c818d84f | 81 | } |
| rgrover1 | 185:28d8c818d84f | 82 | } |
| rgrover1 | 185:28d8c818d84f | 83 | } |
| rgrover1 | 185:28d8c818d84f | 84 | |
| rgrover1 | 185:28d8c818d84f | 85 | #if NEEDED |
| rgrover1 | 185:28d8c818d84f | 86 | /**@brief Function for providing peer information to DFU for re-establishing bonded connection in |
| rgrover1 | 185:28d8c818d84f | 87 | * DFU mode. |
| rgrover1 | 185:28d8c818d84f | 88 | */ |
| rgrover1 | 185:28d8c818d84f | 89 | static void dfu_app_set_peer_data(void) |
| rgrover1 | 185:28d8c818d84f | 90 | { |
| rgrover1 | 185:28d8c818d84f | 91 | uint32_t err_code; |
| rgrover1 | 185:28d8c818d84f | 92 | dm_sec_keyset_t key_set; |
| rgrover1 | 185:28d8c818d84f | 93 | |
| rgrover1 | 185:28d8c818d84f | 94 | /** [DFU bond sharing] */ |
| rgrover1 | 185:28d8c818d84f | 95 | err_code = dm_distributed_keys_get(&m_dm_handle, &key_set); |
| rgrover1 | 185:28d8c818d84f | 96 | APP_ERROR_CHECK(err_code); |
| rgrover1 | 185:28d8c818d84f | 97 | |
| rgrover1 | 185:28d8c818d84f | 98 | m_peer_data.addr = key_set.keys_central.p_id_key->id_addr_info; |
| rgrover1 | 185:28d8c818d84f | 99 | m_peer_data.enc_key = *((ble_gap_enc_key_t *)(key_set.keys_central.enc_key.p_enc_key)); |
| rgrover1 | 185:28d8c818d84f | 100 | m_peer_data.irk = key_set.keys_central.p_id_key->id_info; |
| rgrover1 | 185:28d8c818d84f | 101 | |
| rgrover1 | 185:28d8c818d84f | 102 | err_code = dfu_ble_svc_set_peer_data(&m_peer_data); |
| rgrover1 | 185:28d8c818d84f | 103 | APP_ERROR_CHECK(err_code); |
| rgrover1 | 185:28d8c818d84f | 104 | /** [DFU bond sharing] */ |
| rgrover1 | 185:28d8c818d84f | 105 | } |
| rgrover1 | 185:28d8c818d84f | 106 | #endif /* NEEDED */ |
| rgrover1 | 185:28d8c818d84f | 107 | |
| rgrover1 | 185:28d8c818d84f | 108 | |
| rgrover1 | 185:28d8c818d84f | 109 | /**@brief Function for preparing the reset, disabling SoftDevice and jump to the bootloader. |
| rgrover1 | 185:28d8c818d84f | 110 | */ |
| rgrover1 | 185:28d8c818d84f | 111 | void bootloader_start(void) |
| rgrover1 | 185:28d8c818d84f | 112 | { |
| rgrover1 | 185:28d8c818d84f | 113 | m_reset_prepare(); |
| rgrover1 | 185:28d8c818d84f | 114 | |
| rgrover1 | 185:28d8c818d84f | 115 | uint32_t err_code = sd_power_gpregret_set(BOOTLOADER_DFU_START); |
| rgrover1 | 185:28d8c818d84f | 116 | APP_ERROR_CHECK(err_code); |
| rgrover1 | 185:28d8c818d84f | 117 | |
| rgrover1 | 185:28d8c818d84f | 118 | err_code = sd_softdevice_disable(); |
| rgrover1 | 185:28d8c818d84f | 119 | APP_ERROR_CHECK(err_code); |
| rgrover1 | 185:28d8c818d84f | 120 | |
| rgrover1 | 185:28d8c818d84f | 121 | err_code = sd_softdevice_vector_table_base_set(NRF_UICR->BOOTLOADERADDR); |
| rgrover1 | 185:28d8c818d84f | 122 | APP_ERROR_CHECK(err_code); |
| rgrover1 | 185:28d8c818d84f | 123 | |
| rgrover1 | 185:28d8c818d84f | 124 | // Commenting out the following block because it brings in unwanted dependencies from bonding. |
| rgrover1 | 185:28d8c818d84f | 125 | // TODO: discuss this with Nordic. |
| rgrover1 | 185:28d8c818d84f | 126 | // if (m_dm_handle_valid) |
| rgrover1 | 185:28d8c818d84f | 127 | // { |
| rgrover1 | 185:28d8c818d84f | 128 | // dfu_app_set_peer_data(); |
| rgrover1 | 185:28d8c818d84f | 129 | // } |
| rgrover1 | 185:28d8c818d84f | 130 | |
| rgrover1 | 185:28d8c818d84f | 131 | NVIC_ClearPendingIRQ(SWI2_IRQn); |
| rgrover1 | 185:28d8c818d84f | 132 | interrupts_disable(); |
| rgrover1 | 185:28d8c818d84f | 133 | bootloader_util_app_start(NRF_UICR->BOOTLOADERADDR); |
| rgrover1 | 185:28d8c818d84f | 134 | } |
| rgrover1 | 185:28d8c818d84f | 135 | |
| rgrover1 | 185:28d8c818d84f | 136 | |
| rgrover1 | 185:28d8c818d84f | 137 | void dfu_app_on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt) |
| rgrover1 | 185:28d8c818d84f | 138 | { |
| rgrover1 | 185:28d8c818d84f | 139 | switch (p_evt->ble_dfu_evt_type) |
| rgrover1 | 185:28d8c818d84f | 140 | { |
| rgrover1 | 185:28d8c818d84f | 141 | case BLE_DFU_START: |
| rgrover1 | 185:28d8c818d84f | 142 | // Starting the bootloader - will cause reset. |
| rgrover1 | 185:28d8c818d84f | 143 | bootloader_start(); |
| rgrover1 | 185:28d8c818d84f | 144 | break; |
| rgrover1 | 185:28d8c818d84f | 145 | |
| rgrover1 | 185:28d8c818d84f | 146 | case BLE_DFU_VALIDATE: |
| rgrover1 | 185:28d8c818d84f | 147 | case BLE_DFU_ACTIVATE_N_RESET: |
| rgrover1 | 185:28d8c818d84f | 148 | case BLE_DFU_SYS_RESET: |
| rgrover1 | 185:28d8c818d84f | 149 | case BLE_DFU_RECEIVE_INIT_DATA: |
| rgrover1 | 185:28d8c818d84f | 150 | case BLE_DFU_RECEIVE_APP_DATA: |
| rgrover1 | 185:28d8c818d84f | 151 | case BLE_DFU_PACKET_WRITE: |
| rgrover1 | 185:28d8c818d84f | 152 | case BLE_DFU_PKT_RCPT_NOTIF_ENABLED: |
| rgrover1 | 185:28d8c818d84f | 153 | case BLE_DFU_PKT_RCPT_NOTIF_DISABLED: |
| rgrover1 | 185:28d8c818d84f | 154 | case BLE_DFU_BYTES_RECEIVED_SEND: |
| rgrover1 | 185:28d8c818d84f | 155 | default: |
| rgrover1 | 185:28d8c818d84f | 156 | { |
| rgrover1 | 185:28d8c818d84f | 157 | // Unsupported event received from DFU Service. |
| rgrover1 | 185:28d8c818d84f | 158 | // Send back BLE_DFU_RESP_VAL_NOT_SUPPORTED message to peer. |
| rgrover1 | 185:28d8c818d84f | 159 | uint32_t err_code = ble_dfu_response_send(p_dfu, |
| rgrover1 | 185:28d8c818d84f | 160 | BLE_DFU_START_PROCEDURE, |
| rgrover1 | 185:28d8c818d84f | 161 | BLE_DFU_RESP_VAL_NOT_SUPPORTED); |
| rgrover1 | 185:28d8c818d84f | 162 | APP_ERROR_CHECK(err_code); |
| rgrover1 | 185:28d8c818d84f | 163 | } |
| rgrover1 | 185:28d8c818d84f | 164 | break; |
| rgrover1 | 185:28d8c818d84f | 165 | } |
| rgrover1 | 185:28d8c818d84f | 166 | } |
| rgrover1 | 185:28d8c818d84f | 167 | |
| rgrover1 | 185:28d8c818d84f | 168 | |
| rgrover1 | 185:28d8c818d84f | 169 | void dfu_app_reset_prepare_set(dfu_app_reset_prepare_t reset_prepare_func) |
| rgrover1 | 185:28d8c818d84f | 170 | { |
| rgrover1 | 185:28d8c818d84f | 171 | m_reset_prepare = reset_prepare_func; |
| rgrover1 | 185:28d8c818d84f | 172 | } |
| rgrover1 | 185:28d8c818d84f | 173 | |
| rgrover1 | 185:28d8c818d84f | 174 | #if NEEDED |
| rgrover1 | 185:28d8c818d84f | 175 | void dfu_app_set_dm_handle(dm_handle_t const * p_dm_handle) |
| rgrover1 | 185:28d8c818d84f | 176 | { |
| rgrover1 | 185:28d8c818d84f | 177 | m_dm_handle_valid = false; |
| rgrover1 | 185:28d8c818d84f | 178 | |
| rgrover1 | 185:28d8c818d84f | 179 | if (p_dm_handle != NULL) |
| rgrover1 | 185:28d8c818d84f | 180 | { |
| rgrover1 | 185:28d8c818d84f | 181 | m_dm_handle = *p_dm_handle; |
| rgrover1 | 185:28d8c818d84f | 182 | m_dm_handle_valid = true; |
| rgrover1 | 185:28d8c818d84f | 183 | } |
| rgrover1 | 185:28d8c818d84f | 184 | } |
| rgrover1 | 185:28d8c818d84f | 185 | #endif /* NEEDED */ |
