BLE FOTA APP

Dependencies:   BLE_API mbed

It doesn't work with the default FOTA bootloader. It use NVIC_SystemReset() to enter a bootloader.

Committer:
yihui
Date:
Fri Oct 10 03:36:28 2014 +0000
Revision:
1:a607cd9655d7
use NVIC_SystemReset() to run bootloader

Who changed what in which revision?

UserRevisionLine numberNew contents of line
yihui 1:a607cd9655d7 1 /* mbed Microcontroller Library
yihui 1:a607cd9655d7 2 * Copyright (c) 2006-2013 ARM Limited
yihui 1:a607cd9655d7 3 *
yihui 1:a607cd9655d7 4 * Licensed under the Apache License, Version 2.0 (the "License");
yihui 1:a607cd9655d7 5 * you may not use this file except in compliance with the License.
yihui 1:a607cd9655d7 6 * You may obtain a copy of the License at
yihui 1:a607cd9655d7 7 *
yihui 1:a607cd9655d7 8 * http://www.apache.org/licenses/LICENSE-2.0
yihui 1:a607cd9655d7 9 *
yihui 1:a607cd9655d7 10 * Unless required by applicable law or agreed to in writing, software
yihui 1:a607cd9655d7 11 * distributed under the License is distributed on an "AS IS" BASIS,
yihui 1:a607cd9655d7 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
yihui 1:a607cd9655d7 13 * See the License for the specific language governing permissions and
yihui 1:a607cd9655d7 14 * limitations under the License.
yihui 1:a607cd9655d7 15 */
yihui 1:a607cd9655d7 16
yihui 1:a607cd9655d7 17 #include "common/common.h"
yihui 1:a607cd9655d7 18 #include "nordic_common.h"
yihui 1:a607cd9655d7 19
yihui 1:a607cd9655d7 20 #include "app_timer.h"
yihui 1:a607cd9655d7 21 #include "btle.h"
yihui 1:a607cd9655d7 22
yihui 1:a607cd9655d7 23 #include "ble_stack_handler_types.h"
yihui 1:a607cd9655d7 24 #include "ble_radio_notification.h"
yihui 1:a607cd9655d7 25 #include "ble_flash.h"
yihui 1:a607cd9655d7 26 #if NEED_BOND_MANAGER
yihui 1:a607cd9655d7 27 #include "ble_bondmngr.h"
yihui 1:a607cd9655d7 28 #endif
yihui 1:a607cd9655d7 29 #include "ble_conn_params.h"
yihui 1:a607cd9655d7 30
yihui 1:a607cd9655d7 31 #include "btle_gap.h"
yihui 1:a607cd9655d7 32 #include "btle_advertising.h"
yihui 1:a607cd9655d7 33 #include "custom/custom_helper.h"
yihui 1:a607cd9655d7 34
yihui 1:a607cd9655d7 35 #include "softdevice_handler.h"
yihui 1:a607cd9655d7 36 #include "pstorage.h"
yihui 1:a607cd9655d7 37
yihui 1:a607cd9655d7 38 #include "GapEvents.h"
yihui 1:a607cd9655d7 39 #include "nRF51Gap.h"
yihui 1:a607cd9655d7 40 #include "nRF51GattServer.h"
yihui 1:a607cd9655d7 41
yihui 1:a607cd9655d7 42 #include "ble_hci.h"
yihui 1:a607cd9655d7 43
yihui 1:a607cd9655d7 44 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 45 static void service_error_callback(uint32_t nrf_error);
yihui 1:a607cd9655d7 46 #endif
yihui 1:a607cd9655d7 47 extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
yihui 1:a607cd9655d7 48 void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name);
yihui 1:a607cd9655d7 49
yihui 1:a607cd9655d7 50 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 51 static error_t bond_manager_init(void);
yihui 1:a607cd9655d7 52 #endif
yihui 1:a607cd9655d7 53
yihui 1:a607cd9655d7 54 static void btle_handler(ble_evt_t *p_ble_evt);
yihui 1:a607cd9655d7 55
yihui 1:a607cd9655d7 56 static void sys_evt_dispatch(uint32_t sys_evt)
yihui 1:a607cd9655d7 57 {
yihui 1:a607cd9655d7 58 #if NEED_PSTORAGE /* disabled by default */
yihui 1:a607cd9655d7 59 pstorage_sys_event_handler(sys_evt);
yihui 1:a607cd9655d7 60 #endif
yihui 1:a607cd9655d7 61 }
yihui 1:a607cd9655d7 62
yihui 1:a607cd9655d7 63 error_t btle_init(void)
yihui 1:a607cd9655d7 64 {
yihui 1:a607cd9655d7 65 const bool useScheduler = false;
yihui 1:a607cd9655d7 66 #ifdef TARGET_HRM1017
yihui 1:a607cd9655d7 67 SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_RC_250_PPM_4000MS_CALIBRATION, useScheduler);
yihui 1:a607cd9655d7 68 #else
yihui 1:a607cd9655d7 69 SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, useScheduler);
yihui 1:a607cd9655d7 70 #endif
yihui 1:a607cd9655d7 71
yihui 1:a607cd9655d7 72 // Enable BLE stack
yihui 1:a607cd9655d7 73 /**
yihui 1:a607cd9655d7 74 * Using this call, the application can select whether to include the
yihui 1:a607cd9655d7 75 * Service Changed characteristic in the GATT Server. The default in all
yihui 1:a607cd9655d7 76 * previous releases has been to include the Service Changed characteristic,
yihui 1:a607cd9655d7 77 * but this affects how GATT clients behave. Specifically, it requires
yihui 1:a607cd9655d7 78 * clients to subscribe to this attribute and not to cache attribute handles
yihui 1:a607cd9655d7 79 * between connections unless the devices are bonded. If the application
yihui 1:a607cd9655d7 80 * does not need to change the structure of the GATT server attributes at
yihui 1:a607cd9655d7 81 * runtime this adds unnecessary complexity to the interaction with peer
yihui 1:a607cd9655d7 82 * clients. If the SoftDevice is enabled with the Service Changed
yihui 1:a607cd9655d7 83 * Characteristics turned off, then clients are allowed to cache attribute
yihui 1:a607cd9655d7 84 * handles making applications simpler on both sides.
yihui 1:a607cd9655d7 85 */
yihui 1:a607cd9655d7 86 static const bool IS_SRVC_CHANGED_CHARACT_PRESENT = true;
yihui 1:a607cd9655d7 87 ble_enable_params_t enableParams = {
yihui 1:a607cd9655d7 88 .gatts_enable_params = {
yihui 1:a607cd9655d7 89 .service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT
yihui 1:a607cd9655d7 90 }
yihui 1:a607cd9655d7 91 };
yihui 1:a607cd9655d7 92 if (sd_ble_enable(&enableParams) != NRF_SUCCESS) {
yihui 1:a607cd9655d7 93 return ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 94 }
yihui 1:a607cd9655d7 95
yihui 1:a607cd9655d7 96 ble_gap_addr_t addr;
yihui 1:a607cd9655d7 97 if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) {
yihui 1:a607cd9655d7 98 return ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 99 }
yihui 1:a607cd9655d7 100 if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) {
yihui 1:a607cd9655d7 101 return ERROR_INVALID_PARAM;
yihui 1:a607cd9655d7 102 }
yihui 1:a607cd9655d7 103
yihui 1:a607cd9655d7 104 ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
yihui 1:a607cd9655d7 105 ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));
yihui 1:a607cd9655d7 106
yihui 1:a607cd9655d7 107 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 108 bond_manager_init();
yihui 1:a607cd9655d7 109 #endif
yihui 1:a607cd9655d7 110 btle_gap_init();
yihui 1:a607cd9655d7 111
yihui 1:a607cd9655d7 112 return ERROR_NONE;
yihui 1:a607cd9655d7 113 }
yihui 1:a607cd9655d7 114
yihui 1:a607cd9655d7 115 static void btle_handler(ble_evt_t *p_ble_evt)
yihui 1:a607cd9655d7 116 {
yihui 1:a607cd9655d7 117 /* Library service handlers */
yihui 1:a607cd9655d7 118 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 119 ble_bondmngr_on_ble_evt(p_ble_evt);
yihui 1:a607cd9655d7 120 #endif
yihui 1:a607cd9655d7 121 #if SDK_CONN_PARAMS_MODULE_ENABLE
yihui 1:a607cd9655d7 122 ble_conn_params_on_ble_evt(p_ble_evt);
yihui 1:a607cd9655d7 123 #endif
yihui 1:a607cd9655d7 124
yihui 1:a607cd9655d7 125 /* Custom event handler */
yihui 1:a607cd9655d7 126 switch (p_ble_evt->header.evt_id) {
yihui 1:a607cd9655d7 127 case BLE_GAP_EVT_CONNECTED: {
yihui 1:a607cd9655d7 128 Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
yihui 1:a607cd9655d7 129 nRF51Gap::getInstance().setConnectionHandle(handle);
yihui 1:a607cd9655d7 130 const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params));
yihui 1:a607cd9655d7 131 nRF51Gap::getInstance().processConnectionEvent(handle, params);
yihui 1:a607cd9655d7 132 break;
yihui 1:a607cd9655d7 133 }
yihui 1:a607cd9655d7 134
yihui 1:a607cd9655d7 135 case BLE_GAP_EVT_DISCONNECTED: {
yihui 1:a607cd9655d7 136 Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
yihui 1:a607cd9655d7 137 // Since we are not in a connection and have not started advertising,
yihui 1:a607cd9655d7 138 // store bonds
yihui 1:a607cd9655d7 139 nRF51Gap::getInstance().setConnectionHandle (BLE_CONN_HANDLE_INVALID);
yihui 1:a607cd9655d7 140 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 141 ASSERT_STATUS_RET_VOID ( ble_bondmngr_bonded_centrals_store());
yihui 1:a607cd9655d7 142 #endif
yihui 1:a607cd9655d7 143
yihui 1:a607cd9655d7 144 Gap::DisconnectionReason_t reason;
yihui 1:a607cd9655d7 145 switch (p_ble_evt->evt.gap_evt.params.disconnected.reason) {
yihui 1:a607cd9655d7 146 case BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION:
yihui 1:a607cd9655d7 147 reason = Gap::LOCAL_HOST_TERMINATED_CONNECTION;
yihui 1:a607cd9655d7 148 break;
yihui 1:a607cd9655d7 149 case BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION:
yihui 1:a607cd9655d7 150 reason = Gap::REMOTE_USER_TERMINATED_CONNECTION;
yihui 1:a607cd9655d7 151 break;
yihui 1:a607cd9655d7 152 case BLE_HCI_CONN_INTERVAL_UNACCEPTABLE:
yihui 1:a607cd9655d7 153 reason = Gap::CONN_INTERVAL_UNACCEPTABLE;
yihui 1:a607cd9655d7 154 break;
yihui 1:a607cd9655d7 155 default:
yihui 1:a607cd9655d7 156 /* Please refer to the underlying transport library for an
yihui 1:a607cd9655d7 157 * interpretion of this reason's value. */
yihui 1:a607cd9655d7 158 reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason);
yihui 1:a607cd9655d7 159 break;
yihui 1:a607cd9655d7 160 }
yihui 1:a607cd9655d7 161 nRF51Gap::getInstance().processDisconnectionEvent(handle, reason);
yihui 1:a607cd9655d7 162 break;
yihui 1:a607cd9655d7 163 }
yihui 1:a607cd9655d7 164
yihui 1:a607cd9655d7 165 case BLE_GAP_EVT_SEC_PARAMS_REQUEST: {
yihui 1:a607cd9655d7 166 ble_gap_sec_params_t sec_params = {0};
yihui 1:a607cd9655d7 167
yihui 1:a607cd9655d7 168 sec_params.timeout = 30; /*< Timeout for Pairing Request or
yihui 1:a607cd9655d7 169 * Security Request (in seconds). */
yihui 1:a607cd9655d7 170 sec_params.bond = 1; /**< Perform bonding. */
yihui 1:a607cd9655d7 171 sec_params.mitm = CFG_BLE_SEC_PARAM_MITM;
yihui 1:a607cd9655d7 172 sec_params.io_caps = CFG_BLE_SEC_PARAM_IO_CAPABILITIES;
yihui 1:a607cd9655d7 173 sec_params.oob = CFG_BLE_SEC_PARAM_OOB;
yihui 1:a607cd9655d7 174 sec_params.min_key_size = CFG_BLE_SEC_PARAM_MIN_KEY_SIZE;
yihui 1:a607cd9655d7 175 sec_params.max_key_size = CFG_BLE_SEC_PARAM_MAX_KEY_SIZE;
yihui 1:a607cd9655d7 176
yihui 1:a607cd9655d7 177 ASSERT_STATUS_RET_VOID(sd_ble_gap_sec_params_reply(nRF51Gap::getInstance().getConnectionHandle(),
yihui 1:a607cd9655d7 178 BLE_GAP_SEC_STATUS_SUCCESS, &sec_params));
yihui 1:a607cd9655d7 179 }
yihui 1:a607cd9655d7 180 break;
yihui 1:a607cd9655d7 181
yihui 1:a607cd9655d7 182 case BLE_GAP_EVT_TIMEOUT:
yihui 1:a607cd9655d7 183 if (p_ble_evt->evt.gap_evt.params.timeout.src == BLE_GAP_TIMEOUT_SRC_ADVERTISEMENT) {
yihui 1:a607cd9655d7 184 nRF51Gap::getInstance().processEvent(GapEvents::GAP_EVENT_TIMEOUT);
yihui 1:a607cd9655d7 185 }
yihui 1:a607cd9655d7 186 break;
yihui 1:a607cd9655d7 187
yihui 1:a607cd9655d7 188 case BLE_GATTC_EVT_TIMEOUT:
yihui 1:a607cd9655d7 189 case BLE_GATTS_EVT_TIMEOUT:
yihui 1:a607cd9655d7 190 // Disconnect on GATT Server and Client timeout events.
yihui 1:a607cd9655d7 191 // ASSERT_STATUS_RET_VOID (sd_ble_gap_disconnect(m_conn_handle,
yihui 1:a607cd9655d7 192 // BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
yihui 1:a607cd9655d7 193 break;
yihui 1:a607cd9655d7 194
yihui 1:a607cd9655d7 195 default:
yihui 1:a607cd9655d7 196 break;
yihui 1:a607cd9655d7 197 }
yihui 1:a607cd9655d7 198
yihui 1:a607cd9655d7 199 nRF51GattServer::getInstance().hwCallback(p_ble_evt);
yihui 1:a607cd9655d7 200 }
yihui 1:a607cd9655d7 201
yihui 1:a607cd9655d7 202 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 203 /**************************************************************************/
yihui 1:a607cd9655d7 204 /*!
yihui 1:a607cd9655d7 205 @brief Initialises the bond manager
yihui 1:a607cd9655d7 206
yihui 1:a607cd9655d7 207 @note Bond data will be cleared on reset if the bond delete
yihui 1:a607cd9655d7 208 button is pressed during initialisation (the button is
yihui 1:a607cd9655d7 209 defined as CFG_BLE_BOND_DELETE_BUTTON_NUM).
yihui 1:a607cd9655d7 210
yihui 1:a607cd9655d7 211 @returns
yihui 1:a607cd9655d7 212 */
yihui 1:a607cd9655d7 213 /**************************************************************************/
yihui 1:a607cd9655d7 214 static error_t bond_manager_init(void)
yihui 1:a607cd9655d7 215 {
yihui 1:a607cd9655d7 216 ble_bondmngr_init_t bond_para = {0};
yihui 1:a607cd9655d7 217
yihui 1:a607cd9655d7 218 ASSERT_STATUS ( pstorage_init());
yihui 1:a607cd9655d7 219
yihui 1:a607cd9655d7 220 bond_para.flash_page_num_bond = CFG_BLE_BOND_FLASH_PAGE_BOND;
yihui 1:a607cd9655d7 221 bond_para.flash_page_num_sys_attr = CFG_BLE_BOND_FLASH_PAGE_SYS_ATTR;
yihui 1:a607cd9655d7 222 //bond_para.bonds_delete = boardButtonCheck(CFG_BLE_BOND_DELETE_BUTTON_NUM) ;
yihui 1:a607cd9655d7 223 bond_para.evt_handler = NULL;
yihui 1:a607cd9655d7 224 bond_para.error_handler = service_error_callback;
yihui 1:a607cd9655d7 225
yihui 1:a607cd9655d7 226 ASSERT_STATUS( ble_bondmngr_init( &bond_para ));
yihui 1:a607cd9655d7 227
yihui 1:a607cd9655d7 228 /* Init radio active/inactive notification to flash (to only perform flashing when the radio is inactive) */
yihui 1:a607cd9655d7 229 // ASSERT_STATUS( ble_radio_notification_init(NRF_APP_PRIORITY_HIGH,
yihui 1:a607cd9655d7 230 // NRF_RADIO_NOTIFICATION_DISTANCE_4560US,
yihui 1:a607cd9655d7 231 // ble_flash_on_radio_active_evt) );
yihui 1:a607cd9655d7 232
yihui 1:a607cd9655d7 233 return ERROR_NONE;
yihui 1:a607cd9655d7 234 }
yihui 1:a607cd9655d7 235 #endif // #if NEED_BOND_MANAGER
yihui 1:a607cd9655d7 236
yihui 1:a607cd9655d7 237 #if NEED_BOND_MANAGER /* disabled by default */
yihui 1:a607cd9655d7 238 /**************************************************************************/
yihui 1:a607cd9655d7 239 /*!
yihui 1:a607cd9655d7 240 @brief
yihui 1:a607cd9655d7 241 @param[in] nrf_error
yihui 1:a607cd9655d7 242 @returns
yihui 1:a607cd9655d7 243 */
yihui 1:a607cd9655d7 244 /**************************************************************************/
yihui 1:a607cd9655d7 245 static void service_error_callback(uint32_t nrf_error)
yihui 1:a607cd9655d7 246 {
yihui 1:a607cd9655d7 247 ASSERT_STATUS_RET_VOID( nrf_error );
yihui 1:a607cd9655d7 248 }
yihui 1:a607cd9655d7 249 #endif // #if NEED_BOND_MANAGER
yihui 1:a607cd9655d7 250
yihui 1:a607cd9655d7 251 /**************************************************************************/
yihui 1:a607cd9655d7 252 /*!
yihui 1:a607cd9655d7 253 @brief Callback when an error occurs inside the SoftDevice
yihui 1:a607cd9655d7 254
yihui 1:a607cd9655d7 255 @param[in] line_num
yihui 1:a607cd9655d7 256 @param[in] p-file_name
yihui 1:a607cd9655d7 257
yihui 1:a607cd9655d7 258 @returns
yihui 1:a607cd9655d7 259 */
yihui 1:a607cd9655d7 260 /**************************************************************************/
yihui 1:a607cd9655d7 261 void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name)
yihui 1:a607cd9655d7 262 {
yihui 1:a607cd9655d7 263 ASSERT(false, (void) 0);
yihui 1:a607cd9655d7 264 }
yihui 1:a607cd9655d7 265
yihui 1:a607cd9655d7 266 /**************************************************************************/
yihui 1:a607cd9655d7 267 /*!
yihui 1:a607cd9655d7 268 @brief Handler for general errors above the SoftDevice layer.
yihui 1:a607cd9655d7 269 Typically we can' recover from this so we do a reset.
yihui 1:a607cd9655d7 270
yihui 1:a607cd9655d7 271 @param[in] error_code
yihui 1:a607cd9655d7 272 @param[in] line_num
yihui 1:a607cd9655d7 273 @param[in] p-file_name
yihui 1:a607cd9655d7 274
yihui 1:a607cd9655d7 275 @returns
yihui 1:a607cd9655d7 276 */
yihui 1:a607cd9655d7 277 /**************************************************************************/
yihui 1:a607cd9655d7 278 void app_error_handler(uint32_t error_code,
yihui 1:a607cd9655d7 279 uint32_t line_num,
yihui 1:a607cd9655d7 280 const uint8_t *p_file_name)
yihui 1:a607cd9655d7 281 {
yihui 1:a607cd9655d7 282 ASSERT_STATUS_RET_VOID( error_code );
yihui 1:a607cd9655d7 283 NVIC_SystemReset();
yihui 1:a607cd9655d7 284 }