library for BLE_GAP_backpack
Dependencies: nrf51-sdk
Fork of nRF51822 by
nRF5xGap.h
00001 /* mbed Microcontroller Library 00002 * Copyright (c) 2006-2013 ARM Limited 00003 * 00004 * Licensed under the Apache License, Version 2.0 (the "License"); 00005 * you may not use this file except in compliance with the License. 00006 * You may obtain a copy of the License at 00007 * 00008 * http://www.apache.org/licenses/LICENSE-2.0 00009 * 00010 * Unless required by applicable law or agreed to in writing, software 00011 * distributed under the License is distributed on an "AS IS" BASIS, 00012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 00013 * See the License for the specific language governing permissions and 00014 * limitations under the License. 00015 */ 00016 00017 #ifndef __NRF5x_GAP_H__ 00018 #define __NRF5x_GAP_H__ 00019 00020 #ifdef YOTTA_CFG_MBED_OS 00021 #include "mbed-drivers/mbed.h" 00022 #else 00023 #include "mbed.h" 00024 #endif 00025 #ifndef YOTTA_CFG_WHITELIST_MAX_SIZE 00026 #define YOTTA_CFG_WHITELIST_MAX_SIZE BLE_GAP_WHITELIST_ADDR_MAX_COUNT 00027 #elif YOTTA_CFG_WHITELIST_MAX_SIZE > BLE_GAP_WHITELIST_ADDR_MAX_COUNT 00028 #undef YOTTA_CFG_WHITELIST_MAX_SIZE 00029 #define YOTTA_CFG_WHITELIST_MAX_SIZE BLE_GAP_WHITELIST_ADDR_MAX_COUNT 00030 #endif 00031 #ifndef YOTTA_CFG_IRK_TABLE_MAX_SIZE 00032 #define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT 00033 #elif YOTTA_CFG_IRK_TABLE_MAX_SIZE > BLE_GAP_WHITELIST_IRK_MAX_COUNT 00034 #undef YOTTA_CFG_IRK_TABLE_MAX_SIZE 00035 #define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT 00036 #endif 00037 #include "ble/blecommon.h" 00038 #include "nrf_ble.h" 00039 #include "ble/GapAdvertisingParams.h" 00040 #include "ble/GapAdvertisingData.h" 00041 #include "ble/Gap.h" 00042 #include "ble/GapScanningParams.h" 00043 00044 #include "nrf_soc.h" 00045 00046 extern "C" { 00047 #include "ble_radio_notification.h" 00048 } 00049 00050 #include "btle_security.h" 00051 00052 void radioNotificationStaticCallback(bool param); 00053 00054 /**************************************************************************/ 00055 /*! 00056 \brief 00057 00058 */ 00059 /**************************************************************************/ 00060 class nRF5xGap : public Gap 00061 { 00062 public: 00063 /* Functions that must be implemented from Gap */ 00064 virtual ble_error_t setAddress(AddressType_t type, const Address_t address); 00065 virtual ble_error_t getAddress(AddressType_t *typeP, Address_t address); 00066 virtual ble_error_t setAdvertisingData(const GapAdvertisingData &, const GapAdvertisingData &); 00067 00068 virtual uint16_t getMinAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MIN);} 00069 virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN);} 00070 virtual uint16_t getMaxAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MAX);} 00071 00072 virtual ble_error_t startAdvertising(const GapAdvertisingParams &); 00073 virtual ble_error_t stopAdvertising(void); 00074 virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams); 00075 virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason); 00076 virtual ble_error_t disconnect(DisconnectionReason_t reason); 00077 00078 virtual ble_error_t setDeviceName(const uint8_t *deviceName); 00079 virtual ble_error_t getDeviceName(uint8_t *deviceName, unsigned *lengthP); 00080 virtual ble_error_t setAppearance(GapAdvertisingData::Appearance appearance); 00081 virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP); 00082 00083 virtual ble_error_t setTxPower(int8_t txPower); 00084 virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP); 00085 00086 void setConnectionHandle(uint16_t con_handle); 00087 uint16_t getConnectionHandle(void); 00088 00089 virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params); 00090 virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params); 00091 virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params); 00092 00093 virtual ble_error_t reset(void); 00094 00095 /* 00096 * The following functions are part of the whitelisting experimental API. 00097 * Therefore, this functionality can change in the near future. 00098 */ 00099 virtual uint8_t getMaxWhitelistSize(void) const; 00100 virtual ble_error_t getWhitelist(Gap::Whitelist_t &whitelistOut) const; 00101 virtual ble_error_t setWhitelist(const Gap::Whitelist_t &whitelistIn); 00102 00103 virtual ble_error_t setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode); 00104 virtual ble_error_t setScanningPolicyMode(ScanningPolicyMode_t mode); 00105 virtual ble_error_t setInitiatorPolicyMode(InitiatorPolicyMode_t mode); 00106 virtual Gap::AdvertisingPolicyMode_t getAdvertisingPolicyMode(void) const; 00107 virtual Gap::ScanningPolicyMode_t getScanningPolicyMode(void) const; 00108 virtual Gap::InitiatorPolicyMode_t getInitiatorPolicyMode(void) const; 00109 00110 virtual ble_error_t initRadioNotification(void) { 00111 if (ble_radio_notification_init(NRF_APP_PRIORITY_HIGH, NRF_RADIO_NOTIFICATION_DISTANCE_800US, radioNotificationStaticCallback) == NRF_SUCCESS) { 00112 return BLE_ERROR_NONE; 00113 } 00114 00115 return BLE_ERROR_UNSPECIFIED; 00116 } 00117 00118 /* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */ 00119 #if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110) 00120 virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams); 00121 virtual ble_error_t stopScan(void); 00122 #endif 00123 00124 private: 00125 /* 00126 * Whitelisting API related structures and helper functions. 00127 */ 00128 00129 /* Policy modes set by the user. By default these are set to ignore the whitelist */ 00130 Gap::AdvertisingPolicyMode_t advertisingPolicyMode; 00131 Gap::ScanningPolicyMode_t scanningPolicyMode; 00132 00133 /* Internal representation of a whitelist */ 00134 uint8_t whitelistAddressesSize; 00135 ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE]; 00136 00137 /* 00138 * An internal function used to populate the ble_gap_whitelist_t that will be used by 00139 * the SoftDevice for filtering requests. This function is needed because for the BLE 00140 * API the whitelist is just a collection of keys, but for the stack it also includes 00141 * the IRK table. 00142 */ 00143 ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist); 00144 00145 private: 00146 bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */ 00147 Timeout radioNotificationTimeout; 00148 00149 /* 00150 * A helper function to post radio notification callbacks with low interrupt priority. 00151 */ 00152 void postRadioNotificationCallback(void) { 00153 #ifdef YOTTA_CFG_MBED_OS 00154 /* 00155 * In mbed OS, all user-facing BLE events (interrupts) are posted to the 00156 * MINAR scheduler to be executed as callbacks in thread mode. MINAR guards 00157 * its critical sections from interrupts by acquiring CriticalSectionLock, 00158 * which results in a call to sd_nvic_critical_region_enter(). Thus, it is 00159 * safe to invoke MINAR APIs from interrupt context as long as those 00160 * interrupts are blocked by sd_nvic_critical_region_enter(). 00161 * 00162 * Radio notifications are a special case for the above. The Radio 00163 * Notification IRQ is handled at a very high priority--higher than the 00164 * level blocked by sd_nvic_critical_region_enter(). Thus Radio Notification 00165 * events can preempt MINAR's critical sections. Using MINAR APIs (such as 00166 * posting an event) directly in processRadioNotification() may result in a 00167 * race condition ending in a hard-fault. 00168 * 00169 * The solution is to *not* call MINAR APIs directly from the Radio 00170 * Notification handling; i.e. to do the bulk of RadioNotification 00171 * processing at a reduced priority which respects MINAR's critical 00172 * sections. Unfortunately, on a cortex-M0, there is no clean way to demote 00173 * priority for the currently executing interrupt--we wouldn't want to 00174 * demote the radio notification handling anyway because it is sensitive to 00175 * timing, and the system expects to finish this handling very quickly. The 00176 * workaround is to employ a Timeout to trigger 00177 * postRadioNotificationCallback() after a very short delay (~0 us) and post 00178 * the MINAR callback that context. 00179 * 00180 * !!!WARNING!!! Radio notifications are very time critical events. The 00181 * current solution is expected to work under the assumption that 00182 * postRadioNotificationCalback() will be executed BEFORE the next radio 00183 * notification event is generated. 00184 */ 00185 minar::Scheduler::postCallback( 00186 mbed::util::FunctionPointer1<void, bool>(&radioNotificationCallback, &FunctionPointerWithContext<bool>::call).bind(radioNotificationCallbackParam) 00187 ); 00188 #else 00189 /* 00190 * In mbed classic, all user-facing BLE events execute callbacks in interrupt 00191 * mode. Radio Notifications are a special case because its IRQ is handled at 00192 * a very high priority. Thus Radio Notification events can preempt other 00193 * operations that require interaction with the SoftDevice such as advertising 00194 * payload updates and changing the Gap state. Therefore, executing a Radio 00195 * Notification callback directly from processRadioNotification() may result 00196 * in a race condition ending in a hard-fault. 00197 * 00198 * The solution is to *not* execute the Radio Notification callback directly 00199 * from the Radio Notification handling; i.e. to do the bulk of the 00200 * Radio Notification processing at a reduced priority. Unfortunately, on a 00201 * cortex-M0, there is no clean way to demote priority for the currently 00202 * executing interrupt--we wouldn't want to demote the radio notification 00203 * handling anyway because it is sensitive to timing, and the system expects 00204 * to finish this handling very quickly. The workaround is to employ a Timeout 00205 * to trigger postRadioNotificationCallback() after a very short delay (~0 us) 00206 * and execute the callback in that context. 00207 * 00208 * !!!WARNING!!! Radio notifications are very time critical events. The 00209 * current solution is expected to work under the assumption that 00210 * postRadioNotificationCalback() will be executed BEFORE the next radio 00211 * notification event is generated. 00212 */ 00213 radioNotificationCallback.call(radioNotificationCallbackParam); 00214 #endif /* #ifdef YOTTA_CFG_MBED_OS */ 00215 } 00216 00217 /** 00218 * A helper function to process radio-notification events; to be called internally. 00219 * @param param [description] 00220 */ 00221 void processRadioNotificationEvent(bool param) { 00222 radioNotificationCallbackParam = param; 00223 radioNotificationTimeout.attach_us(this, &nRF5xGap::postRadioNotificationCallback, 0); 00224 } 00225 friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */ 00226 00227 private: 00228 uint16_t m_connectionHandle; 00229 00230 /* 00231 * Allow instantiation from nRF5xn when required. 00232 */ 00233 friend class nRF5xn; 00234 00235 nRF5xGap() : 00236 advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST), 00237 scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST), 00238 whitelistAddressesSize(0) { 00239 m_connectionHandle = BLE_CONN_HANDLE_INVALID; 00240 } 00241 00242 nRF5xGap(nRF5xGap const &); 00243 void operator=(nRF5xGap const &); 00244 }; 00245 00246 #endif // ifndef __NRF5x_GAP_H__
Generated on Wed Jul 13 2022 11:18:00 by 1.7.2