58:de6b64cd7f21

Release 0.1.0
=============

We've achieved significant gains in power consumption: the BLE_Beacon demo now
runs at around 35uA of average current broadcasting once a second at 0dB; when
not using the radio, this demo consumes around 7uA.

Features
~~~~~~~~

- Replace initialization of high-frequency external crystal clock-source with
  the use of low-frequency clock. This brings in significant gains in power
  consumption.

- Re-implement the micro-second timer on nRF51 using the app_timer module
  (which internally uses RTC). This limits the precision of the us_Timer to
  30uS; but brings in significant gains in power consumption.

- Reduce the number of available app_timers and the event depths for app-timer
  events; this will reduce memory consumption for zero-initialized data by
  around 1K.

- Remove the call to conn_params_init() at startup. This is not mandatory; and
  was causing an unnecessary re-negotiation of connection parameters a few
  seconds into every connection.

- Reduce default transmission power level to 0dbB (was 4dbB before).

- Reduce min connection interval to 50ms and max to 500ms (previous values
  were much larger).

- Replace a few instances of use of wait() with nrf_delay_us().

- onConnection() callback now receives connection-parameters applicable to the
  new connection.

- onDataSent() callback now receives a count parameter containing the number of
  times notifications were sent out since the last callback.

- A 'reason' parameter has been added to Gap::disconnect() to indicate the
  reason for disconnection; and also to the onDisconnection callback to
  receive a reason from the remote host.

- disable the app_gpiote module by default.

Bugfixes
~~~~~~~~

- onDataWritten() callback now passes an additional parameter
  (GattServer::WriteEventCallback_t) encapsulating the update. This avoids
  having to re-fetch the updated characteristic's value attribute. It also
  fixes a bug where multiple updates to the characteristic's value-attribute
  could get clobbered if they occurred in quick succession before the
  callbacks could be processed.

Compatibility
~~~~~~~~~~~~~

Compatible with revision 0.1.0 of the BLE_API.
master
Rohit Grover 2014-09-02 16:17:54 +01:00
commit 384c84522b
19 changed files with 1116 additions and 413 deletions

View File

@ -39,13 +39,13 @@
#include "nRF51Gap.h"
#include "nRF51GattServer.h"
#include "ble_hci.h"
#if NEED_BOND_MANAGER /* disabled by default */
static void service_error_callback(uint32_t nrf_error);
#endif
extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
void app_error_handler(uint32_t error_code,
uint32_t line_num,
const uint8_t *p_file_name);
extern "C" void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name);
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name);
#if NEED_BOND_MANAGER /* disabled by default */
static error_t bond_manager_init(void);
@ -62,8 +62,40 @@ static void sys_evt_dispatch(uint32_t sys_evt)
error_t btle_init(void)
{
APP_TIMER_INIT(0, 8, 5, false);
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, false);
const bool useScheduler = false;
SOFTDEVICE_HANDLER_INIT(NRF_CLOCK_LFCLKSRC_XTAL_20_PPM, useScheduler);
// Enable BLE stack
/**
* Using this call, the application can select whether to include the
* Service Changed characteristic in the GATT Server. The default in all
* previous releases has been to include the Service Changed characteristic,
* but this affects how GATT clients behave. Specifically, it requires
* clients to subscribe to this attribute and not to cache attribute handles
* between connections unless the devices are bonded. If the application
* does not need to change the structure of the GATT server attributes at
* runtime this adds unnecessary complexity to the interaction with peer
* clients. If the SoftDevice is enabled with the Service Changed
* Characteristics turned off, then clients are allowed to cache attribute
* handles making applications simpler on both sides.
*/
static const bool IS_SRVC_CHANGED_CHARACT_PRESENT = false;
ble_enable_params_t enableParams = {
.gatts_enable_params = {
.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT
}
};
if (sd_ble_enable(&enableParams) != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
ble_gap_addr_t addr;
if (sd_ble_gap_address_get(&addr) != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
if (sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr) != NRF_SUCCESS) {
return ERROR_INVALID_PARAM;
}
ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));
@ -82,14 +114,17 @@ static void btle_handler(ble_evt_t *p_ble_evt)
#if NEED_BOND_MANAGER /* disabled by default */
ble_bondmngr_on_ble_evt(p_ble_evt);
#endif
#if SDK_CONN_PARAMS_MODULE_ENABLE
ble_conn_params_on_ble_evt(p_ble_evt);
#endif
/* Custom event handler */
switch (p_ble_evt->header.evt_id) {
case BLE_GAP_EVT_CONNECTED: {
Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
nRF51Gap::getInstance().setConnectionHandle(handle);
nRF51Gap::getInstance().processHandleSpecificEvent(GapEvents::GAP_EVENT_CONNECTED, handle);
const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params));
nRF51Gap::getInstance().processConnectionEvent(handle, params);
break;
}
@ -101,7 +136,10 @@ static void btle_handler(ble_evt_t *p_ble_evt)
#if NEED_BOND_MANAGER /* disabled by default */
ASSERT_STATUS_RET_VOID ( ble_bondmngr_bonded_centrals_store());
#endif
nRF51Gap::getInstance().processHandleSpecificEvent(GapEvents::GAP_EVENT_DISCONNECTED, handle);
if (p_ble_evt->evt.gap_evt.params.disconnected.reason == BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION) {
nRF51Gap::getInstance().processDisconnectionEvent(handle, Gap::LOCAL_HOST_TERMINATED_CONNECTION);
}
break;
}
@ -117,11 +155,8 @@ static void btle_handler(ble_evt_t *p_ble_evt)
sec_params.min_key_size = CFG_BLE_SEC_PARAM_MIN_KEY_SIZE;
sec_params.max_key_size = CFG_BLE_SEC_PARAM_MAX_KEY_SIZE;
ASSERT_STATUS_RET_VOID(
sd_ble_gap_sec_params_reply(nRF51Gap::getInstance().
getConnectionHandle(),
BLE_GAP_SEC_STATUS_SUCCESS,
&sec_params));
ASSERT_STATUS_RET_VOID(sd_ble_gap_sec_params_reply(nRF51Gap::getInstance().getConnectionHandle(),
BLE_GAP_SEC_STATUS_SUCCESS, &sec_params));
}
break;

