Release 0.3.7

=============

This is a minor set of enhancements mostly around reduce our global static
memory footprint.

Enhancements
~~~~~~~~~~~~

* Reduce the maximum number of CHARACTERISTICS and DESCRIPTORS that can be
  handled. This has memory implications for static global memory. It should
  be possible to re-architect our solution for add_characteristic() to not
  require these limits; hopefully we'll get there soon.

* Move nRF51GattServer::getInstance() into a .cpp file; same for nRF51Gap::getInstance().

* Reduce max bonds to managed by device-manager to 4; this has memory implications for static global memory.

* Reduce pStorage command queue size to 2; this has memory implications for static global memory.

* Replace uses of deprecated Gap::addr_type_t with Gap::AddressType_t.

* Some UUID-related types have moved into UUID class. Minor changes were needed to work around build errors.

Bugfixes
~~~~~~~~

* None.
This commit is contained in:
Rohit Grover 2015-06-08 10:37:21 +01:00
commit 9f72c4ba7c
9 changed files with 366 additions and 359 deletions

View file

@ -113,8 +113,8 @@ static void btle_handler(ble_evt_t *p_ble_evt)
const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr;
const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr;
nRF51Gap::getInstance().processConnectionEvent(handle,
static_cast<Gap::addr_type_t>(peer->addr_type), peer->addr,
static_cast<Gap::addr_type_t>(own->addr_type), own->addr,
static_cast<Gap::AddressType_t>(peer->addr_type), peer->addr,
static_cast<Gap::AddressType_t>(own->addr_type), own->addr,
params);
break;
}

View file

