Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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 "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 Fri Jul 15 2022 12:51:28 by