View File

@ -20,7 +20,9 @@
#include "ble_conn_params.h"
static inline uint32_t msec_to_1_25msec(uint32_t interval_ms) ATTR_ALWAYS_INLINE ATTR_CONST;
#if SDK_CONN_PARAMS_MODULE_ENABLE
static void error_callback(uint32_t nrf_error);
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
/**************************************************************************/
/*!
@ -46,6 +48,11 @@ error_t btle_gap_init(void)
ASSERT_STATUS( sd_ble_gap_ppcp_set(&gap_conn_params));
ASSERT_STATUS( sd_ble_gap_tx_power_set(CFG_BLE_TX_POWER_LEVEL));
/**
* Call to conn_params_init() is not necessary; and so is disabled by default.
* This API should be exposed to the user to be invoked when necessary.
*/
#if SDK_CONN_PARAMS_MODULE_ENABLE
/* Connection Parameters */
enum {
FIRST_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER),
@ -65,6 +72,7 @@ error_t btle_gap_init(void)
cp_init.error_handler = error_callback;
ASSERT_STATUS ( ble_conn_params_init(&cp_init));
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
return ERROR_NONE;
}
@ -84,7 +92,9 @@ static inline uint32_t msec_to_1_25msec(uint32_t interval_ms)
return (interval_ms * 4) / 5;
}
#if SDK_CONN_PARAMS_MODULE_ENABLE
static void error_callback(uint32_t nrf_error)
{
ASSERT_STATUS_RET_VOID( nrf_error );
}
#endif // SDK_CONN_PARAMS_MODULE_ENABLE

View File