@ -23,7 +23,7 @@
* structures involved in maintaining a local cache of 128-bit UUIDs.
*/
typedef struct {
LongUUIDBytes_t uuid;
UUID::LongUUIDBytes_t uuid;
uint8_t type;
} converted_uuid_table_entry_t;
static const unsigned UUID_TABLE_MAX_ENTRIES = 8; /* This is the maximum number of 128-bit UUIDs with distinct bases that
@ -38,12 +38,12 @@ converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES];
* @return true if a match is found.
*/
static bool
lookupConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t *recoveredType)
lookupConvertedUUIDTable(const UUID::LongUUIDBytes_t uuid, uint8_t *recoveredType)
{
unsigned i;
for (i = 0; i < uuidTableEntries; i++) {
unsigned byteIndex;
for (byteIndex = 0; byteIndex < LENGTH_OF_LONG_UUID; byteIndex++) {
for (byteIndex = 0; byteIndex < UUID::LENGTH_OF_LONG_UUID; byteIndex++) {
/* Skip bytes 2 and 3, because they contain the shortUUID (16-bit) version of the
* long UUID; and we're comparing against the remainder. */
if ((byteIndex == 2) || (byteIndex == 3)) {
@ -55,7 +55,7 @@ lookupConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t *recoveredType)
}
}
if (byteIndex == LENGTH_OF_LONG_UUID) {
if (byteIndex == UUID::LENGTH_OF_LONG_UUID) {
*recoveredType = convertedUUIDTable[i].type;
return true;
}
@ -65,13 +65,13 @@ lookupConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t *recoveredType)
}
static void
addToConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t type)
addToConvertedUUIDTable(const UUID::LongUUIDBytes_t uuid, uint8_t type)
{
if (uuidTableEntries == UUID_TABLE_MAX_ENTRIES) {
return; /* recovery needed; or at least the user should be warned about this fact.*/
}
memcpy(convertedUUIDTable[uuidTableEntries].uuid, uuid, LENGTH_OF_LONG_UUID);
memcpy(convertedUUIDTable[uuidTableEntries].uuid, uuid, UUID::LENGTH_OF_LONG_UUID);
convertedUUIDTable[uuidTableEntries].uuid[2] = 0;
convertedUUIDTable[uuidTableEntries].uuid[3] = 0;
convertedUUIDTable[uuidTableEntries].type = type;
@ -149,8 +149,8 @@ uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base)
uint8_t uuid_type = 0;
/* Reverse the bytes since ble_uuid128_t is LSB */
for (unsigned i = 0; i < LENGTH_OF_LONG_UUID; i++) {
base_uuid.uuid128[i] = p_uuid_base[LENGTH_OF_LONG_UUID - 1 - i];
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
base_uuid.uuid128[i] = p_uuid_base[UUID::LENGTH_OF_LONG_UUID - 1 - i];
}
ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0);
@ -166,14 +166,14 @@ uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base)
error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
ble_uuid_t *p_uuid)
{
LongUUIDBytes_t uuid_base_le;
UUID::LongUUIDBytes_t uuid_base_le;
/* Reverse the bytes since ble_uuid128_t is LSB */
for (uint8_t i = 0; i < LENGTH_OF_LONG_UUID; i++) {
uuid_base_le[i] = p_uuid_base[LENGTH_OF_LONG_UUID - 1 - i];
for (uint8_t i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
uuid_base_le[i] = p_uuid_base[UUID::LENGTH_OF_LONG_UUID - 1 - i];
}
ASSERT_STATUS( sd_ble_uuid_decode(LENGTH_OF_LONG_UUID, uuid_base_le, p_uuid));
ASSERT_STATUS( sd_ble_uuid_decode(UUID::LENGTH_OF_LONG_UUID, uuid_base_le, p_uuid));
return ERROR_NONE;
}

View file

@ -21,6 +21,11 @@
#include "ble_advdata.h"
#include "ble_hci.h"
nRF51Gap &nRF51Gap::getInstance() {
static nRF51Gap m_instance;
return m_instance;
}
/**************************************************************************/
/*!
@brief Sets the advertising parameters and payload for the device
@ -304,7 +309,7 @@ uint16_t nRF51Gap::getConnectionHandle(void)
@endcode
*/
/**************************************************************************/
ble_error_t nRF51Gap::setAddress(addr_type_t type, const address_t address)
ble_error_t nRF51Gap::setAddress(AddressType_t type, const address_t address)
{
if (type > ADDR_TYPE_RANDOM_PRIVATE_NON_RESOLVABLE) {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
@ -319,7 +324,7 @@ ble_error_t nRF51Gap::setAddress(addr_type_t type, const address_t address)
return BLE_ERROR_NONE;
}
ble_error_t nRF51Gap::getAddress(addr_type_t *typeP, address_t address)
ble_error_t nRF51Gap::getAddress(AddressType_t *typeP, address_t address)
{
ble_gap_addr_t dev_addr;
if (sd_ble_gap_address_get(&dev_addr) != NRF_SUCCESS) {
@ -327,7 +332,7 @@ ble_error_t nRF51Gap::getAddress(addr_type_t *typeP, address_t address)
}
if (typeP != NULL) {
*typeP = static_cast<addr_type_t>(dev_addr.addr_type);
*typeP = static_cast<AddressType_t>(dev_addr.addr_type);
}
if (address != NULL) {
memcpy(address, dev_addr.addr, ADDR_LEN);

View file

@ -38,14 +38,11 @@
class nRF51Gap : public Gap
{
public:
static nRF51Gap &getInstance() {
static nRF51Gap m_instance;
return m_instance;
}
static nRF51Gap &getInstance();
/* Functions that must be implemented from Gap */
virtual ble_error_t setAddress(addr_type_t type, const address_t address);
virtual ble_error_t getAddress(addr_type_t *typeP, address_t address);
virtual ble_error_t setAddress(AddressType_t type, const address_t address);
virtual ble_error_t getAddress(AddressType_t *typeP, address_t address);
virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &);
virtual uint16_t getMinAdvertisingInterval(void) const {return ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MIN);}

View file

@ -22,6 +22,11 @@
#include "nRF51Gap.h"
nRF51GattServer &nRF51GattServer::getInstance(void) {
static nRF51GattServer m_instance;
return m_instance;
}
/**************************************************************************/
/*!
@brief Adds a new service to the GATT table on the peripheral

View file

@ -27,10 +27,7 @@
class nRF51GattServer : public GattServer
{
public:
static nRF51GattServer &getInstance() {
static nRF51GattServer m_instance;
return m_instance;
}
static nRF51GattServer &getInstance();
/* Functions that must be implemented from GattServer */
virtual ble_error_t addService(GattService &);
@ -45,8 +42,8 @@ public:
void hwCallback(ble_evt_t *p_ble_evt);
private:
const static unsigned BLE_TOTAL_CHARACTERISTICS = 24;
const static unsigned BLE_TOTAL_DESCRIPTORS = 24;
const static unsigned BLE_TOTAL_CHARACTERISTICS = 20;
const static unsigned BLE_TOTAL_DESCRIPTORS = 8;
GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS];
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];

View file

@ -1,98 +1,98 @@
/* Copyright (C) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
/**
* @file device_manager_cnfg.h
*
* @cond
* @defgroup device_manager_cnfg Device Manager Configuration
* @ingroup device_manager
* @{
*
* @brief Defines application specific configuration for Device Manager.
*
* @details All configurations that are specific to application have been defined
* here. Application should configuration that best suits its requirements.
*/
#ifndef DEVICE_MANAGER_CNFG_H__
#define DEVICE_MANAGER_CNFG_H__
/**
* @defgroup device_manager_inst Device Manager Instances
* @{
*/
/**
* @brief Maximum applications that Device Manager can support.
*
* @details Maximum application that the Device Manager can support.
* Currently only one application can be supported.
* Minimum value : 1
* Maximum value : 1
* Dependencies : None.
*/
#define DEVICE_MANAGER_MAX_APPLICATIONS 1
/**
* @brief Maximum connections that Device Manager should simultaneously manage.
*
* @details Maximum connections that Device Manager should simultaneously manage.
* Minimum value : 1
* Maximum value : Maximum links supported by SoftDevice.
* Dependencies : None.
*/
#define DEVICE_MANAGER_MAX_CONNECTIONS 1
/**
* @brief Maximum bonds that Device Manager should manage.
*
* @details Maximum bonds that Device Manager should manage.
* Minimum value : 1
* Maximum value : 254.
* Dependencies : None.
* @note In case of GAP Peripheral role, the Device Manager will accept bonding procedure
* requests from peers even if this limit is reached, but bonding information will not
* be stored. In such cases, application will be notified with DM_DEVICE_CONTEXT_FULL
* as event result at the completion of the security procedure.
*/
#define DEVICE_MANAGER_MAX_BONDS 7
/**
* @brief Maximum Characteristic Client Descriptors used for GATT Server.
*
* @details Maximum Characteristic Client Descriptors used for GATT Server.
* Minimum value : 1
* Maximum value : 254.
* Dependencies : None.
*/
#define DM_GATT_CCCD_COUNT 2
/**
* @brief Size of application context.
*
* @details Size of application context that Device Manager should manage for each bonded device.
* Size had to be a multiple of word size.
* Minimum value : 4.
* Maximum value : 256.
* Dependencies : Needed only if Application Context saving is used by the application.
* @note If set to zero, its an indication that application context is not required to be managed
* by the module.
*/
#define DEVICE_MANAGER_APP_CONTEXT_SIZE 0
/* @} */
/* @} */
/** @endcond */
#endif // DEVICE_MANAGER_CNFG_H__
/* Copyright (C) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
/**
* @file device_manager_cnfg.h
*
* @cond
* @defgroup device_manager_cnfg Device Manager Configuration
* @ingroup device_manager
* @{
*
* @brief Defines application specific configuration for Device Manager.
*
* @details All configurations that are specific to application have been defined
* here. Application should configuration that best suits its requirements.
*/
#ifndef DEVICE_MANAGER_CNFG_H__
#define DEVICE_MANAGER_CNFG_H__
/**
* @defgroup device_manager_inst Device Manager Instances
* @{
*/
/**
* @brief Maximum applications that Device Manager can support.
*
* @details Maximum application that the Device Manager can support.
* Currently only one application can be supported.
* Minimum value : 1
* Maximum value : 1
* Dependencies : None.
*/
#define DEVICE_MANAGER_MAX_APPLICATIONS 1
/**
* @brief Maximum connections that Device Manager should simultaneously manage.
*
* @details Maximum connections that Device Manager should simultaneously manage.
* Minimum value : 1
* Maximum value : Maximum links supported by SoftDevice.
* Dependencies : None.
*/
#define DEVICE_MANAGER_MAX_CONNECTIONS 1
/**
* @brief Maximum bonds that Device Manager should manage.
*
* @details Maximum bonds that Device Manager should manage.
* Minimum value : 1
* Maximum value : 254.
* Dependencies : None.
* @note In case of GAP Peripheral role, the Device Manager will accept bonding procedure
* requests from peers even if this limit is reached, but bonding information will not
* be stored. In such cases, application will be notified with DM_DEVICE_CONTEXT_FULL
* as event result at the completion of the security procedure.
*/
#define DEVICE_MANAGER_MAX_BONDS 4
/**
* @brief Maximum Characteristic Client Descriptors used for GATT Server.
*
* @details Maximum Characteristic Client Descriptors used for GATT Server.
* Minimum value : 1
* Maximum value : 254.
* Dependencies : None.
*/
#define DM_GATT_CCCD_COUNT 2
/**
* @brief Size of application context.
*
* @details Size of application context that Device Manager should manage for each bonded device.
* Size had to be a multiple of word size.
* Minimum value : 4.
* Maximum value : 256.
* Dependencies : Needed only if Application Context saving is used by the application.
* @note If set to zero, its an indication that application context is not required to be managed
* by the module.
*/
#define DEVICE_MANAGER_APP_CONTEXT_SIZE 0
/* @} */
/* @} */
/** @endcond */
#endif // DEVICE_MANAGER_CNFG_H__

View file

@ -1,70 +1,70 @@
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
/** @cond To make doxygen skip this file */
/** @file
* This header contains defines with respect persistent storage that are specific to
* persistent storage implementation and application use case.
*/
#ifndef PSTORAGE_PL_H__
#define PSTORAGE_PL_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif // #ifdef __cplusplus
#define PSTORAGE_FLASH_PAGE_SIZE ((uint16_t)NRF_FICR->CODEPAGESIZE) /**< Size of one flash page. */
#define PSTORAGE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */
#define PSTORAGE_FLASH_PAGE_END \
((NRF_UICR->BOOTLOADERADDR != PSTORAGE_FLASH_EMPTY_MASK) \
? (NRF_UICR->BOOTLOADERADDR / PSTORAGE_FLASH_PAGE_SIZE) \
: NRF_FICR->CODESIZE)
#define PSTORAGE_MAX_APPLICATIONS 1 /**< Maximum number of applications that can be registered with the module, configurable based on system requirements. */
#define PSTORAGE_MIN_BLOCK_SIZE 0x0010 /**< Minimum size of block that can be registered with the module. Should be configured based on system requirements, recommendation is not have this value to be at least size of word. */
#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_MAX_APPLICATIONS - 1) \
* PSTORAGE_FLASH_PAGE_SIZE) /**< Start address for persistent data, configurable according to system requirements. */
#define PSTORAGE_DATA_END_ADDR ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */
#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR /**< Top-most page is used as swap area for clear and update. */
#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */
#define PSTORAGE_CMD_QUEUE_SIZE 10 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */
/** Abstracts persistently memory block identifier. */
typedef uint32_t pstorage_block_t;
typedef struct
{
uint32_t module_id; /**< Module ID.*/
pstorage_block_t block_id; /**< Block ID.*/
} pstorage_handle_t;
typedef uint16_t pstorage_size_t; /** Size of length and offset fields. */
/**@brief Handles Flash Access Result Events. To be called in the system event dispatcher of the application. */
void pstorage_sys_event_handler (uint32_t sys_evt);
#ifdef __cplusplus
}
#endif // #ifdef __cplusplus
#endif // PSTORAGE_PL_H__
/** @} */
/** @endcond */
/* Copyright (c) 2013 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
/** @cond To make doxygen skip this file */
/** @file
* This header contains defines with respect persistent storage that are specific to
* persistent storage implementation and application use case.
*/
#ifndef PSTORAGE_PL_H__
#define PSTORAGE_PL_H__
#include <stdint.h>
#ifdef __cplusplus
extern "C" {
#endif // #ifdef __cplusplus
#define PSTORAGE_FLASH_PAGE_SIZE ((uint16_t)NRF_FICR->CODEPAGESIZE) /**< Size of one flash page. */
#define PSTORAGE_FLASH_EMPTY_MASK 0xFFFFFFFF /**< Bit mask that defines an empty address in flash. */
#define PSTORAGE_FLASH_PAGE_END \
((NRF_UICR->BOOTLOADERADDR != PSTORAGE_FLASH_EMPTY_MASK) \
? (NRF_UICR->BOOTLOADERADDR / PSTORAGE_FLASH_PAGE_SIZE) \
: NRF_FICR->CODESIZE)
#define PSTORAGE_MAX_APPLICATIONS 1 /**< Maximum number of applications that can be registered with the module, configurable based on system requirements. */
#define PSTORAGE_MIN_BLOCK_SIZE 0x0010 /**< Minimum size of block that can be registered with the module. Should be configured based on system requirements, recommendation is not have this value to be at least size of word. */
#define PSTORAGE_DATA_START_ADDR ((PSTORAGE_FLASH_PAGE_END - PSTORAGE_MAX_APPLICATIONS - 1) \
* PSTORAGE_FLASH_PAGE_SIZE) /**< Start address for persistent data, configurable according to system requirements. */
#define PSTORAGE_DATA_END_ADDR ((PSTORAGE_FLASH_PAGE_END - 1) * PSTORAGE_FLASH_PAGE_SIZE) /**< End address for persistent data, configurable according to system requirements. */
#define PSTORAGE_SWAP_ADDR PSTORAGE_DATA_END_ADDR /**< Top-most page is used as swap area for clear and update. */
#define PSTORAGE_MAX_BLOCK_SIZE PSTORAGE_FLASH_PAGE_SIZE /**< Maximum size of block that can be registered with the module. Should be configured based on system requirements. And should be greater than or equal to the minimum size. */
#define PSTORAGE_CMD_QUEUE_SIZE 2 /**< Maximum number of flash access commands that can be maintained by the module for all applications. Configurable. */
/** Abstracts persistently memory block identifier. */
typedef uint32_t pstorage_block_t;
typedef struct
{
uint32_t module_id; /**< Module ID.*/
pstorage_block_t block_id; /**< Block ID.*/
} pstorage_handle_t;
typedef uint16_t pstorage_size_t; /** Size of length and offset fields. */
/**@brief Handles Flash Access Result Events. To be called in the system event dispatcher of the application. */
void pstorage_sys_event_handler (uint32_t sys_evt);
#ifdef __cplusplus
}
#endif // #ifdef __cplusplus
#endif // PSTORAGE_PL_H__
/** @} */
/** @endcond */

