Nordic stack and drivers for the mbed BLE API. Version to work around build bug.

Dependents:   microbit_rubber_ducky microbit_mouse_BLE microbit_mouse_BLE_daybreak_version microbit_presenter

Fork of nRF51822 by Nordic Semiconductor

Committer:
vcoubard
Date:
Mon Jan 11 10:19:18 2016 +0000
Revision:
565:cf03471a4ec4
Parent:
563:9c4b96f7be8d
Child:
566:e425ad9e5d6e
Synchronized with git rev 0bcc2e96
Author: Andres Amaya Garcia
Modify shutdown due to BLE API change

The module is updated to comply with the changes to BLE API regarding correct
shutdown functionality. The following changes are introduced to ble-nrf51822:

* Calls to the old static function shutdown in Gap, GattClient, GattServer and
SecurityManager are removed.
* The cleanup function in Gap, GattClient, GattServer and SecurityManager is
renamed to `reset()` and made public.
* The static references inside nRF5xGap, nRF5xGattClient, nRF5xGattServer and
nRF5xSecurityManager to objects of their own class are moved to nRF5xn.
* The static getInstance accessors in nRF5xGap, nRF5xGattClient,
nRF5xGattServer and nRF5xSecurityManager are removed and their functionality is
moved to the implemented virtual accessors in nRF5xn i.e. getGap(),
getGattClient, etc.
* A static function Instance is added to nRF5xn class to make the transport
object accessible across the module.

Who changed what in which revision?