@ -23,8 +23,8 @@
* structures involved in maintaining a local cache of 128-bit UUIDs.
*/
typedef struct {
LongUUID_t uuid;
uint8_t type;
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
@ -40,7 +40,7 @@ converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES];
* @return true if a match is found.
*/
static bool
lookupConvertedUUIDTable(const LongUUID_t uuid, uint8_t *recoveredType)
lookupConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t *recoveredType)
{
unsigned i;
for (i = 0; i < uuidTableEntries; i++) {
@ -56,7 +56,7 @@ lookupConvertedUUIDTable(const LongUUID_t uuid, uint8_t *recoveredType)
}
static void
addToConvertedUUIDTable(const LongUUID_t uuid, uint8_t type)
addToConvertedUUIDTable(const LongUUIDBytes_t uuid, uint8_t type)
{
if (uuidTableEntries == UUID_TABLE_MAX_ENTRIES) {
return; /* recovery needed; or at least the user should be
@ -157,7 +157,7 @@ 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)
{
LongUUID_t uuid_base_le;
LongUUIDBytes_t uuid_base_le;
/* Reverse the bytes since ble_uuid128_t is LSB */
for (uint8_t i = 0; i<16; i++) {

View File

@ -54,7 +54,7 @@
#ifdef __cplusplus
extern "C" {
extern "C" {
#endif
#define CSI_CODE(seq) "\33[" seq
@ -95,7 +95,7 @@
#define ANSI_BG_DEFAULT CSI_SGR(49)
#ifdef __cplusplus
}
}
#endif
#endif /* _TUSB_ANSI_ESC_CODE_H_ */

View File

@ -19,6 +19,7 @@
#include "nrf_soc.h"
#include "btle/btle.h"
#include "nrf_delay.h"
/**
* The singleton which represents the nRF51822 transport for the BLEDevice.
@ -133,10 +134,10 @@ ble_error_t nRF51822n::init(void)
/**************************************************************************/
ble_error_t nRF51822n::reset(void)
{
wait(0.5);
nrf_delay_us(500000);
/* Wait for the radio to come back up */
wait(1);
nrf_delay_us(1000000);
return BLE_ERROR_NONE;
}

View File

@ -168,8 +168,7 @@ ble_error_t nRF51Gap::startAdvertising(const GapAdvertisingParams &params)
adv_para.interval = params.getInterval(); // advertising interval (in units of 0.625 ms)
adv_para.timeout = params.getTimeout();
ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para),
BLE_ERROR_PARAM_OUT_OF_RANGE);
ASSERT(ERROR_NONE == sd_ble_gap_adv_start(&adv_para), BLE_ERROR_PARAM_OUT_OF_RANGE);
state.advertising = 1;
@ -218,14 +217,23 @@ ble_error_t nRF51Gap::stopAdvertising(void)
@endcode
*/
/**************************************************************************/
ble_error_t nRF51Gap::disconnect(void)
ble_error_t nRF51Gap::disconnect(DisconnectionReason_t reason)
{
state.advertising = 0;
state.connected = 0;
uint8_t code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION;
switch (reason) {
case REMOTE_USER_TERMINATED_CONNECTION:
code = BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION;
break;
case CONN_INTERVAL_UNACCEPTABLE:
code = BLE_HCI_CONN_INTERVAL_UNACCEPTABLE;
break;
}
/* Disconnect if we are connected to a central device */
ASSERT_INT(ERROR_NONE,
sd_ble_gap_disconnect(m_connectionHandle, BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION), BLE_ERROR_PARAM_OUT_OF_RANGE);
ASSERT_INT(ERROR_NONE, sd_ble_gap_disconnect(m_connectionHandle, code), BLE_ERROR_PARAM_OUT_OF_RANGE);
return BLE_ERROR_NONE;
}
@ -252,8 +260,7 @@ ble_error_t nRF51Gap::updateConnectionParams(Handle_t handle, const ConnectionPa
{
uint32_t rc;
rc = sd_ble_gap_conn_param_update(handle,
reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams)));
rc = sd_ble_gap_conn_param_update(handle, reinterpret_cast<ble_gap_conn_params_t *>(const_cast<ConnectionParams_t*>(newParams)));
if (rc == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
@ -314,3 +321,42 @@ ble_error_t nRF51Gap::setAddress(addr_type_t type, const uint8_t address[6])
return BLE_ERROR_NONE;
}
ble_error_t nRF51Gap::setDeviceName(const uint8_t *deviceName)
{
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
ble_error_t nRF51Gap::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
{
if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
ble_error_t nRF51Gap::setAppearance(uint16_t appearance)
{
if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
ble_error_t nRF51Gap::getAppearance(uint16_t *appearanceP)
{
if (sd_ble_gap_appearance_get(appearanceP)) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}

View File

@ -45,7 +45,12 @@ public:
const GapAdvertisingData &);
virtual ble_error_t startAdvertising(const GapAdvertisingParams &);
virtual ble_error_t stopAdvertising(void);
virtual ble_error_t disconnect(void);
virtual ble_error_t disconnect(DisconnectionReason_t reason);
virtual ble_error_t setDeviceName(const uint8_t *deviceName);
virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP);
virtual ble_error_t setAppearance(uint16_t appearance);
virtual ble_error_t getAppearance(uint16_t *appearanceP);
void setConnectionHandle(uint16_t con_handle);
uint16_t getConnectionHandle(void);

View File

@ -77,7 +77,7 @@ ble_error_t nRF51GattServer::addService(GattService &service)
p_characteristics[characteristicCount++] = p_char;
p_char->getValueAttribute().setHandle(charHandle);
/* Add optional descriptors if any */
/* ToDo: Make sure we don't overflow the array */
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
@ -95,10 +95,9 @@ ble_error_t nRF51GattServer::addService(GattService &service)
BLE_ERROR_PARAM_OUT_OF_RANGE );
uint16_t descHandle = descriptorCount;
p_descriptors[descriptorCount++] = p_desc;
p_descriptors[descriptorCount++] = p_desc;
p_desc->setHandle(descHandle);
}
}
serviceCount++;
@ -213,45 +212,6 @@ ble_error_t nRF51GattServer::updateValue(uint16_t charHandle, uint8_t buffer[],
return BLE_ERROR_NONE;
}
ble_error_t nRF51GattServer::setDeviceName(const uint8_t *deviceName)
{
ble_gap_conn_sec_mode_t sec_mode;
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
if (sd_ble_gap_device_name_set(&sec_mode, deviceName, strlen((const char *)deviceName)) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
ble_error_t nRF51GattServer::getDeviceName(uint8_t *deviceName, unsigned *lengthP)
{
if (sd_ble_gap_device_name_get(deviceName, (uint16_t *)lengthP) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
ble_error_t nRF51GattServer::setAppearance(uint16_t appearance)
{
if (sd_ble_gap_appearance_set(appearance) == NRF_SUCCESS) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
ble_error_t nRF51GattServer::getAppearance(uint16_t *appearanceP)
{
if (sd_ble_gap_appearance_get(appearanceP)) {
return BLE_ERROR_NONE;
} else {
return BLE_ERROR_PARAM_OUT_OF_RANGE;
}
}
/**************************************************************************/
/*!
@brief Callback handler for events getting pushed up from the SD
@ -259,52 +219,52 @@ ble_error_t nRF51GattServer::getAppearance(uint16_t *appearanceP)
/**************************************************************************/
void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt)
{
uint16_t handle_value;
GattServerEvents::gattEvent_t event;
uint16_t handle_value;
GattServerEvents::gattEvent_t eventType;
const ble_gatts_evt_t *gattsEventP = &p_ble_evt->evt.gatts_evt;
switch (p_ble_evt->header.evt_id) {
case BLE_GATTS_EVT_WRITE:
/* There are 2 use case here: Values being updated & CCCD (indicate/notify) enabled */
/* 1.) Handle CCCD changes */
handle_value = p_ble_evt->evt.gatts_evt.params.write.handle;
handle_value = gattsEventP->params.write.handle;
for (uint8_t i = 0; i<characteristicCount; i++) {
if ((p_characteristics[i]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY)) &&
(nrfCharacteristicHandles[i].cccd_handle == handle_value)) {
uint16_t cccd_value =
(p_ble_evt->evt.gatts_evt.params.write.data[1] << 8) |
p_ble_evt->evt.gatts_evt.params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
(gattsEventP->params.write.data[1] << 8) |
gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
if (((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) ||
((p_characteristics[i]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) {
event = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
} else {
event = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
}
handleEvent(event, i);
handleEvent(eventType, i);
return;
}
}
/* 2.) Changes to the characteristic value will be handled with other events below */
event = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
break;
case BLE_EVT_TX_COMPLETE:
for (uint8_t i = 0; i<p_ble_evt->evt.common_evt.params.tx_complete.count; i++){
handleEvent(GattServerEvents::GATT_EVENT_DATA_SENT);
}
return;
case BLE_GATTS_EVT_HVC:
/* Indication confirmation received */
event = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
handle_value = p_ble_evt->evt.gatts_evt.params.hvc.handle;
eventType = GattServerEvents::GATT_EVENT_CONFIRMATION_RECEIVED;
handle_value = gattsEventP->params.hvc.handle;
break;
case BLE_EVT_TX_COMPLETE: {
handleDataSentEvent(p_ble_evt->evt.common_evt.params.tx_complete.count);
return;
}
case BLE_GATTS_EVT_SYS_ATTR_MISSING:
sd_ble_gatts_sys_attr_set(p_ble_evt->evt.gatts_evt.conn_handle, NULL, 0);
sd_ble_gatts_sys_attr_set(gattsEventP->conn_handle, NULL, 0);
return;
default:
@ -314,8 +274,21 @@ void nRF51GattServer::hwCallback(ble_evt_t *p_ble_evt)
/* Find index (charHandle) in the pool */
for (uint8_t i = 0; i<characteristicCount; i++) {
if (nrfCharacteristicHandles[i].value_handle == handle_value) {
handleEvent(event, i);
break;
switch (eventType) {
case GattServerEvents::GATT_EVENT_DATA_WRITTEN: {
GattCharacteristicWriteCBParams cbParams = {
.op = static_cast<GattCharacteristicWriteCBParams::Type>(gattsEventP->params.write.op),
.offset = gattsEventP->params.write.offset,
.len = gattsEventP->params.write.len,
.data = gattsEventP->params.write.data
};
handleDataWrittenEvent(i, &cbParams);
break;
}
default:
handleEvent(eventType, i);
break;
}
}
}
}

View File

@ -39,11 +39,6 @@ public:
virtual ble_error_t readValue(uint16_t handle, uint8_t buffer[], uint16_t *const lengthP);
virtual ble_error_t updateValue(uint16_t, uint8_t[], uint16_t, bool localOnly = false);
virtual ble_error_t setDeviceName(const uint8_t *deviceName);
virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP);
virtual ble_error_t setAppearance(uint16_t appearance);
virtual ble_error_t getAppearance(uint16_t *appearanceP);
/* nRF51 Functions */
void eventCallback(void);
void hwCallback(ble_evt_t *p_ble_evt);

View File

@ -0,0 +1,284 @@
/* Copyright (c) 2012 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 "app_button.h"
#include <string.h>
#include "nordic_common.h"
#include "app_util.h"
#include "app_gpiote.h"
#include "app_timer.h"
#include "app_error.h"
static app_button_cfg_t * mp_buttons = NULL; /**< Button configuration. */
static uint8_t m_button_count; /**< Number of configured buttons. */
static uint32_t m_detection_delay; /**< Delay before a button is reported as pushed. */
static app_button_evt_schedule_func_t m_evt_schedule_func; /**< Pointer to function for propagating button events to the scheduler. */
static app_gpiote_user_id_t m_gpiote_user_id; /**< GPIOTE user id for buttons module. */
static app_timer_id_t m_detection_delay_timer_id; /**< Polling timer id. */
static pin_transition_t m_pin_transition; /**< pin transaction direction. */
/**@brief Function for executing the application button handler for specified button.
*
* @param[in] p_btn Button that has been pushed.
*/
static void button_handler_execute(app_button_cfg_t * p_btn, uint32_t transition)
{
if (m_evt_schedule_func != NULL)
{
uint32_t err_code = m_evt_schedule_func(p_btn->button_handler, p_btn->pin_no,transition);
APP_ERROR_CHECK(err_code);
}
else
{
if(transition == APP_BUTTON_PUSH)
{
p_btn->button_handler(p_btn->pin_no, APP_BUTTON_PUSH);
}
else if(transition == APP_BUTTON_RELEASE)
{
p_btn->button_handler(p_btn->pin_no, APP_BUTTON_RELEASE);
}
}
}
/**@brief Function for handling the timeout that delays reporting buttons as pushed.
*
* @details The detection_delay_timeout_handler(...) is a call-back issued from the app_timer
* module. It is called with the p_context parameter. The p_context parameter is
* provided to the app_timer module when a timer is started, using the call
* @ref app_timer_start. On @ref app_timer_start the p_context will be holding the
* currently pressed buttons.
*
* @param[in] p_context Pointer used for passing information app_start_timer() was called.
* In the app_button module the p_context holds information on pressed
* buttons.
*/
static void detection_delay_timeout_handler(void * p_context)
{
uint32_t err_code;
uint32_t current_state_pins;
// Get current state of pins.
err_code = app_gpiote_pins_state_get(m_gpiote_user_id, &current_state_pins);
if (err_code != NRF_SUCCESS)
{
return;
}
uint8_t i;
// Pushed button(s) detected, execute button handler(s).
for (i = 0; i < m_button_count; i++)
{
app_button_cfg_t * p_btn = &mp_buttons[i];
if (((m_pin_transition.high_to_low & (1 << p_btn->pin_no)) != 0) && (p_btn->button_handler != NULL))
{
//If it's active high then going from high to low was a release of the button.
if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH)
{
button_handler_execute(p_btn, APP_BUTTON_RELEASE);
}
//If it's active low then going from high to low was a push of the button.
else
{
button_handler_execute(p_btn, APP_BUTTON_PUSH);
}
}
else if (((m_pin_transition.low_to_high & (1 << p_btn->pin_no)) != 0) && (p_btn->button_handler != NULL))
{
//If it's active high then going from low to high was a push of the button.
if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH)
{
button_handler_execute(p_btn,APP_BUTTON_PUSH);
}
//If it's active low then going from low to high was a release of the button.
else
{
button_handler_execute(p_btn,APP_BUTTON_RELEASE);
}
}
}
}
/**@brief Function for handling the GPIOTE event.
*
* @details Saves the current status of the button pins, and starts a timer. If the timer is already
* running, it will be restarted.
*
* @param[in] event_pins_low_to_high Mask telling which pin(s) had a low to high transition.
* @param[in] event_pins_high_to_low Mask telling which pin(s) had a high to low transition.
*/
static void gpiote_event_handler(uint32_t event_pins_low_to_high, uint32_t event_pins_high_to_low)
{
uint32_t err_code;
// Start detection timer. If timer is already running, the detection period is restarted.
// NOTE: Using the p_context parameter of app_timer_start() to transfer the pin states to the
// timeout handler (by casting event_pins_mask into the equally sized void * p_context
// parameter).
STATIC_ASSERT(sizeof(void *) == sizeof(uint32_t));
err_code = app_timer_stop(m_detection_delay_timer_id);
if (err_code != NRF_SUCCESS)
{
// The impact in app_button of the app_timer queue running full is losing a button press.
// The current implementation ensures that the system will continue working as normal.
return;
}
m_pin_transition.low_to_high = event_pins_low_to_high;
m_pin_transition.high_to_low = event_pins_high_to_low;
err_code = app_timer_start(m_detection_delay_timer_id,
m_detection_delay,
(void *)(event_pins_low_to_high | event_pins_high_to_low));
if (err_code != NRF_SUCCESS)
{
// The impact in app_button of the app_timer queue running full is losing a button press.
// The current implementation ensures that the system will continue working as normal.
}
}
uint32_t app_button_init(app_button_cfg_t * p_buttons,
uint8_t button_count,
uint32_t detection_delay,
app_button_evt_schedule_func_t evt_schedule_func)
{
uint32_t err_code;
if (detection_delay < APP_TIMER_MIN_TIMEOUT_TICKS)
{
return NRF_ERROR_INVALID_PARAM;
}
// Save configuration.
mp_buttons = p_buttons;
m_button_count = button_count;
m_detection_delay = detection_delay;
m_evt_schedule_func = evt_schedule_func;
// Configure pins.
uint32_t pins_transition_mask = 0;
while (button_count--)
{
app_button_cfg_t * p_btn = &p_buttons[button_count];
// Configure pin.
nrf_gpio_cfg_input(p_btn->pin_no, p_btn->pull_cfg);
// Build GPIOTE user registration masks.
pins_transition_mask |= (1 << p_btn->pin_no);
}
// Register button module as a GPIOTE user.
err_code = app_gpiote_user_register(&m_gpiote_user_id,
pins_transition_mask,
pins_transition_mask,
gpiote_event_handler);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Create polling timer.
return app_timer_create(&m_detection_delay_timer_id,
APP_TIMER_MODE_SINGLE_SHOT,
detection_delay_timeout_handler);
}
uint32_t app_button_enable(void)
{
if (mp_buttons == NULL)
{
return NRF_ERROR_INVALID_STATE;
}
return app_gpiote_user_enable(m_gpiote_user_id);
}
uint32_t app_button_disable(void)
{
uint32_t err_code;
if (mp_buttons == NULL)
{
return NRF_ERROR_INVALID_STATE;
}
err_code = app_gpiote_user_disable(m_gpiote_user_id);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
// Make sure polling timer is not running.
return app_timer_stop(m_detection_delay_timer_id);
}
uint32_t app_button_is_pushed(uint8_t pin_no, bool * p_is_pushed)
{
uint32_t err_code;
uint32_t active_pins;
app_button_cfg_t * p_btn = &mp_buttons[pin_no];
if (mp_buttons == NULL)
{
return NRF_ERROR_INVALID_STATE;
}
err_code = app_gpiote_pins_state_get(m_gpiote_user_id, &active_pins);
if (err_code != NRF_SUCCESS)
{
return err_code;
}
if(p_btn->active_state == APP_BUTTON_ACTIVE_LOW)
{
// If the pin is active low, then the pin being high means it is not pushed.
if(((active_pins >> pin_no) & 0x01))
{
*p_is_pushed = false;
}
else
{
*p_is_pushed = true;
}
}
else if(p_btn->active_state == APP_BUTTON_ACTIVE_HIGH)
{
// If the pin is active high, then the pin being high means it is pushed.
if(((active_pins >> pin_no) & 0x01))
{
*p_is_pushed = true;
}
else
{
*p_is_pushed = false;
}
}
return NRF_SUCCESS;
}

View File

@ -10,6 +10,8 @@
*
*/
#if NEED_APP_GPIOTE /* disabled by default */
#include "app_gpiote.h"
#include <stdlib.h>
#include <string.h>
@ -358,3 +360,5 @@ uint32_t app_gpiote_disable_interrupts(void)
return NRF_ERROR_NOT_SUPPORTED;
}
#endif // SVCALL_AS_NORMAL_FUNCTION || SER_CONNECTIVITY
#endif // #if NEED_APP_GPIOTE

View File

@ -16,8 +16,7 @@
#include "nrf51_bitfields.h"
#include "nrf_soc.h"
#include "app_error.h"
//#include "nrf_delay.h"
#include "mbed.h"
#include "nrf_delay.h"
#include "app_util.h"
#include "app_util_platform.h"
@ -30,8 +29,6 @@
// (e.g. by using guard/trigger flags).
STATIC_ASSERT(RTC1_IRQ_PRI == SWI0_IRQ_PRI);
#define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
#define APP_HIGH_USER_ID 0 /**< User Id for the Application High "user". */
#define APP_LOW_USER_ID 1 /**< User Id for the Application Low "user". */
#define THREAD_MODE_USER_ID 2 /**< User Id for the Thread Mode "user". */
@ -125,7 +122,6 @@ STATIC_ASSERT(sizeof(timer_user_t) % 4 == 0);
*/
typedef uint32_t timer_user_id_t;
#define TIMER_NULL ((app_timer_id_t)(0 - 1)) /**< Invalid timer id. */
#define CONTEXT_QUEUE_SIZE_MAX (2) /**< Timer internal elapsed ticks queue size. */
static uint8_t m_node_array_size; /**< Size of timer node array. */
@ -138,6 +134,8 @@ static uint32_t m_ticks_elapsed[CONTEXT_QUEUE_SIZE_MAX];
static uint8_t m_ticks_elapsed_q_read_ind; /**< Timer internal elapsed ticks queue read index. */
static uint8_t m_ticks_elapsed_q_write_ind; /**< Timer internal elapsed ticks queue write index. */
static app_timer_evt_schedule_func_t m_evt_schedule_func; /**< Pointer to function for propagating timeout events to the scheduler. */
static bool m_rtc1_running; /**< Boolean indicating if RTC1 is running. */
static volatile uint64_t overflowBits; /**< The upper 40 bits of the 64-bit value returned by cnt_get() */
/**@brief Function for initializing the RTC1 counter.
@ -155,14 +153,20 @@ static void rtc1_init(uint32_t prescaler)
*/
static void rtc1_start(void)
{
if (m_rtc1_running) {
return;
}
NRF_RTC1->EVTENSET = RTC_EVTEN_COMPARE0_Msk;
NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk;
NRF_RTC1->INTENSET = RTC_INTENSET_COMPARE0_Msk | RTC_INTENSET_OVRFLW_Msk;
NVIC_ClearPendingIRQ(RTC1_IRQn);
NVIC_EnableIRQ(RTC1_IRQn);
NRF_RTC1->TASKS_START = 1;
wait(0.0000001 * MAX_RTC_TASKS_DELAY);
nrf_delay_us(MAX_RTC_TASKS_DELAY);
m_rtc1_running = true;
}
@ -170,13 +174,23 @@ static void rtc1_start(void)
*/
static void rtc1_stop(void)
{
if (!m_rtc1_running) {
return;
}
NVIC_DisableIRQ(RTC1_IRQn);
NRF_RTC1->EVTENCLR = RTC_EVTEN_COMPARE0_Msk;
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk;
NRF_RTC1->INTENCLR = RTC_INTENSET_COMPARE0_Msk | RTC_INTENSET_OVRFLW_Msk;
NRF_RTC1->TASKS_STOP = 1;
wait(0.0000001 * MAX_RTC_TASKS_DELAY);
nrf_delay_us(MAX_RTC_TASKS_DELAY);
NRF_RTC1->TASKS_CLEAR = 1;
m_ticks_latest = 0;
nrf_delay_us(MAX_RTC_TASKS_DELAY);
m_rtc1_running = false;
}
@ -296,6 +310,12 @@ static void timer_list_remove(app_timer_id_t timer_id)
if (previous == current)
{
m_timer_id_head = mp_nodes[m_timer_id_head].next;
// No more timers in the list. Disable RTC1.
if (m_timer_id_head == TIMER_NULL)
{
rtc1_stop();
}
}
// Remaining timeout between next timeout
@ -673,7 +693,7 @@ static void compare_reg_update(app_timer_id_t timer_id_head_old)
uint32_t cc = m_ticks_latest;
uint32_t ticks_elapsed = ticks_diff_get(pre_counter_val, cc) + RTC_COMPARE_OFFSET_MIN;
if (timer_id_head_old == TIMER_NULL)
if (!m_rtc1_running)
{
// No timers were already running, start RTC
rtc1_start();
@ -686,11 +706,7 @@ static void compare_reg_update(app_timer_id_t timer_id_head_old)
uint32_t post_counter_val = rtc1_counter_get();
if (
(ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN)
>
ticks_diff_get(cc, pre_counter_val)
)
if ((ticks_diff_get(post_counter_val, pre_counter_val) + RTC_COMPARE_OFFSET_MIN) > ticks_diff_get(cc, pre_counter_val))
{
// When this happens the COMPARE event may not be triggered by the RTC.
// The nRF51 Series User Specification states that if the COUNTER value is N
@ -897,6 +913,9 @@ extern "C" void RTC1_IRQHandler(void)
NRF_RTC1->EVENTS_COMPARE[2] = 0;
NRF_RTC1->EVENTS_COMPARE[3] = 0;
NRF_RTC1->EVENTS_TICK = 0;
if (NRF_RTC1->EVENTS_OVRFLW) {
overflowBits += (1 << 24);
}
NRF_RTC1->EVENTS_OVRFLW = 0;
// Check for expired timers
@ -979,6 +998,7 @@ uint32_t app_timer_init(uint32_t prescaler,
NVIC_EnableIRQ(SWI0_IRQn);
rtc1_init(prescaler);
rtc1_start();
m_ticks_latest = rtc1_counter_get();
@ -1115,9 +1135,9 @@ uint32_t app_timer_stop_all(void)
}
uint32_t app_timer_cnt_get(uint32_t * p_ticks)
uint32_t app_timer_cnt_get(uint64_t * p_ticks)
{
*p_ticks = rtc1_counter_get();
*p_ticks = overflowBits | rtc1_counter_get();
return NRF_SUCCESS;
}

File diff suppressed because it is too large Load Diff

View File

@ -62,6 +62,8 @@ extern "C" {
#define APP_TIMER_USER_SIZE 8 /**< Size of app_timer.timer_user_t (only for use inside APP_TIMER_BUF_SIZE()). */
#define APP_TIMER_INT_LEVELS 3 /**< Number of interrupt levels from where timer operations may be initiated (only for use inside APP_TIMER_BUF_SIZE()). */
#define MAX_RTC_COUNTER_VAL 0x00FFFFFF /**< Maximum value of the RTC counter. */
/**@brief Compute number of bytes required to hold the application timer data structures.
*
* @param[in] MAX_TIMERS Maximum number of timers that can be created at any given time.
@ -106,6 +108,8 @@ extern "C" {
/**@brief Timer id type. */
typedef uint32_t app_timer_id_t;
#define TIMER_NULL ((app_timer_id_t)(0 - 1)) /**< Invalid timer id. */
/**@brief Application timeout handler type. */
typedef void (*app_timer_timeout_handler_t)(void * p_context);
@ -249,13 +253,14 @@ uint32_t app_timer_stop(app_timer_id_t timer_id);
*/
uint32_t app_timer_stop_all(void);
/**@brief Function for returning the current value of the RTC1 counter.
/**@brief Function for returning the current value of the RTC1 counter. The
* value includes overflow bits to extend the range to 64-bits.
*
* @param[out] p_ticks Current value of the RTC1 counter.
*
* @retval NRF_SUCCESS Counter was successfully read.
*/
uint32_t app_timer_cnt_get(uint32_t * p_ticks);
uint32_t app_timer_cnt_get(uint64_t * p_ticks);
/**@brief Function for computing the difference between two RTC1 counter values.
*

View File

@ -164,7 +164,7 @@ typedef union
*/
typedef struct
{
ble_gatts_enable_params_t gatts_enable_params; /**< GATTS init options @ref ble_gatts_enable_params_t. */
ble_gatts_enable_params_t gatts_enable_params; /**< GATTS init options @ref ble_gatts_enable_params_t. */
} ble_enable_params_t;
/** @} */
@ -188,16 +188,16 @@ SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(ble_enable_params_t * p_ble_enable
* @param[in] p_dest Pointer to buffer to be filled in with an event, or NULL to retrieve the event length. This buffer <b>must be 4-byte aligned in memory</b>.
* @param[in, out] p_len Pointer the length of the buffer, on return it is filled with the event length.
*
* @details This call allows the application to pull a BLE event from the BLE stack. The application is signalled that an event is
* @details This call allows the application to pull a BLE event from the BLE stack. The application is signalled that an event is
* available from the BLE Stack by the triggering of the SD_EVT_IRQn interrupt (mapped to IRQ 22).
* The application is free to choose whether to call this function from thread mode (main context) or directly from the Interrupt Service Routine
* that maps to SD_EVT_IRQn. In any case however, and because the BLE stack runs at a higher priority than the application, this function should be called
* in a loop (until @ref NRF_ERROR_NOT_FOUND is returned) every time SD_EVT_IRQn is raised to ensure that all available events are pulled from the stack.
* in a loop (until @ref NRF_ERROR_NOT_FOUND is returned) every time SD_EVT_IRQn is raised to ensure that all available events are pulled from the stack.
* Failure to do so could potentially leave events in the internal queue without the application being aware of this fact.
* Sizing the p_dest buffer is equally important, since the application needs to provide all the memory necessary for the event to be copied into
* application memory. If the buffer provided is not large enough to fit the entire contents of the event, @ref NRF_ERROR_DATA_SIZE will be returned
* and the application can then call again with a larger buffer size.
* Please note that because of the variable length nature of some events, sizeof(ble_evt_t) will not always be large enough to fit certain events,
* Please note that because of the variable length nature of some events, sizeof(ble_evt_t) will not always be large enough to fit certain events,
* and so it is the application's responsability to provide an amount of memory large enough so that the relevant event is copied in full.
* The application may "peek" the event length by providing p_dest as a NULL pointer and inspecting the value of *p_len upon return.
*
@ -219,7 +219,7 @@ SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t* p_dest, uint16_t *p_len
* The application has two options to handle its own application transmission buffers:
* - Use a simple arithmetic calculation: at boot time the application should use this function
* to find out the total amount of buffers available to it and store it in a variable.
* Every time a packet that consumes an application buffer is sent using any of the
* Every time a packet that consumes an application buffer is sent using any of the
* exposed functions in this BLE API, the application should decrement that variable.
* Conversely, whenever a @ref BLE_EVT_TX_COMPLETE event is received by the application
* it should retrieve the count field in such event and add that number to the same
@ -228,11 +228,11 @@ SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t* p_dest, uint16_t *p_len
* application packets available in the BLE stack's internal buffers, and therefore
* it can know with certainty whether it is possible to send more data or it has to
* wait for a @ref BLE_EVT_TX_COMPLETE event before it proceeds.
* - Choose to simply not keep track of available buffers at all, and instead handle the
* @ref BLE_ERROR_NO_TX_BUFFERS error by queueing the packet to be transmitted and
* - Choose to simply not keep track of available buffers at all, and instead handle the
* @ref BLE_ERROR_NO_TX_BUFFERS error by queueing the packet to be transmitted and
* try again as soon as a @ref BLE_EVT_TX_COMPLETE event arrives.
*
* The API functions that <b>may</b> consume an application buffer depending on
* The API functions that <b>may</b> consume an application buffer depending on
* the parameters supplied to them can be found below:
*
* - @ref sd_ble_gattc_write (write witout response only)
@ -253,15 +253,15 @@ SVCALL(SD_BLE_TX_BUFFER_COUNT_GET, uint32_t, sd_ble_tx_buffer_count_get(uint8_t*
* @details This call enables the application to add a vendor specific UUID to the BLE stack's table,
* for later use all other modules and APIs. This then allows the application to use the shorter,
* 24-bit @ref ble_uuid_t format when dealing with both 16-bit and 128-bit UUIDs without having to
* check for lengths and having split code paths. The way that this is accomplished is by extending the
* grouping mechanism that the Bluetooth SIG standard base UUID uses for all other 128-bit UUIDs. The
* type field in the @ref ble_uuid_t structure is an index (relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN)
* to the table populated by multiple calls to this function, and the uuid field in the same structure
* contains the 2 bytes at indices 12 and 13. The number of possible 128-bit UUIDs available to the
* application is therefore the number of Vendor Specific UUIDs added with the help of this function times 65536,
* check for lengths and having split code paths. The way that this is accomplished is by extending the
* grouping mechanism that the Bluetooth SIG standard base UUID uses for all other 128-bit UUIDs. The
* type field in the @ref ble_uuid_t structure is an index (relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN)
* to the table populated by multiple calls to this function, and the uuid field in the same structure
* contains the 2 bytes at indices 12 and 13. The number of possible 128-bit UUIDs available to the
* application is therefore the number of Vendor Specific UUIDs added with the help of this function times 65536,
* although restricted to modifying bytes 12 and 13 for each of the entries in the supplied array.
*
* @note Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by
* @note Bytes 12 and 13 of the provided UUID will not be used internally, since those are always replaced by
* the 16-bit uuid field in @ref ble_uuid_t.
*
*
@ -278,11 +278,11 @@ SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const * co
/** @brief Decode little endian raw UUID bytes (16-bit or 128-bit) into a 24 bit @ref ble_uuid_t structure.
*
* @details The raw UUID bytes excluding bytes 12 and 13 (i.e. bytes 0-11 and 14-15) of p_uuid_le are compared
* to the corresponding ones in each entry of the table of vendor specific UUIDs pouplated with @ref sd_ble_uuid_vs_add
* to look for a match. If there is such a match, bytes 12 and 13 are returned as p_uuid->uuid and the index
* relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN as p_uuid->type.
*
* @details The raw UUID bytes excluding bytes 12 and 13 (i.e. bytes 0-11 and 14-15) of p_uuid_le are compared
* to the corresponding ones in each entry of the table of vendor specific UUIDs pouplated with @ref sd_ble_uuid_vs_add
* to look for a match. If there is such a match, bytes 12 and 13 are returned as p_uuid->uuid and the index
* relative to @ref BLE_UUID_TYPE_VENDOR_BEGIN as p_uuid->type.
*
* @note If the UUID length supplied is 2, then the type set by this call will always be @ref BLE_UUID_TYPE_BLE.
*
@ -294,7 +294,7 @@ SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const * co
* @return @ref NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
* @return @ref NRF_ERROR_INVALID_LENGTH Invalid UUID length.
* @return @ref NRF_ERROR_NOT_FOUND For a 128-bit UUID, no match in the populated table of UUIDs.
*/
*/
SVCALL(SD_BLE_UUID_DECODE, uint32_t, sd_ble_uuid_decode(uint8_t uuid_le_len, uint8_t const * const p_uuid_le, ble_uuid_t * const p_uuid));

View File

@ -6,20 +6,20 @@
agreement with Nordic Semiconductor.
*/
/**
@addtogroup BLE_COMMON
@addtogroup BLE_COMMON
@{
*/
#ifndef BLE_HCI_H__
#define BLE_HCI_H__
#define BLE_HCI_H__
/** @defgroup BLE_HCI_STATUS_CODES Bluetooth status codes
* @{ */
#define BLE_HCI_STATUS_CODE_SUCCESS 0x00
#define BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND 0x01
#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02
#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02
/*0x03 Hardware Failure
0x04 Page Timeout
*/

View File

@ -71,21 +71,12 @@ typedef void (*sys_evt_handler_t) (uint32_t evt_id);
* reinitialization).
*/
/*lint -emacro(506, SOFTDEVICE_HANDLER_INIT) */ /* Suppress "Constant value Boolean */
#define SOFTDEVICE_HANDLER_INIT(CLOCK_SOURCE, \
USE_SCHEDULER) \
#define SOFTDEVICE_HANDLER_INIT(CLOCK_SOURCE, USE_SCHEDULER) \
do \
{ \
static uint32_t EVT_BUFFER[CEIL_DIV(MAX( \
MAX(BLE_STACK_EVT_MSG_BUF_SIZE, \
ANT_STACK_EVT_STRUCT_SIZE), \
SYS_EVT_MSG_BUF_SIZE \
), \
sizeof(uint32_t))]; \
static uint32_t EVT_BUFFER[CEIL_DIV(MAX(MAX(BLE_STACK_EVT_MSG_BUF_SIZE, ANT_STACK_EVT_STRUCT_SIZE), SYS_EVT_MSG_BUF_SIZE), sizeof(uint32_t))]; \
uint32_t ERR_CODE; \
ERR_CODE = softdevice_handler_init((CLOCK_SOURCE), \
EVT_BUFFER, \
sizeof(EVT_BUFFER), \
(USE_SCHEDULER) ? softdevice_evt_schedule : NULL); \
ERR_CODE = softdevice_handler_init((CLOCK_SOURCE), EVT_BUFFER, sizeof(EVT_BUFFER), (USE_SCHEDULER) ? softdevice_evt_schedule : NULL); \
APP_ERROR_CHECK(ERR_CODE); \
} while (0)

View File

@ -235,36 +235,6 @@ uint32_t softdevice_handler_init(nrf_clock_lfclksrc_t clock_source,
return err_code;
}
/**
* Using this call, the application can select whether to include the
* Service Changed characteristic in the GATT Server. The default in all
* previous releases has been to include the Service Changed characteristic,
* but this affects how GATT clients behave. Specifically, it requires
* clients to subscribe to this attribute and not to cache attribute handles
* between connections unless the devices are bonded. If the application
* does not need to change the structure of the GATT server attributes at
* runtime this adds unnecessary complexity to the interaction with peer
* clients. If the SoftDevice is enabled with the Service Changed
* Characteristics turned off, then clients are allowed to cache attribute
* handles making applications simpler on both sides.
*/
ble_enable_params_t enableParams = {
.gatts_enable_params = {
.service_changed = 0
}
};
if ((err_code = sd_ble_enable(&enableParams)) != NRF_SUCCESS) {
return err_code;
}
ble_gap_addr_t addr;
if ((err_code = sd_ble_gap_address_get(&addr)) != NRF_SUCCESS) {
return err_code;
}
if ((err_code = sd_ble_gap_address_set(BLE_GAP_ADDR_CYCLE_MODE_NONE, &addr)) != NRF_SUCCESS) {
return err_code;
}
m_softdevice_enabled = true;
// Enable BLE event interrupt (interrupt priority has already been set by the stack).
return sd_nvic_EnableIRQ(SWI2_IRQn);

View File

@ -88,8 +88,8 @@
/*-------------------------------- TIMER ------------------------------*/
#define CFG_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. freq = (32768/(PRESCALER+1)) */
#define CFG_TIMER_MAX_INSTANCE 8 /**< Maximum number of simultaneously created timers. */
#define CFG_TIMER_OPERATION_QUEUE_SIZE 5 /**< Size of timer operation queues. */
#define CFG_TIMER_MAX_INSTANCE 1 /**< Maximum number of simultaneously created timers. */
#define CFG_TIMER_OPERATION_QUEUE_SIZE 1 /**< Size of timer operation queues. */
/*=========================================================================*/
@ -97,7 +97,7 @@
BTLE SETTINGS
-----------------------------------------------------------------------*/
#define CFG_BLE_TX_POWER_LEVEL 4 /**< in dBm (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
#define CFG_BLE_TX_POWER_LEVEL 0 /**< in dBm (Valid values are -40, -20, -16, -12, -8, -4, 0, 4) */
/*---------------------------- BOND MANAGER ---------------------------*/
#define CFG_BLE_BOND_FLASH_PAGE_BOND (BLE_FLASH_PAGE_END-1) /**< Flash page used for bond manager bonding information.*/
@ -115,8 +115,8 @@
#define CFG_GAP_APPEARANCE BLE_APPEARANCE_GENERIC_TAG
#define CFG_GAP_LOCAL_NAME "nRF5x"
#define CFG_GAP_CONNECTION_MIN_INTERVAL_MS 500 /**< Minimum acceptable connection interval */
#define CFG_GAP_CONNECTION_MAX_INTERVAL_MS 1000 /**< Maximum acceptable connection interval */
#define CFG_GAP_CONNECTION_MIN_INTERVAL_MS 50 /**< Minimum acceptable connection interval */
#define CFG_GAP_CONNECTION_MAX_INTERVAL_MS 500 /**< Maximum acceptable connection interval */
#define CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS 4000 /**< Connection supervisory timeout */
#define CFG_GAP_CONNECTION_SLAVE_LATENCY 0 /**< Slave Latency in number of connection events. */