View file

@ -1,162 +1,165 @@
/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include <string.h>
#include "dfu_app_handler.h"
#include "bootloader_util.h"
#include "nrf.h"
#include "nrf_sdm.h"
#include "ble_gatts.h"
#include "app_error.h"
#include "dfu_ble_svc.h"
#include "device_manager.h"
#define IRQ_ENABLED 0x01 /**< Field identifying if an interrupt is enabled. */
#define MAX_NUMBER_INTERRUPTS 32 /**< Maximum number of interrupts available. */
static void dfu_app_reset_prepare(void); /**< Forward declare of default reset handler. */
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. */
static dfu_ble_peer_data_t m_peer_data; /**< Peer data to be used for data exchange when reseting into DFU mode. */
static dm_handle_t m_dm_handle; /**< Device Manager handle with instance id's of current BLE connection. */
static bool m_dm_handle_valid = false; /**< Variable indicating if the Device Manager handle is valid. */
/**@brief Default reset prepare handler if application hasn't registered a handler.
*/
static void dfu_app_reset_prepare(void)
{
// Reset prepare should be handled by application.
// This function can be extended to include default handling if application does not implement
// own handler.
}
/**@brief Function for disabling all interrupts before jumping from bootloader to application.
*/
static void interrupts_disable(void)
{
uint32_t interrupt_setting_mask;
uint32_t irq = 0; // We start from first interrupt, i.e. interrupt 0.
// Fetch the current interrupt settings.
interrupt_setting_mask = NVIC->ISER[0];
for (; irq < MAX_NUMBER_INTERRUPTS; irq++)
{
if (interrupt_setting_mask & (IRQ_ENABLED << irq))
{
// The interrupt was enabled, and hence disable it.
NVIC_DisableIRQ((IRQn_Type)irq);
}
}
}
/**@brief Function for providing peer information to DFU for re-establishing bonded connection in
* DFU mode.
*/
static void dfu_app_set_peer_data(void)
{
uint32_t err_code;
dm_sec_keyset_t key_set;
/** [DFU bond sharing] */
err_code = dm_distributed_keys_get(&m_dm_handle, &key_set);
APP_ERROR_CHECK(err_code);
m_peer_data.addr = key_set.keys_central.p_id_key->id_addr_info;
m_peer_data.enc_key = *((ble_gap_enc_key_t *)(key_set.keys_central.enc_key.p_enc_key));
m_peer_data.irk = key_set.keys_central.p_id_key->id_info;
err_code = dfu_ble_svc_set_peer_data(&m_peer_data);
APP_ERROR_CHECK(err_code);
/** [DFU bond sharing] */
}
/**@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);
}
void dfu_app_on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
{
switch (p_evt->ble_dfu_evt_type)
{
case BLE_DFU_START:
// Starting the bootloader - will cause reset.
bootloader_start();
break;
case BLE_DFU_VALIDATE:
case BLE_DFU_ACTIVATE_N_RESET:
case BLE_DFU_SYS_RESET:
case BLE_DFU_RECEIVE_INIT_DATA:
case BLE_DFU_RECEIVE_APP_DATA:
case BLE_DFU_PACKET_WRITE:
case BLE_DFU_PKT_RCPT_NOTIF_ENABLED:
case BLE_DFU_PKT_RCPT_NOTIF_DISABLED:
case BLE_DFU_BYTES_RECEIVED_SEND:
default:
{
// Unsupported event received from DFU Service.
// Send back BLE_DFU_RESP_VAL_NOT_SUPPORTED message to peer.
uint32_t err_code = ble_dfu_response_send(p_dfu,
BLE_DFU_START_PROCEDURE,
BLE_DFU_RESP_VAL_NOT_SUPPORTED);
APP_ERROR_CHECK(err_code);
}
break;
}
}
void dfu_app_reset_prepare_set(dfu_app_reset_prepare_t reset_prepare_func)
{
m_reset_prepare = reset_prepare_func;
}
void dfu_app_set_dm_handle(dm_handle_t const * p_dm_handle)
{
m_dm_handle_valid = false;
if (p_dm_handle != NULL)
{
m_dm_handle = *p_dm_handle;
m_dm_handle_valid = true;
}
}
/* Copyright (c) 2014 Nordic Semiconductor. All Rights Reserved.
*
* The information contained herein is property of Nordic Semiconductor ASA.
* Terms and conditions of usage are described in detail in NORDIC
* SEMICONDUCTOR STANDARD SOFTWARE LICENSE AGREEMENT.
*
* Licensees are granted free, non-transferable use of the information. NO
* WARRANTY of ANY KIND is provided. This heading must NOT be removed from
* the file.
*
*/
#include <string.h>
#include "dfu_app_handler.h"
#include "bootloader_util.h"
#include "nrf.h"
#include "nrf_sdm.h"
#include "ble_gatts.h"
#include "app_error.h"
#include "dfu_ble_svc.h"
#include "device_manager.h"
#define IRQ_ENABLED 0x01 /**< Field identifying if an interrupt is enabled. */
#define MAX_NUMBER_INTERRUPTS 32 /**< Maximum number of interrupts available. */
static void dfu_app_reset_prepare(void); /**< Forward declare of default reset handler. */
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. */
#if NEEDED
static dfu_ble_peer_data_t m_peer_data; /**< Peer data to be used for data exchange when reseting into DFU mode. */
static dm_handle_t m_dm_handle; /**< Device Manager handle with instance id's of current BLE connection. */
static bool m_dm_handle_valid = false; /**< Variable indicating if the Device Manager handle is valid. */
#endif /* NEEDED */
/**@brief Default reset prepare handler if application hasn't registered a handler.
*/
static void dfu_app_reset_prepare(void)
{
// Reset prepare should be handled by application.
// This function can be extended to include default handling if application does not implement
// own handler.
}
/**@brief Function for disabling all interrupts before jumping from bootloader to application.
*/
static void interrupts_disable(void)
{
uint32_t interrupt_setting_mask;
uint32_t irq = 0; // We start from first interrupt, i.e. interrupt 0.
// Fetch the current interrupt settings.
interrupt_setting_mask = NVIC->ISER[0];
for (; irq < MAX_NUMBER_INTERRUPTS; irq++)
{
if (interrupt_setting_mask & (IRQ_ENABLED << irq))
{
// The interrupt was enabled, and hence disable it.
NVIC_DisableIRQ((IRQn_Type)irq);
}
}
}
#if NEEDED
/**@brief Function for providing peer information to DFU for re-establishing bonded connection in
* DFU mode.
*/
static void dfu_app_set_peer_data(void)
{
uint32_t err_code;
dm_sec_keyset_t key_set;
/** [DFU bond sharing] */
err_code = dm_distributed_keys_get(&m_dm_handle, &key_set);
APP_ERROR_CHECK(err_code);
m_peer_data.addr = key_set.keys_central.p_id_key->id_addr_info;
m_peer_data.enc_key = *((ble_gap_enc_key_t *)(key_set.keys_central.enc_key.p_enc_key));
m_peer_data.irk = key_set.keys_central.p_id_key->id_info;
err_code = dfu_ble_svc_set_peer_data(&m_peer_data);
APP_ERROR_CHECK(err_code);
/** [DFU bond sharing] */
}
#endif /* NEEDED */
/**@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);
}
void dfu_app_on_dfu_evt(ble_dfu_t * p_dfu, ble_dfu_evt_t * p_evt)
{
switch (p_evt->ble_dfu_evt_type)
{
case BLE_DFU_START:
// Starting the bootloader - will cause reset.
bootloader_start();
break;
case BLE_DFU_VALIDATE:
case BLE_DFU_ACTIVATE_N_RESET:
case BLE_DFU_SYS_RESET:
case BLE_DFU_RECEIVE_INIT_DATA:
case BLE_DFU_RECEIVE_APP_DATA:
case BLE_DFU_PACKET_WRITE:
case BLE_DFU_PKT_RCPT_NOTIF_ENABLED:
case BLE_DFU_PKT_RCPT_NOTIF_DISABLED:
case BLE_DFU_BYTES_RECEIVED_SEND:
default:
{
// Unsupported event received from DFU Service.
// Send back BLE_DFU_RESP_VAL_NOT_SUPPORTED message to peer.
uint32_t err_code = ble_dfu_response_send(p_dfu,
BLE_DFU_START_PROCEDURE,
BLE_DFU_RESP_VAL_NOT_SUPPORTED);
APP_ERROR_CHECK(err_code);
}
break;
}
}
void dfu_app_reset_prepare_set(dfu_app_reset_prepare_t reset_prepare_func)
{
m_reset_prepare = reset_prepare_func;
}
#if NEEDED
void dfu_app_set_dm_handle(dm_handle_t const * p_dm_handle)
{
m_dm_handle_valid = false;
if (p_dm_handle != NULL)
{
m_dm_handle = *p_dm_handle;
m_dm_handle_valid = true;
}
}
#endif /* NEEDED */