UserRevisionLine numberNew contents of line
vcoubard 541:884f95bf5351 1 /* mbed Microcontroller Library
vcoubard 541:884f95bf5351 2 * Copyright (c) 2006-2013 ARM Limited
vcoubard 541:884f95bf5351 3 *
vcoubard 541:884f95bf5351 4 * Licensed under the Apache License, Version 2.0 (the "License");
vcoubard 541:884f95bf5351 5 * you may not use this file except in compliance with the License.
vcoubard 541:884f95bf5351 6 * You may obtain a copy of the License at
vcoubard 541:884f95bf5351 7 *
vcoubard 541:884f95bf5351 8 * http://www.apache.org/licenses/LICENSE-2.0
vcoubard 541:884f95bf5351 9 *
vcoubard 541:884f95bf5351 10 * Unless required by applicable law or agreed to in writing, software
vcoubard 541:884f95bf5351 11 * distributed under the License is distributed on an "AS IS" BASIS,
vcoubard 541:884f95bf5351 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
vcoubard 541:884f95bf5351 13 * See the License for the specific language governing permissions and
vcoubard 541:884f95bf5351 14 * limitations under the License.
vcoubard 541:884f95bf5351 15 */
vcoubard 541:884f95bf5351 16
vcoubard 541:884f95bf5351 17 #ifndef __NRF5x_GAP_H__
vcoubard 541:884f95bf5351 18 #define __NRF5x_GAP_H__
vcoubard 541:884f95bf5351 19
vcoubard 541:884f95bf5351 20 #include "mbed.h"
vcoubard 541:884f95bf5351 21 #include "ble/blecommon.h"
vcoubard 541:884f95bf5351 22 #include "ble.h"
vcoubard 541:884f95bf5351 23 #include "ble/GapAdvertisingParams.h"
vcoubard 541:884f95bf5351 24 #include "ble/GapAdvertisingData.h"
vcoubard 541:884f95bf5351 25 #include "ble/Gap.h"
vcoubard 541:884f95bf5351 26 #include "ble/GapScanningParams.h"
vcoubard 541:884f95bf5351 27
vcoubard 541:884f95bf5351 28 #include "nrf_soc.h"
vcoubard 549:3f782c64d014 29
vcoubard 549:3f782c64d014 30 extern "C" {
vcoubard 541:884f95bf5351 31 #include "ble_radio_notification.h"
vcoubard 549:3f782c64d014 32 }
vcoubard 549:3f782c64d014 33
vcoubard 541:884f95bf5351 34 #include "btle_security.h"
vcoubard 541:884f95bf5351 35
vcoubard 541:884f95bf5351 36 void radioNotificationStaticCallback(bool param);
vcoubard 541:884f95bf5351 37
vcoubard 541:884f95bf5351 38 /**************************************************************************/
vcoubard 541:884f95bf5351 39 /*!
vcoubard 541:884f95bf5351 40 \brief
vcoubard 541:884f95bf5351 41
vcoubard 541:884f95bf5351 42 */
vcoubard 541:884f95bf5351 43 /**************************************************************************/
vcoubard 541:884f95bf5351 44 class nRF5xGap : public Gap
vcoubard 541:884f95bf5351 45 {
vcoubard 541:884f95bf5351 46 public:
vcoubard 541:884f95bf5351 47 /* Functions that must be implemented from Gap */
vcoubard 541:884f95bf5351 48 virtual ble_error_t setAddress(AddressType_t type, const Address_t address);
vcoubard 541:884f95bf5351 49 virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address);
vcoubard 541:884f95bf5351 50 virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &);
vcoubard 541:884f95bf5351 51
vcoubard 541:884f95bf5351 52 virtual uint16_t getMinAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MIN);}
vcoubard 541:884f95bf5351 53 virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN);}
vcoubard 541:884f95bf5351 54 virtual uint16_t getMaxAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MAX);}
vcoubard 541:884f95bf5351 55
vcoubard 541:884f95bf5351 56 virtual ble_error_t startAdvertising(const GapAdvertisingParams &);
vcoubard 541:884f95bf5351 57 virtual ble_error_t stopAdvertising(void);
vcoubard 541:884f95bf5351 58 virtual ble_error_t connect(const Address_t, Gap::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams);
vcoubard 541:884f95bf5351 59 virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason);
vcoubard 541:884f95bf5351 60 virtual ble_error_t disconnect(DisconnectionReason_t reason);
vcoubard 541:884f95bf5351 61
vcoubard 541:884f95bf5351 62 virtual ble_error_t setDeviceName(const uint8_t *deviceName);
vcoubard 541:884f95bf5351 63 virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP);
vcoubard 541:884f95bf5351 64 virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance);
vcoubard 541:884f95bf5351 65 virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP);
vcoubard 541:884f95bf5351 66
vcoubard 541:884f95bf5351 67 virtual ble_error_t setTxPower(int8_t txPower);
vcoubard 541:884f95bf5351 68 virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP);
vcoubard 541:884f95bf5351 69
vcoubard 541:884f95bf5351 70 void setConnectionHandle(uint16_t con_handle);
vcoubard 541:884f95bf5351 71 uint16_t getConnectionHandle(void);
vcoubard 541:884f95bf5351 72
vcoubard 541:884f95bf5351 73 virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params);
vcoubard 541:884f95bf5351 74 virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params);
vcoubard 541:884f95bf5351 75 virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params);
vcoubard 541:884f95bf5351 76
vcoubard 565:cf03471a4ec4 77 virtual ble_error_t reset(void);
vcoubard 565:cf03471a4ec4 78
vcoubard 541:884f95bf5351 79 virtual ble_error_t initRadioNotification(void) {
vcoubard 541:884f95bf5351 80 if (ble_radio_notification_init(NRF_APP_PRIORITY_HIGH, NRF_RADIO_NOTIFICATION_DISTANCE_800US, radioNotificationStaticCallback) == NRF_SUCCESS) {
vcoubard 541:884f95bf5351 81 return BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 82 }
vcoubard 541:884f95bf5351 83
vcoubard 541:884f95bf5351 84 return BLE_ERROR_UNSPECIFIED;
vcoubard 541:884f95bf5351 85 }
vcoubard 541:884f95bf5351 86
vcoubard 541:884f95bf5351 87 /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */
vcoubard 541:884f95bf5351 88 #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
vcoubard 541:884f95bf5351 89 virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams) {
vcoubard 541:884f95bf5351 90 ble_gap_scan_params_t scanParams = {
vcoubard 541:884f95bf5351 91 .active = scanningParams.getActiveScanning(), /**< If 1, perform active scanning (scan requests). */
vcoubard 541:884f95bf5351 92 .selective = 0, /**< If 1, ignore unknown devices (non whitelisted). */
vcoubard 541:884f95bf5351 93 .p_whitelist = NULL, /**< Pointer to whitelist, NULL if none is given. */
vcoubard 541:884f95bf5351 94 .interval = scanningParams.getInterval(), /**< Scan interval between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
vcoubard 541:884f95bf5351 95 .window = scanningParams.getWindow(), /**< Scan window between 0x0004 and 0x4000 in 0.625ms units (2.5ms to 10.24s). */
vcoubard 541:884f95bf5351 96 .timeout = scanningParams.getTimeout(), /**< Scan timeout between 0x0001 and 0xFFFF in seconds, 0x0000 disables timeout. */
vcoubard 541:884f95bf5351 97 };
vcoubard 541:884f95bf5351 98
vcoubard 541:884f95bf5351 99 if (sd_ble_gap_scan_start(&scanParams) != NRF_SUCCESS) {
vcoubard 541:884f95bf5351 100 return BLE_ERROR_PARAM_OUT_OF_RANGE;
vcoubard 541:884f95bf5351 101 }
vcoubard 541:884f95bf5351 102
vcoubard 541:884f95bf5351 103 return BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 104 }
vcoubard 541:884f95bf5351 105
vcoubard 541:884f95bf5351 106 virtual ble_error_t stopScan(void) {
vcoubard 541:884f95bf5351 107 if (sd_ble_gap_scan_stop() == NRF_SUCCESS) {
vcoubard 541:884f95bf5351 108 return BLE_ERROR_NONE;
vcoubard 541:884f95bf5351 109 }
vcoubard 541:884f95bf5351 110
vcoubard 541:884f95bf5351 111 return BLE_STACK_BUSY;
vcoubard 541:884f95bf5351 112 }
vcoubard 541:884f95bf5351 113 #endif
vcoubard 541:884f95bf5351 114
vcoubard 541:884f95bf5351 115 private:
vcoubard 546:1e147322b2b5 116 bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */
vcoubard 546:1e147322b2b5 117 Timeout radioNotificationTimeout;
vcoubard 546:1e147322b2b5 118
vcoubard 546:1e147322b2b5 119 /*
vcoubard 550:bcb632fc92df 120 * A helper function to post radio notification callbacks with low interrupt priority.
vcoubard 546:1e147322b2b5 121 */
vcoubard 546:1e147322b2b5 122 void postRadioNotificationCallback(void) {
vcoubard 550:bcb632fc92df 123 #ifdef YOTTA_CFG_MBED_OS
vcoubard 550:bcb632fc92df 124 /*
vcoubard 550:bcb632fc92df 125 * In mbed OS, all user-facing BLE events (interrupts) are posted to the
vcoubard 550:bcb632fc92df 126 * MINAR scheduler to be executed as callbacks in thread mode. MINAR guards
vcoubard 550:bcb632fc92df 127 * its critical sections from interrupts by acquiring CriticalSectionLock,
vcoubard 550:bcb632fc92df 128 * which results in a call to sd_nvic_critical_region_enter(). Thus, it is
vcoubard 550:bcb632fc92df 129 * safe to invoke MINAR APIs from interrupt context as long as those
vcoubard 550:bcb632fc92df 130 * interrupts are blocked by sd_nvic_critical_region_enter().
vcoubard 550:bcb632fc92df 131 *
vcoubard 550:bcb632fc92df 132 * Radio notifications are a special case for the above. The Radio
vcoubard 550:bcb632fc92df 133 * Notification IRQ is handled at a very high priority--higher than the
vcoubard 550:bcb632fc92df 134 * level blocked by sd_nvic_critical_region_enter(). Thus Radio Notification
vcoubard 550:bcb632fc92df 135 * events can preempt MINAR's critical sections. Using MINAR APIs (such as
vcoubard 550:bcb632fc92df 136 * posting an event) directly in processRadioNotification() may result in a
vcoubard 550:bcb632fc92df 137 * race condition ending in a hard-fault.
vcoubard 550:bcb632fc92df 138 *
vcoubard 550:bcb632fc92df 139 * The solution is to *not* call MINAR APIs directly from the Radio
vcoubard 550:bcb632fc92df 140 * Notification handling; i.e. to do the bulk of RadioNotification
vcoubard 550:bcb632fc92df 141 * processing at a reduced priority which respects MINAR's critical
vcoubard 550:bcb632fc92df 142 * sections. Unfortunately, on a cortex-M0, there is no clean way to demote
vcoubard 550:bcb632fc92df 143 * priority for the currently executing interrupt--we wouldn't want to
vcoubard 550:bcb632fc92df 144 * demote the radio notification handling anyway because it is sensitive to
vcoubard 550:bcb632fc92df 145 * timing, and the system expects to finish this handling very quickly. The
vcoubard 550:bcb632fc92df 146 * workaround is to employ a Timeout to trigger
vcoubard 550:bcb632fc92df 147 * postRadioNotificationCallback() after a very short delay (~0 us) and post
vcoubard 550:bcb632fc92df 148 * the MINAR callback that context.
vcoubard 550:bcb632fc92df 149 *
vcoubard 550:bcb632fc92df 150 * !!!WARNING!!! Radio notifications are very time critical events. The
vcoubard 550:bcb632fc92df 151 * current solution is expected to work under the assumption that
vcoubard 550:bcb632fc92df 152 * postRadioNotificationCalback() will be executed BEFORE the next radio
vcoubard 550:bcb632fc92df 153 * notification event is generated.
vcoubard 550:bcb632fc92df 154 */
vcoubard 546:1e147322b2b5 155 minar::Scheduler::postCallback(
vcoubard 546:1e147322b2b5 156 mbed::util::FunctionPointer1<void, bool>(&radioNotificationCallback, &FunctionPointerWithContext<bool>::call).bind(radioNotificationCallbackParam)
vcoubard 546:1e147322b2b5 157 );
vcoubard 550:bcb632fc92df 158 #else
vcoubard 550:bcb632fc92df 159 /*
vcoubard 550:bcb632fc92df 160 * In mbed classic, all user-facing BLE events execute callbacks in interrupt
vcoubard 550:bcb632fc92df 161 * mode. Radio Notifications are a special case because its IRQ is handled at
vcoubard 550:bcb632fc92df 162 * a very high priority. Thus Radio Notification events can preempt other
vcoubard 550:bcb632fc92df 163 * operations that require interaction with the SoftDevice such as advertising
vcoubard 550:bcb632fc92df 164 * payload updates and changing the Gap state. Therefore, executing a Radio
vcoubard 550:bcb632fc92df 165 * Notification callback directly from processRadioNotification() may result
vcoubard 550:bcb632fc92df 166 * in a race condition ending in a hard-fault.
vcoubard 550:bcb632fc92df 167 *
vcoubard 550:bcb632fc92df 168 * The solution is to *not* execute the Radio Notification callback directly
vcoubard 550:bcb632fc92df 169 * from the Radio Notification handling; i.e. to do the bulk of the
vcoubard 550:bcb632fc92df 170 * Radio Notification processing at a reduced priority. Unfortunately, on a
vcoubard 550:bcb632fc92df 171 * cortex-M0, there is no clean way to demote priority for the currently
vcoubard 550:bcb632fc92df 172 * executing interrupt--we wouldn't want to demote the radio notification
vcoubard 550:bcb632fc92df 173 * handling anyway because it is sensitive to timing, and the system expects
vcoubard 550:bcb632fc92df 174 * to finish this handling very quickly. The workaround is to employ a Timeout
vcoubard 550:bcb632fc92df 175 * to trigger postRadioNotificationCallback() after a very short delay (~0 us)
vcoubard 550:bcb632fc92df 176 * and execute the callback in that context.
vcoubard 550:bcb632fc92df 177 *
vcoubard 550:bcb632fc92df 178 * !!!WARNING!!! Radio notifications are very time critical events. The
vcoubard 550:bcb632fc92df 179 * current solution is expected to work under the assumption that
vcoubard 550:bcb632fc92df 180 * postRadioNotificationCalback() will be executed BEFORE the next radio
vcoubard 550:bcb632fc92df 181 * notification event is generated.
vcoubard 550:bcb632fc92df 182 */
vcoubard 550:bcb632fc92df 183 radioNotificationCallback.call(radioNotificationCallbackParam);
vcoubard 550:bcb632fc92df 184 #endif /* #ifdef YOTTA_CFG_MBED_OS */
vcoubard 546:1e147322b2b5 185 }
vcoubard 546:1e147322b2b5 186
vcoubard 541:884f95bf5351 187 /**
vcoubard 541:884f95bf5351 188 * A helper function to process radio-notification events; to be called internally.
vcoubard 541:884f95bf5351 189 * @param param [description]
vcoubard 541:884f95bf5351 190 */
vcoubard 541:884f95bf5351 191 void processRadioNotificationEvent(bool param) {
vcoubard 546:1e147322b2b5 192 radioNotificationCallbackParam = param;
vcoubard 546:1e147322b2b5 193 radioNotificationTimeout.attach_us(this, &nRF5xGap::postRadioNotificationCallback, 0);
vcoubard 541:884f95bf5351 194 }
vcoubard 541:884f95bf5351 195 friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */
vcoubard 541:884f95bf5351 196
vcoubard 541:884f95bf5351 197 private:
vcoubard 541:884f95bf5351 198 uint16_t m_connectionHandle;
vcoubard 565:cf03471a4ec4 199
vcoubard 565:cf03471a4ec4 200 /*
vcoubard 565:cf03471a4ec4 201 * Allow instantiation from nRF5xn when required.
vcoubard 565:cf03471a4ec4 202 */
vcoubard 565:cf03471a4ec4 203 friend class nRF5xn;
vcoubard 565:cf03471a4ec4 204
vcoubard 541:884f95bf5351 205 nRF5xGap() {
vcoubard 541:884f95bf5351 206 m_connectionHandle = BLE_CONN_HANDLE_INVALID;
vcoubard 541:884f95bf5351 207 }
vcoubard 541:884f95bf5351 208
vcoubard 541:884f95bf5351 209 nRF5xGap(nRF5xGap const &);
vcoubard 541:884f95bf5351 210 void operator=(nRF5xGap const &);
vcoubard 541:884f95bf5351 211 };
vcoubard 541:884f95bf5351 212
rgrover1 388:db85a09c27ef 213 #endif // ifndef __NRF5x_GAP_H__