mirror of https://github.com/ARMmbed/mbed-os.git
commit
12eb5b702d
|
@ -0,0 +1,344 @@
|
|||
# Change Log
|
||||
|
||||
## [v2.5.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.3) (2016-02-16)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.5.2...v2.5.3)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix for compilation errors with S110 softdevice in btle.cpp [\#109](https://github.com/ARMmbed/ble-nrf51822/pull/109) ([ddavidebor](https://github.com/ddavidebor))
|
||||
|
||||
## [v2.5.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.2) (2016-02-16)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.5.1...v2.5.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Sync develop against master [\#113](https://github.com/ARMmbed/ble-nrf51822/pull/113) ([pan-](https://github.com/pan-))
|
||||
- Fix incorrect handles of characteristics descriptors. [\#112](https://github.com/ARMmbed/ble-nrf51822/pull/112) ([pan-](https://github.com/pan-))
|
||||
|
||||
## [v2.5.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.1) (2016-01-27)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.5.0...v2.5.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Remove Gap::state updates from this module [\#108](https://github.com/ARMmbed/ble-nrf51822/pull/108) ([andresag01](https://github.com/andresag01))
|
||||
- merge version [\#106](https://github.com/ARMmbed/ble-nrf51822/pull/106) ([pan-](https://github.com/pan-))
|
||||
|
||||
## [v2.5.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.5.0) (2016-01-12)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.4.1...v2.5.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix access to enum member [\#105](https://github.com/ARMmbed/ble-nrf51822/pull/105) ([pan-](https://github.com/pan-))
|
||||
- Hotfix dependency [\#104](https://github.com/ARMmbed/ble-nrf51822/pull/104) ([pan-](https://github.com/pan-))
|
||||
- Finish implementation of getAddressesFromBondTable [\#103](https://github.com/ARMmbed/ble-nrf51822/pull/103) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.4.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.4.1) (2016-01-11)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.4.0...v2.4.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- merge branch develop \(v2.4.0\) [\#100](https://github.com/ARMmbed/ble-nrf51822/pull/100) ([pan-](https://github.com/pan-))
|
||||
|
||||
## [v2.4.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.4.0) (2016-01-10)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.3.1...v2.4.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add implementation of experimental whitelisting API [\#99](https://github.com/ARMmbed/ble-nrf51822/pull/99) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.3.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.3.1) (2016-01-07)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.3.0...v2.3.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update yotta module dependencies [\#98](https://github.com/ARMmbed/ble-nrf51822/pull/98) ([pan-](https://github.com/pan-))
|
||||
|
||||
## [v2.3.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.3.0) (2015-12-23)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.10...v2.3.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Implementation of Characteristic descriptor discovery [\#74](https://github.com/ARMmbed/ble-nrf51822/pull/74) ([pan-](https://github.com/pan-))
|
||||
|
||||
## [v2.2.10](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.10) (2015-12-23)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.9...v2.2.10)
|
||||
|
||||
**Fixed bugs:**
|
||||
|
||||
- nRF5xn::init don't verify if errors have occurred during btle\_init [\#59](https://github.com/ARMmbed/ble-nrf51822/issues/59)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- A call to shutdown does not clear the state of some components of BLE API [\#85](https://github.com/ARMmbed/ble-nrf51822/issues/85)
|
||||
- Memory allocation issue on the NRF51DK board. [\#76](https://github.com/ARMmbed/ble-nrf51822/issues/76)
|
||||
- Terrible handling of initLen / minLen and variable length characteristics. [\#56](https://github.com/ARMmbed/ble-nrf51822/issues/56)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix shutdown of Gap instance to avoid NULL refs [\#96](https://github.com/ARMmbed/ble-nrf51822/pull/96) ([andresag01](https://github.com/andresag01))
|
||||
- Add check for return code of ble\_init [\#95](https://github.com/ARMmbed/ble-nrf51822/pull/95) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.2.9](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.9) (2015-12-18)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.8...v2.2.9)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Cannot open source input file "system\_nrf51.h" [\#52](https://github.com/ARMmbed/ble-nrf51822/issues/52)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Remove occurrence of deprecated appearance enum [\#92](https://github.com/ARMmbed/ble-nrf51822/pull/92) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.2.8](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.8) (2015-12-16)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.7...v2.2.8)
|
||||
|
||||
## [v2.2.7](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.7) (2015-12-15)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.6...v2.2.7)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Replace deprecated inclusions of mbed.h [\#89](https://github.com/ARMmbed/ble-nrf51822/pull/89) ([andresag01](https://github.com/andresag01))
|
||||
- Improve shutdown to clear BLE API and not just SD [\#87](https://github.com/ARMmbed/ble-nrf51822/pull/87) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.2.6](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.6) (2015-12-15)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.5...v2.2.6)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- follow the extraction of address related types from Gap.h into BLEProtocol.h [\#88](https://github.com/ARMmbed/ble-nrf51822/pull/88) ([rgrover](https://github.com/rgrover))
|
||||
|
||||
## [v2.2.5](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.5) (2015-12-11)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.3...v2.2.5)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Added SecurityManager::setLinkSecurity call for elevating security settings on a particular connection. [\#86](https://github.com/ARMmbed/ble-nrf51822/pull/86) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [v2.2.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.3) (2015-12-10)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.2...v2.2.3)
|
||||
|
||||
## [v2.2.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.2) (2015-12-08)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.1...v2.2.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Add -Wno-unused-function to supress-warnings.cmake [\#83](https://github.com/ARMmbed/ble-nrf51822/pull/83) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.2.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.1) (2015-12-08)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.2.0...v2.2.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- WIP: UUID endian change [\#82](https://github.com/ARMmbed/ble-nrf51822/pull/82) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [v2.2.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.2.0) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.4...v2.2.0)
|
||||
|
||||
## [v2.1.4](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.4) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.3...v2.1.4)
|
||||
|
||||
## [v2.1.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.3) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.2...v2.1.3)
|
||||
|
||||
## [v2.1.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.2) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.1...v2.1.2)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Allow GattAttributes to have variable length [\#81](https://github.com/ARMmbed/ble-nrf51822/pull/81) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.1.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.1) (2015-12-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.1.0...v2.1.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fixed endianness bug in nRF5xServiceDiscovery::processDiscoverUUIDResponse so it is consistent with BLE API. [\#80](https://github.com/ARMmbed/ble-nrf51822/pull/80) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
- Fixed bug in nRF5xGap.setAddress where random adresses where not set properly. [\#79](https://github.com/ARMmbed/ble-nrf51822/pull/79) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
- Separate concept of minlen and len for BLE chars [\#78](https://github.com/ARMmbed/ble-nrf51822/pull/78) ([andresag01](https://github.com/andresag01))
|
||||
- Split nordic sdk into its own module [\#75](https://github.com/ARMmbed/ble-nrf51822/pull/75) ([LiyouZhou](https://github.com/LiyouZhou))
|
||||
|
||||
## [v2.1.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.1.0) (2015-11-27)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.8...v2.1.0)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update to sdk 8.1 [\#77](https://github.com/ARMmbed/ble-nrf51822/pull/77) ([LiyouZhou](https://github.com/LiyouZhou))
|
||||
|
||||
## [v2.0.8](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.8) (2015-11-26)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.7...v2.0.8)
|
||||
|
||||
## [v2.0.7](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.7) (2015-11-26)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.6...v2.0.7)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- test2000 [\#72](https://github.com/ARMmbed/ble-nrf51822/issues/72)
|
||||
- test1000000 [\#71](https://github.com/ARMmbed/ble-nrf51822/issues/71)
|
||||
- test4 [\#70](https://github.com/ARMmbed/ble-nrf51822/issues/70)
|
||||
- test3 [\#69](https://github.com/ARMmbed/ble-nrf51822/issues/69)
|
||||
- test2 [\#68](https://github.com/ARMmbed/ble-nrf51822/issues/68)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- use Extern c around \#include to use nordic sdk headers implemented in C [\#73](https://github.com/ARMmbed/ble-nrf51822/pull/73) ([LiyouZhou](https://github.com/LiyouZhou))
|
||||
|
||||
## [v2.0.6](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.6) (2015-11-17)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.5...v2.0.6)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- test [\#66](https://github.com/ARMmbed/ble-nrf51822/issues/66)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- add Nordic's license agreement. [\#67](https://github.com/ARMmbed/ble-nrf51822/pull/67) ([rgrover](https://github.com/rgrover))
|
||||
|
||||
## [v2.0.5](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.5) (2015-11-16)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.4...v2.0.5)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Post radio notification callback through minar [\#65](https://github.com/ARMmbed/ble-nrf51822/pull/65) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.0.4](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.4) (2015-11-13)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.3...v2.0.4)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Fix assembly sequence to start bootloader in GCC [\#64](https://github.com/ARMmbed/ble-nrf51822/pull/64) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v2.0.3](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.3) (2015-11-09)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.2...v2.0.3)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Added watchdog header file from Nordic SDK 8.1 [\#62](https://github.com/ARMmbed/ble-nrf51822/pull/62) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [v2.0.2](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.2) (2015-11-03)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/mbedos-release-15-11...v2.0.2)
|
||||
|
||||
## [mbedos-release-15-11](https://github.com/ARMmbed/ble-nrf51822/tree/mbedos-release-15-11) (2015-11-03)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.1...mbedos-release-15-11)
|
||||
|
||||
## [v2.0.1](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.1) (2015-11-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v2.0.0...v2.0.1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Ensure that the initialization flags is set to false if the BLE stack is shutdown properly. [\#58](https://github.com/ARMmbed/ble-nrf51822/pull/58) ([pan-](https://github.com/pan-))
|
||||
|
||||
## [v2.0.0](https://github.com/ARMmbed/ble-nrf51822/tree/v2.0.0) (2015-11-02)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v1.1.0...v2.0.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Nordic SDK and SoftDevice [\#57](https://github.com/ARMmbed/ble-nrf51822/issues/57)
|
||||
- shouldn't eab6631cb be merged into master? [\#54](https://github.com/ARMmbed/ble-nrf51822/issues/54)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Introduced changes for memory savings [\#55](https://github.com/ARMmbed/ble-nrf51822/pull/55) ([andresag01](https://github.com/andresag01))
|
||||
|
||||
## [v1.1.0](https://github.com/ARMmbed/ble-nrf51822/tree/v1.1.0) (2015-10-28)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v1.0.0...v1.1.0)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- target dependencies in module.json [\#50](https://github.com/ARMmbed/ble-nrf51822/issues/50)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- When connecting, if no scanning parameters are passed, use values from Gap parent. [\#53](https://github.com/ARMmbed/ble-nrf51822/pull/53) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
## [v1.0.0](https://github.com/ARMmbed/ble-nrf51822/tree/v1.0.0) (2015-10-19)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/mbedos-techcon-oob2...v1.0.0)
|
||||
|
||||
## [mbedos-techcon-oob2](https://github.com/ARMmbed/ble-nrf51822/tree/mbedos-techcon-oob2) (2015-10-19)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.8...mbedos-techcon-oob2)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- rename the bootloader files with \_fota in the name? [\#51](https://github.com/ARMmbed/ble-nrf51822/issues/51)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Update S110 detection macros, again [\#49](https://github.com/ARMmbed/ble-nrf51822/pull/49) ([jpbrucker](https://github.com/jpbrucker))
|
||||
- Error check number of characteristics [\#48](https://github.com/ARMmbed/ble-nrf51822/pull/48) ([Timmmm](https://github.com/Timmmm))
|
||||
|
||||
## [v0.4.8](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.8) (2015-09-25)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.7...v0.4.8)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- Error real cause loss in nRF5xGattServer.cpp [\#44](https://github.com/ARMmbed/ble-nrf51822/issues/44)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- rgrover patch fixed [\#47](https://github.com/ARMmbed/ble-nrf51822/pull/47) ([fabiencomte](https://github.com/fabiencomte))
|
||||
- Update S110 detection macros [\#43](https://github.com/ARMmbed/ble-nrf51822/pull/43) ([jpbrucker](https://github.com/jpbrucker))
|
||||
- remove some unnecessary include paths [\#42](https://github.com/ARMmbed/ble-nrf51822/pull/42) ([autopulated](https://github.com/autopulated))
|
||||
- Add FOTA bootloader image [\#41](https://github.com/ARMmbed/ble-nrf51822/pull/41) ([jpbrucker](https://github.com/jpbrucker))
|
||||
|
||||
## [v0.4.7](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.7) (2015-08-13)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.6...v0.4.7)
|
||||
|
||||
## [v0.4.6](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.6) (2015-08-11)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.5...v0.4.6)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- remove duplication of global static variable BLE\_EVT\_BUFFER [\#39](https://github.com/ARMmbed/ble-nrf51822/issues/39)
|
||||
- clearScanResponse\(\) [\#30](https://github.com/ARMmbed/ble-nrf51822/issues/30)
|
||||
- Debug builds fail due to missing bsp.h [\#11](https://github.com/ARMmbed/ble-nrf51822/issues/11)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Disable GattClient features when using S110 SoftDevice [\#38](https://github.com/ARMmbed/ble-nrf51822/pull/38) ([jpbrucker](https://github.com/jpbrucker))
|
||||
|
||||
## [v0.4.5](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.5) (2015-08-10)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.4...v0.4.5)
|
||||
|
||||
## [v0.4.4](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.4) (2015-08-07)
|
||||
[Full Changelog](https://github.com/ARMmbed/ble-nrf51822/compare/v0.4.3...v0.4.4)
|
||||
|
||||
**Closed issues:**
|
||||
|
||||
- nrf51822 hangs after calling sd\_flash\_page\_erase\(\) [\#35](https://github.com/ARMmbed/ble-nrf51822/issues/35)
|
||||
- nRF5xn::getVersion return \(Unknown\) with version 8 soft device [\#29](https://github.com/ARMmbed/ble-nrf51822/issues/29)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Changed Gap:: to GapAdvertisingParams:: because of change in BLE [\#34](https://github.com/ARMmbed/ble-nrf51822/pull/34) ([jslater8](https://github.com/jslater8))
|
||||
- Select the clock source dynamically on SoftDevice initialisation [\#32](https://github.com/ARMmbed/ble-nrf51822/pull/32) ([jpbrucker](https://github.com/jpbrucker))
|
||||
- Add S110 SoftDevice compatibility [\#28](https://github.com/ARMmbed/ble-nrf51822/pull/28) ([jpbrucker](https://github.com/jpbrucker))
|
||||
|
||||
## [v0.4.3](https://github.com/ARMmbed/ble-nrf51822/tree/v0.4.3) (2015-07-22)
|
||||
**Closed issues:**
|
||||
|
||||
- Target polling failed [\#24](https://github.com/ARMmbed/ble-nrf51822/issues/24)
|
||||
- support handling of HVX Events \(notifications and indications\). [\#22](https://github.com/ARMmbed/ble-nrf51822/issues/22)
|
||||
- provide an implementation for GattServer::areUpdatesEnabled\(\) [\#21](https://github.com/ARMmbed/ble-nrf51822/issues/21)
|
||||
- getValueHandle\(\) returns characteristicIndex instead of attribute-handle [\#20](https://github.com/ARMmbed/ble-nrf51822/issues/20)
|
||||
- Clash With Definition And Enum Naming [\#16](https://github.com/ARMmbed/ble-nrf51822/issues/16)
|
||||
- Errors in GCC build [\#14](https://github.com/ARMmbed/ble-nrf51822/issues/14)
|
||||
- bring s110 support back [\#10](https://github.com/ARMmbed/ble-nrf51822/issues/10)
|
||||
- Allow adding a User Description descriptor to a GattCharacteristic. [\#9](https://github.com/ARMmbed/ble-nrf51822/issues/9)
|
||||
- device\_manager\_peripheral.c includes app\_trace.h [\#7](https://github.com/ARMmbed/ble-nrf51822/issues/7)
|
||||
- linking esb\_gcc.a \(nrf51822 enhanced shock burst\) with mbed [\#5](https://github.com/ARMmbed/ble-nrf51822/issues/5)
|
||||
- The app\_timer usage may conflict [\#2](https://github.com/ARMmbed/ble-nrf51822/issues/2)
|
||||
- Nordic License [\#1](https://github.com/ARMmbed/ble-nrf51822/issues/1)
|
||||
|
||||
**Merged pull requests:**
|
||||
|
||||
- Develop [\#25](https://github.com/ARMmbed/ble-nrf51822/pull/25) ([zoujixing](https://github.com/zoujixing))
|
||||
- Remove unnecessary 'compiler\_abstraction.h' to get rid of duplicate '… [\#23](https://github.com/ARMmbed/ble-nrf51822/pull/23) ([adfernandes](https://github.com/adfernandes))
|
||||
- restructure for minimal yotta compatibility [\#15](https://github.com/ARMmbed/ble-nrf51822/pull/15) ([autopulated](https://github.com/autopulated))
|
||||
- Fix various GCC compilation issues. [\#12](https://github.com/ARMmbed/ble-nrf51822/pull/12) ([adfernandes](https://github.com/adfernandes))
|
||||
- Fix for GCC lost in SDK v8.0 update [\#8](https://github.com/ARMmbed/ble-nrf51822/pull/8) ([rosterloh](https://github.com/rosterloh))
|
||||
- new target DELTA\_DFCM\_NNN40 with nrf51822 chip, config internal RC crystal. [\#6](https://github.com/ARMmbed/ble-nrf51822/pull/6) ([Marcomissyou](https://github.com/Marcomissyou))
|
||||
- Updated return value for nRF51GattServer::updateValue. Will now report w... [\#4](https://github.com/ARMmbed/ble-nrf51822/pull/4) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
- Added optional data and length fields to the return struct for authorize... [\#3](https://github.com/ARMmbed/ble-nrf51822/pull/3) ([marcuschangarm](https://github.com/marcuschangarm))
|
||||
|
||||
|
||||
|
||||
\* *This Change Log was automatically generated by [github_changelog_generator](https://github.com/skywinder/Github-Changelog-Generator)*
|
|
@ -0,0 +1,13 @@
|
|||
Copyright (c) 2015 ARM Limited
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
|
@ -0,0 +1,30 @@
|
|||
/*
|
||||
* S110/S120/S130 License Agreement
|
||||
*
|
||||
* Copyright (c) 2015, Nordic Semiconductor ASA, All rights reserved.
|
||||
*
|
||||
* Redistribution. Redistribution and use in binary form, without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* • Redistributions must reproduce the above copyright notice and the following
|
||||
* disclaimer in the documentation and/or other materials provided with the
|
||||
* distribution.
|
||||
* • Neither the name of the copyright holder nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
* • No reverse engineering, decompilation, or disassembly of this software is
|
||||
* permitted.
|
||||
*
|
||||
* DISCLAIMER.
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
* /
|
|
@ -0,0 +1,336 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "common/common.h"
|
||||
#include "nordic_common.h"
|
||||
|
||||
#include "btle.h"
|
||||
#include "btle_clock.h"
|
||||
|
||||
#include "ble_flash.h"
|
||||
#include "ble_conn_params.h"
|
||||
|
||||
#include "btle_gap.h"
|
||||
//#include "btle_advertising.h"
|
||||
#include "custom/custom_helper.h"
|
||||
|
||||
#include "ble/GapEvents.h"
|
||||
#include "nRF5xn.h"
|
||||
|
||||
#ifdef S110
|
||||
#define IS_LEGACY_DEVICE_MANAGER_ENABLED 1
|
||||
#elif defined(S130) || defined(S132)
|
||||
#define IS_LEGACY_DEVICE_MANAGER_ENABLED 0
|
||||
#endif
|
||||
|
||||
extern "C" {
|
||||
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
|
||||
#include "pstorage.h"
|
||||
#include "device_manager.h"
|
||||
#else
|
||||
#include "fstorage.h"
|
||||
#include "fds.h"
|
||||
#include "peer_manager.h"
|
||||
#include "ble_conn_state.h"
|
||||
#endif
|
||||
|
||||
#include "softdevice_handler.h"
|
||||
#include "ble_stack_handler_types.h"
|
||||
}
|
||||
|
||||
#include "ble_hci.h"
|
||||
#include "btle_discovery.h"
|
||||
|
||||
#include "nRF5xGattClient.h"
|
||||
#include "nRF5xServiceDiscovery.h"
|
||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
||||
|
||||
|
||||
bool isEventsSignaled = false;
|
||||
|
||||
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 SD_EVT_IRQHandler(void); // export the softdevice event handler for registration by nvic-set-vector.
|
||||
|
||||
|
||||
static void btle_handler(ble_evt_t *p_ble_evt);
|
||||
|
||||
#if 0
|
||||
#define CENTRAL_LINK_COUNT (YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS) /**<number of central links used by the application. When changing this number remember to adjust the RAM settings */
|
||||
/** If value for YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
||||
#define PERIPHERAL_LINK_COUNT (YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS) /**<number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
|
||||
/** If value for YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
||||
#define GATTS_ATTR_TAB_SIZE (YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE) /**< GATTS attribite table size. */
|
||||
/** If value for YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE was used, ram settings are adjusted by the yotta target module. */
|
||||
#else
|
||||
#define CENTRAL_LINK_COUNT 3 /**<number of central links used by the application. When changing this number remember to adjust the RAM settings */
|
||||
/** If value for YOTTA_CFG_NORDIC_BLE_PERIPHERAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
||||
#define PERIPHERAL_LINK_COUNT 1 /**<number of peripheral links used by the application. When changing this number remember to adjust the RAM settings*/
|
||||
/** If value for YOTTA_CFG_NORDIC_BLE_CENTRAL_LINKS was used, ram settings are adjusted by the yotta target module. */
|
||||
#define GATTS_ATTR_TAB_SIZE 0x600 /**< GATTS attribite table size. */
|
||||
/** If value for YOTTA_CFG_NORDIC_BLE_GATTS_ATTR_TAB_SIZE was used, ram settings are adjusted by the yotta target module. */
|
||||
|
||||
#endif
|
||||
|
||||
static void sys_evt_dispatch(uint32_t sys_evt)
|
||||
{
|
||||
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
|
||||
pstorage_sys_event_handler(sys_evt);
|
||||
#else
|
||||
// Forward Softdevice events to the fstorage module
|
||||
fs_sys_event_handler(sys_evt);
|
||||
#endif
|
||||
}
|
||||
|
||||
/**
|
||||
* This function is called in interrupt context to handle BLE events; i.e. pull
|
||||
* system and user events out of the pending events-queue of the BLE stack. The
|
||||
* BLE stack signals the availability of events by the triggering the SWI2
|
||||
* interrupt, which forwards the handling to this function.
|
||||
*
|
||||
* The event processing loop is implemented in intern_softdevice_events_execute().
|
||||
*
|
||||
* This function will signal to the user code by calling signalEventsToProcess
|
||||
* that their is events to process and BLE::processEvents should be called.
|
||||
*/
|
||||
static uint32_t signalEvent()
|
||||
{
|
||||
if(isEventsSignaled == false) {
|
||||
isEventsSignaled = true;
|
||||
nRF5xn::Instance(BLE::DEFAULT_INSTANCE).signalEventsToProcess(BLE::DEFAULT_INSTANCE);
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
error_t btle_init(void)
|
||||
{
|
||||
nrf_clock_lf_cfg_t clockConfiguration;
|
||||
|
||||
// register softdevice handler vector
|
||||
NVIC_SetVector(SD_EVT_IRQn, (uint32_t) SD_EVT_IRQHandler);
|
||||
|
||||
// Configure the LF clock according to values provided by btle_clock.h.
|
||||
// It is input from the chain of the yotta configuration system.
|
||||
clockConfiguration.source = LFCLK_CONF_SOURCE;
|
||||
clockConfiguration.xtal_accuracy = LFCLK_CONF_ACCURACY;
|
||||
clockConfiguration.rc_ctiv = LFCLK_CONF_RC_CTIV;
|
||||
clockConfiguration.rc_temp_ctiv = LFCLK_CONF_RC_TEMP_CTIV;
|
||||
|
||||
SOFTDEVICE_HANDLER_INIT(&clockConfiguration, signalEvent);
|
||||
|
||||
// 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 = true;
|
||||
|
||||
ble_enable_params_t ble_enable_params;
|
||||
uint32_t err_code = softdevice_enable_get_default_config(CENTRAL_LINK_COUNT,
|
||||
PERIPHERAL_LINK_COUNT,
|
||||
&ble_enable_params);
|
||||
|
||||
ble_enable_params.gatts_enable_params.attr_tab_size = GATTS_ATTR_TAB_SIZE;
|
||||
ble_enable_params.gatts_enable_params.service_changed = IS_SRVC_CHANGED_CHARACT_PRESENT;
|
||||
ble_enable_params.common_enable_params.vs_uuid_count = UUID_TABLE_MAX_ENTRIES;
|
||||
|
||||
if(err_code != NRF_SUCCESS) {
|
||||
return ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
if (softdevice_enable(&ble_enable_params) != NRF_SUCCESS) {
|
||||
return ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
// Peer Manger must been initialised prior any other call to its API (this file and btle_security_pm.cpp)
|
||||
pm_init();
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
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;
|
||||
}
|
||||
#else
|
||||
ble_gap_privacy_params_t privacy_params = {0};
|
||||
privacy_params.privacy_mode = BLE_GAP_PRIVACY_MODE_OFF;
|
||||
pm_privacy_set(&privacy_params);
|
||||
#endif
|
||||
|
||||
ASSERT_STATUS( softdevice_ble_evt_handler_set(btle_handler));
|
||||
ASSERT_STATUS( softdevice_sys_evt_handler_set(sys_evt_dispatch));
|
||||
|
||||
return btle_gap_init();
|
||||
}
|
||||
|
||||
static void btle_handler(ble_evt_t *p_ble_evt)
|
||||
{
|
||||
/* Library service handlers */
|
||||
#if SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
ble_conn_params_on_ble_evt(p_ble_evt);
|
||||
#endif
|
||||
|
||||
#if (IS_LEGACY_DEVICE_MANAGER_ENABLED)
|
||||
dm_ble_evt_handler(p_ble_evt);
|
||||
#else
|
||||
// Forward BLE events to the Connection State module.
|
||||
// This must be called before any event handler that uses this module.
|
||||
ble_conn_state_on_ble_evt(p_ble_evt);
|
||||
|
||||
// Forward BLE events to the Peer Manager
|
||||
pm_on_ble_evt(p_ble_evt);
|
||||
#endif
|
||||
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
bleGattcEventHandler(p_ble_evt);
|
||||
#endif
|
||||
|
||||
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
||||
nRF5xGap &gap = (nRF5xGap &) ble.getGap();
|
||||
nRF5xGattServer &gattServer = (nRF5xGattServer &) ble.getGattServer();
|
||||
nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
|
||||
|
||||
/* 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;
|
||||
#if defined(TARGET_MCU_NRF51_16K_S110) || defined(TARGET_MCU_NRF51_32K_S110)
|
||||
/* Only peripheral role is supported by S110 */
|
||||
Gap::Role_t role = Gap::PERIPHERAL;
|
||||
#else
|
||||
Gap::Role_t role = static_cast<Gap::Role_t>(p_ble_evt->evt.gap_evt.params.connected.role);
|
||||
#endif
|
||||
gap.setConnectionHandle(handle);
|
||||
const Gap::ConnectionParams_t *params = reinterpret_cast<Gap::ConnectionParams_t *>(&(p_ble_evt->evt.gap_evt.params.connected.conn_params));
|
||||
|
||||
const ble_gap_addr_t *peer = &p_ble_evt->evt.gap_evt.params.connected.peer_addr;
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
const ble_gap_addr_t *own = &p_ble_evt->evt.gap_evt.params.connected.own_addr;
|
||||
|
||||
gap.processConnectionEvent(handle,
|
||||
role,
|
||||
static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
|
||||
static_cast<BLEProtocol::AddressType_t>(own->addr_type), own->addr,
|
||||
params);
|
||||
#else
|
||||
Gap::AddressType_t addr_type;
|
||||
Gap::Address_t own_address;
|
||||
gap.getAddress(&addr_type, own_address);
|
||||
|
||||
gap.processConnectionEvent(handle,
|
||||
role,
|
||||
static_cast<BLEProtocol::AddressType_t>(peer->addr_type), peer->addr,
|
||||
addr_type, own_address,
|
||||
params);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVT_DISCONNECTED: {
|
||||
Gap::Handle_t handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
// Since we are not in a connection and have not started advertising,
|
||||
// store bonds
|
||||
gap.setConnectionHandle (BLE_CONN_HANDLE_INVALID);
|
||||
|
||||
Gap::DisconnectionReason_t reason;
|
||||
switch (p_ble_evt->evt.gap_evt.params.disconnected.reason) {
|
||||
case BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION:
|
||||
reason = Gap::LOCAL_HOST_TERMINATED_CONNECTION;
|
||||
break;
|
||||
case BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION:
|
||||
reason = Gap::REMOTE_USER_TERMINATED_CONNECTION;
|
||||
break;
|
||||
case BLE_HCI_CONN_INTERVAL_UNACCEPTABLE:
|
||||
reason = Gap::CONN_INTERVAL_UNACCEPTABLE;
|
||||
break;
|
||||
default:
|
||||
/* Please refer to the underlying transport library for an
|
||||
* interpretion of this reason's value. */
|
||||
reason = static_cast<Gap::DisconnectionReason_t>(p_ble_evt->evt.gap_evt.params.disconnected.reason);
|
||||
break;
|
||||
}
|
||||
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
// Close all pending discoveries for this connection
|
||||
nRF5xGattClient& gattClient = ble.getGattClient();
|
||||
gattClient.characteristicDescriptorDiscoverer().terminate(handle, BLE_ERROR_INVALID_STATE);
|
||||
gattClient.discovery().terminate(handle);
|
||||
#endif
|
||||
|
||||
gap.processDisconnectionEvent(handle, reason);
|
||||
break;
|
||||
}
|
||||
|
||||
case BLE_GAP_EVT_PASSKEY_DISPLAY:
|
||||
securityManager.processPasskeyDisplayEvent(p_ble_evt->evt.gap_evt.conn_handle, p_ble_evt->evt.gap_evt.params.passkey_display.passkey);
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_TIMEOUT:
|
||||
gap.processTimeoutEvent(static_cast<Gap::TimeoutSource_t>(p_ble_evt->evt.gap_evt.params.timeout.src));
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_TIMEOUT:
|
||||
case BLE_GATTS_EVT_TIMEOUT:
|
||||
// Disconnect on GATT Server and Client timeout events.
|
||||
// ASSERT_STATUS_RET_VOID (sd_ble_gap_disconnect(m_conn_handle,
|
||||
// BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION));
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_ADV_REPORT: {
|
||||
const ble_gap_evt_adv_report_t *advReport = &p_ble_evt->evt.gap_evt.params.adv_report;
|
||||
gap.processAdvertisementReport(advReport->peer_addr.addr,
|
||||
advReport->rssi,
|
||||
advReport->scan_rsp,
|
||||
static_cast<GapAdvertisingParams::AdvertisingType_t>(advReport->type),
|
||||
advReport->dlen,
|
||||
advReport->data);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
gattServer.hwCallback(p_ble_evt);
|
||||
}
|
||||
|
||||
/*! @brief Callback when an error occurs inside the SoftDevice */
|
||||
void assert_nrf_callback(uint16_t line_num, const uint8_t *p_file_name)
|
||||
{
|
||||
ASSERT_TRUE(false, (void) 0);
|
||||
}
|
||||
|
||||
/*!
|
||||
@brief Handler for general errors above the SoftDevice layer.
|
||||
Typically we can' recover from this so we do a reset.
|
||||
*/
|
||||
void app_error_handler(uint32_t error_code, uint32_t line_num, const uint8_t *p_file_name)
|
||||
{
|
||||
ASSERT_STATUS_RET_VOID( error_code );
|
||||
NVIC_SystemReset();
|
||||
}
|
|
@ -0,0 +1,41 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BTLE_H_
|
||||
#define _BTLE_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
#include "ble_srv_common.h"
|
||||
#include "headers/ble.h"
|
||||
|
||||
error_t btle_init(void);
|
||||
|
||||
// flag indicating if events have been signaled or not
|
||||
// It is used by processEvents and signalEventsToProcess
|
||||
// signalEventsToProcess raise the flag and processEvents
|
||||
// clears it.
|
||||
extern bool isEventsSignaled;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ifndef _BTLE_H_
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef _BTLE_CLOCK_H_
|
||||
#define _BTLE_CLOCK_H_
|
||||
|
||||
#include "nrf5x_lf_clk_helper.h"
|
||||
|
||||
/**
|
||||
* @brief Module that generates settings for the low-frequency (LF) clock configuration.
|
||||
*
|
||||
* This module provides macros that are generated from the mbed config system macros.
|
||||
*
|
||||
*
|
||||
*
|
||||
* As a result, this module provides the following: @n
|
||||
* - literal value LFCLK_CONF_SOURCE @n
|
||||
* - literal value LFCLK_CONF_ACCURACY @n
|
||||
* - literal value LFCLK_CONF_RC_CTIV @n
|
||||
* - literal value LFCLK_CONF_RC_TEMP_CTIV
|
||||
*/
|
||||
|
||||
|
||||
|
||||
#include "nrf_sdm.h"
|
||||
|
||||
#define DEFAULT_LFCLK_CONF_ACCURACY NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM
|
||||
|
||||
#ifdef NRF52
|
||||
#define MAX_LFCLK_CONF_RC_CTIV 32
|
||||
#else
|
||||
#define MAX_LFCLK_CONF_RC_CTIV 64
|
||||
#endif
|
||||
|
||||
#define MAX_LFCLK_CONF_RC_TEMP_CTIV 33
|
||||
|
||||
#define DEFAULT_LFCLK_CONF_RC_CTIV 16 // Check temperature every 16 * 250ms.
|
||||
#define DEFAULT_LFCLK_CONF_RC_TEMP_CTIV 1 // Only calibrate if temperature has changed.
|
||||
|
||||
#define NRF_LF_SRC_XTAL 2
|
||||
#define NRF_LF_SRC_SYNTH 3
|
||||
#define NRF_LF_SRC_RC 4
|
||||
|
||||
#if MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC == NRF_LF_SRC_RC
|
||||
#define LFCLK_CONF_SOURCE NRF_CLOCK_LF_SRC_RC
|
||||
|
||||
#ifdef MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL
|
||||
#define LFCLK_CONF_RC_CTIV MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL
|
||||
#else
|
||||
#define LFCLK_CONF_RC_CTIV DEFAULT_LFCLK_CONF_RC_CTIV
|
||||
#endif
|
||||
|
||||
#ifdef MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG
|
||||
#define LFCLK_CONF_RC_TEMP_CTIV MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG
|
||||
#else
|
||||
#define LFCLK_CONF_RC_TEMP_CTIV DEFAULT_LFCLK_CONF_RC_TEMP_CTIV
|
||||
#endif
|
||||
|
||||
#if (LFCLK_CONF_RC_CTIV < 1) || (LFCLK_CONF_RC_CTIV > MAX_LFCLK_CONF_RC_CTIV)
|
||||
#error Calibration timer interval out of range!
|
||||
#endif
|
||||
|
||||
#if (LFCLK_CONF_RC_TEMP_CTIV < 0 ) || (LFCLK_CONF_RC_TEMP_CTIV > 33)
|
||||
#error Number/mode of LF RC calibration intervals out of range!
|
||||
#endif
|
||||
|
||||
#elif MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC == NRF_LF_SRC_SYNTH
|
||||
#define LFCLK_CONF_SOURCE NRF_CLOCK_LF_SRC_SYNTH
|
||||
#define LFCLK_CONF_RC_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
|
||||
#define LFCLK_CONF_RC_TEMP_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
|
||||
|
||||
#ifdef MBED_CONF_NORDIC_LF_CLOCK_HF_SYNTH_ACCURACY
|
||||
#define LFCLK_CONF_ACCURACY MBED_CONF_NORDIC_LF_CLOCK_HF_SYNTH_ACCURACY
|
||||
#endif
|
||||
|
||||
#else // default is NRF_LF_SRC_SYNTH
|
||||
#define LFCLK_CONF_SOURCE NRF_CLOCK_LF_SRC_XTAL
|
||||
#define LFCLK_CONF_RC_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
|
||||
#define LFCLK_CONF_RC_TEMP_CTIV 0 // Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
|
||||
|
||||
#ifdef MBED_CONF_NORDIC_LF_CLOCK_XTAL_ACCURACY
|
||||
#define LFCLK_CONF_ACCURACY MBED_CONF_NORDIC_LF_CLOCK_XTAL_ACCURACY
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifndef LFCLK_CONF_ACCURACY
|
||||
#define LFCLK_CONF_ACCURACY DEFAULT_LFCLK_CONF_ACCURACY
|
||||
#endif
|
||||
|
||||
#if (LFCLK_CONF_ACCURACY > NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM) || (LFCLK_CONF_ACCURACY < NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM)
|
||||
#error Low frequency clock accuracy out of range!
|
||||
#endif
|
||||
|
||||
|
||||
#endif //_BTLE_CLOCK_H_
|
||||
|
||||
|
|
@ -0,0 +1,146 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nRF5xServiceDiscovery.h"
|
||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
||||
#include "nRF5xGattClient.h"
|
||||
#include "nRF5xn.h"
|
||||
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
void bleGattcEventHandler(const ble_evt_t *p_ble_evt)
|
||||
{
|
||||
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
||||
nRF5xGattClient &gattClient = (nRF5xGattClient &) ble.getGattClient();
|
||||
nRF5xServiceDiscovery &sdSingleton = gattClient.discovery();
|
||||
nRF5xCharacteristicDescriptorDiscoverer &characteristicDescriptorDiscoverer =
|
||||
gattClient.characteristicDescriptorDiscoverer();
|
||||
|
||||
switch (p_ble_evt->header.evt_id) {
|
||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||
switch (p_ble_evt->evt.gattc_evt.gatt_status) {
|
||||
case BLE_GATT_STATUS_SUCCESS:
|
||||
sdSingleton.setupDiscoveredServices(&p_ble_evt->evt.gattc_evt.params.prim_srvc_disc_rsp);
|
||||
break;
|
||||
|
||||
case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
|
||||
default:
|
||||
sdSingleton.terminate();
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
||||
switch (p_ble_evt->evt.gattc_evt.gatt_status) {
|
||||
case BLE_GATT_STATUS_SUCCESS:
|
||||
sdSingleton.setupDiscoveredCharacteristics(&p_ble_evt->evt.gattc_evt.params.char_disc_rsp);
|
||||
break;
|
||||
|
||||
case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
|
||||
default:
|
||||
sdSingleton.terminateCharacteristicDiscovery(BLE_ERROR_NONE);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP:
|
||||
if (sdSingleton.isActive()) {
|
||||
sdSingleton.processDiscoverUUIDResponse(&p_ble_evt->evt.gattc_evt);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_READ_RSP: {
|
||||
GattReadCallbackParams response = {
|
||||
.connHandle = p_ble_evt->evt.gattc_evt.conn_handle,
|
||||
.handle = p_ble_evt->evt.gattc_evt.params.read_rsp.handle,
|
||||
.offset = p_ble_evt->evt.gattc_evt.params.read_rsp.offset,
|
||||
.len = p_ble_evt->evt.gattc_evt.params.read_rsp.len,
|
||||
.data = p_ble_evt->evt.gattc_evt.params.read_rsp.data,
|
||||
};
|
||||
gattClient.processReadResponse(&response);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_WRITE_RSP: {
|
||||
GattWriteCallbackParams response = {
|
||||
.connHandle = p_ble_evt->evt.gattc_evt.conn_handle,
|
||||
.handle = p_ble_evt->evt.gattc_evt.params.write_rsp.handle,
|
||||
.writeOp = (GattWriteCallbackParams::WriteOp_t)(p_ble_evt->evt.gattc_evt.params.write_rsp.write_op),
|
||||
.offset = p_ble_evt->evt.gattc_evt.params.write_rsp.offset,
|
||||
.len = p_ble_evt->evt.gattc_evt.params.write_rsp.len,
|
||||
.data = p_ble_evt->evt.gattc_evt.params.write_rsp.data,
|
||||
};
|
||||
gattClient.processWriteResponse(&response);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_HVX: {
|
||||
GattHVXCallbackParams params;
|
||||
params.connHandle = p_ble_evt->evt.gattc_evt.conn_handle;
|
||||
params.handle = p_ble_evt->evt.gattc_evt.params.hvx.handle;
|
||||
params.type = static_cast<HVXType_t>(p_ble_evt->evt.gattc_evt.params.hvx.type);
|
||||
params.len = p_ble_evt->evt.gattc_evt.params.hvx.len;
|
||||
params.data = p_ble_evt->evt.gattc_evt.params.hvx.data;
|
||||
|
||||
gattClient.processHVXEvent(¶ms);
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_DESC_DISC_RSP: {
|
||||
uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
|
||||
uint16_t status = p_ble_evt->evt.gattc_evt.gatt_status;
|
||||
const ble_gattc_evt_desc_disc_rsp_t& discovered_descriptors = p_ble_evt->evt.gattc_evt.params.desc_disc_rsp;
|
||||
|
||||
switch(status) {
|
||||
case BLE_GATT_STATUS_SUCCESS:
|
||||
characteristicDescriptorDiscoverer.process(
|
||||
conn_handle,
|
||||
discovered_descriptors
|
||||
);
|
||||
break;
|
||||
case BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND:
|
||||
// end of discovery
|
||||
characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_NONE);
|
||||
break;
|
||||
default:
|
||||
characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_UNSPECIFIED);
|
||||
break;
|
||||
}
|
||||
} break;
|
||||
|
||||
case BLE_GATTC_EVT_ATTR_INFO_DISC_RSP : {
|
||||
uint16_t conn_handle = p_ble_evt->evt.gattc_evt.conn_handle;
|
||||
uint16_t status = p_ble_evt->evt.gattc_evt.gatt_status;
|
||||
const ble_gattc_evt_attr_info_disc_rsp_t& infos = p_ble_evt->evt.gattc_evt.params.attr_info_disc_rsp;
|
||||
|
||||
switch(status) {
|
||||
case BLE_GATT_STATUS_SUCCESS:
|
||||
characteristicDescriptorDiscoverer.processAttributeInformation(
|
||||
conn_handle,
|
||||
infos
|
||||
);
|
||||
break;
|
||||
default:
|
||||
characteristicDescriptorDiscoverer.terminate(conn_handle, BLE_ERROR_UNSPECIFIED);
|
||||
break;
|
||||
}
|
||||
|
||||
} break;
|
||||
}
|
||||
|
||||
sdSingleton.progressCharacteristicDiscovery();
|
||||
sdSingleton.progressServiceDiscovery();
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,22 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BTLE_DISCOVERY_H_
|
||||
#define _BTLE_DISCOVERY_H_
|
||||
|
||||
void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
|
||||
|
||||
#endif /*_BTLE_DISCOVERY_H_*/
|
|
@ -0,0 +1,99 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "common/common.h"
|
||||
|
||||
#include "ble_gap.h"
|
||||
#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
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Initialise GAP in the underlying SoftDevice
|
||||
|
||||
@returns
|
||||
*/
|
||||
/**************************************************************************/
|
||||
error_t btle_gap_init(void)
|
||||
{
|
||||
ble_gap_conn_params_t gap_conn_params = {0};
|
||||
|
||||
gap_conn_params.min_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MIN_INTERVAL_MS); // in 1.25ms units
|
||||
gap_conn_params.max_conn_interval = msec_to_1_25msec(CFG_GAP_CONNECTION_MAX_INTERVAL_MS); // in 1.25ms unit
|
||||
gap_conn_params.slave_latency = CFG_GAP_CONNECTION_SLAVE_LATENCY;
|
||||
gap_conn_params.conn_sup_timeout = CFG_GAP_CONNECTION_SUPERVISION_TIMEOUT_MS / 10; // in 10ms unit
|
||||
|
||||
ble_gap_conn_sec_mode_t sec_mode;
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&sec_mode); // no security is needed
|
||||
|
||||
ASSERT_STATUS( sd_ble_gap_device_name_set(&sec_mode, (const uint8_t *) CFG_GAP_LOCAL_NAME, strlen(CFG_GAP_LOCAL_NAME)));
|
||||
ASSERT_STATUS( sd_ble_gap_appearance_set(CFG_GAP_APPEARANCE));
|
||||
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),
|
||||
NEXT_UPDATE_DELAY = APP_TIMER_TICKS(5000, CFG_TIMER_PRESCALER),
|
||||
MAX_UPDATE_COUNT = 3
|
||||
};
|
||||
|
||||
ble_conn_params_init_t cp_init = {0};
|
||||
|
||||
cp_init.p_conn_params = NULL;
|
||||
cp_init.first_conn_params_update_delay = FIRST_UPDATE_DELAY;
|
||||
cp_init.next_conn_params_update_delay = NEXT_UPDATE_DELAY;
|
||||
cp_init.max_conn_params_update_count = MAX_UPDATE_COUNT;
|
||||
cp_init.start_on_notify_cccd_handle = BLE_GATT_HANDLE_INVALID;
|
||||
cp_init.disconnect_on_fail = true;
|
||||
cp_init.evt_handler = NULL;
|
||||
cp_init.error_handler = error_callback;
|
||||
|
||||
ASSERT_STATUS ( ble_conn_params_init(&cp_init));
|
||||
#endif // SDK_CONN_PARAMS_MODULE_ENABLE
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Converts msecs to an integer representing 1.25ms units
|
||||
|
||||
@param[in] ms
|
||||
The number of milliseconds to conver to 1.25ms units
|
||||
|
||||
@returns The number of 1.25ms units in the supplied number of ms
|
||||
*/
|
||||
/**************************************************************************/
|
||||
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
|
|
@ -0,0 +1,24 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BTLE_GAP_H_
|
||||
#define _BTLE_GAP_H_
|
||||
|
||||
#include "common/common.h"
|
||||
|
||||
error_t btle_gap_init(void);
|
||||
|
||||
#endif // ifndef _BTLE_GAP_H_
|
|
@ -0,0 +1,326 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#if defined(S110)
|
||||
#include "btle.h"
|
||||
|
||||
#include "nRF5xn.h"
|
||||
|
||||
extern "C" {
|
||||
#include "pstorage.h"
|
||||
#include "device_manager.h"
|
||||
#include "id_manager.h"
|
||||
}
|
||||
|
||||
#include "btle_security.h"
|
||||
|
||||
static dm_application_instance_t applicationInstance;
|
||||
static bool initialized = false;
|
||||
static ret_code_t dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result);
|
||||
|
||||
// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11.
|
||||
static ble_gap_sec_params_t securityParameters = {
|
||||
.bond = true, /**< Perform bonding. */
|
||||
.mitm = true, /**< Man In The Middle protection required. */
|
||||
.lesc = false, /**< Enable LE Secure Connection pairing. */
|
||||
.keypress = false, /**< Enable generation of keypress notifications. */
|
||||
.io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
|
||||
.oob = 0, /**< Out Of Band data available. */
|
||||
.min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
|
||||
.max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */
|
||||
.kdist_own = {
|
||||
.enc = 0, /**< Long Term Key and Master Identification. */
|
||||
.id = 0, /**< Identity Resolving Key and Identity Address Information. */
|
||||
.sign = 0, /**< Connection Signature Resolving Key. */
|
||||
.link = 0 /**< Derive the Link Key from the LTK. */
|
||||
}, /**< Key distribution bitmap: keys that the local device will distribute. */
|
||||
.kdist_peer = {
|
||||
.enc = 1, /**< Long Term Key and Master Identification. */
|
||||
.id = 1, /**< Identity Resolving Key and Identity Address Information. */
|
||||
.sign = 1, /**< Connection Signature Resolving Key. */
|
||||
.link = 0 /**< Derive the Link Key from the LTK. */
|
||||
} /**< Key distribution bitmap: keys that the peripheral device will distribute. */
|
||||
};
|
||||
|
||||
bool
|
||||
btle_hasInitializedSecurity(void)
|
||||
{
|
||||
return initialized;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_initializeSecurity(bool enableBonding,
|
||||
bool requireMITM,
|
||||
SecurityManager::SecurityIOCapabilities_t iocaps,
|
||||
const SecurityManager::Passkey_t passkey)
|
||||
{
|
||||
/* guard against multiple initializations */
|
||||
if (initialized) {
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
if (pstorage_init() != NRF_SUCCESS) {
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
ret_code_t rc;
|
||||
if (passkey) {
|
||||
ble_opt_t opts;
|
||||
opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey);
|
||||
if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) {
|
||||
switch (rc) {
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
case NRF_ERROR_INVALID_PARAM:
|
||||
default:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
case NRF_ERROR_BUSY:
|
||||
return BLE_STACK_BUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
dm_init_param_t dm_init_param = {
|
||||
.clear_persistent_data = false /* Set to true in case the module should clear all persistent data. */
|
||||
};
|
||||
if (dm_init(&dm_init_param) != NRF_SUCCESS) {
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
// update default security parameters with function call parameters
|
||||
securityParameters.bond = enableBonding;
|
||||
securityParameters.mitm = requireMITM;
|
||||
securityParameters.io_caps = iocaps;
|
||||
|
||||
const dm_application_param_t dm_param = {
|
||||
.evt_handler = dm_handler,
|
||||
.service_type = DM_PROTOCOL_CNTXT_GATT_CLI_ID,
|
||||
.sec_param = securityParameters
|
||||
};
|
||||
|
||||
if ((rc = dm_register(&applicationInstance, &dm_param)) != NRF_SUCCESS) {
|
||||
switch (rc) {
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
case NRF_ERROR_NO_MEM:
|
||||
return BLE_ERROR_NO_MEM;
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_purgeAllBondingState(void)
|
||||
{
|
||||
ret_code_t rc;
|
||||
if ((rc = dm_device_delete_all(&applicationInstance)) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
case NRF_ERROR_NO_MEM:
|
||||
return BLE_ERROR_NO_MEM;
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP)
|
||||
{
|
||||
ret_code_t rc;
|
||||
dm_handle_t dmHandle = {
|
||||
.appl_id = applicationInstance,
|
||||
};
|
||||
if ((rc = dm_handle_get(connectionHandle, &dmHandle)) != NRF_SUCCESS) {
|
||||
if (rc == NRF_ERROR_NOT_FOUND) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
} else {
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
if ((rc = dm_security_status_req(&dmHandle, reinterpret_cast<dm_security_status_t *>(securityStatusP))) != NRF_SUCCESS) {
|
||||
switch (rc) {
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
case NRF_ERROR_NO_MEM:
|
||||
return BLE_ERROR_NO_MEM;
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode)
|
||||
{
|
||||
// use default and updated parameters as starting point
|
||||
// and modify structure based on security mode.
|
||||
ble_gap_sec_params_t params = securityParameters;
|
||||
|
||||
switch (securityMode) {
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK:
|
||||
/**< Require no protection, open link. */
|
||||
securityParameters.bond = false;
|
||||
securityParameters.mitm = false;
|
||||
break;
|
||||
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM:
|
||||
/**< Require encryption, but no MITM protection. */
|
||||
securityParameters.bond = true;
|
||||
securityParameters.mitm = false;
|
||||
break;
|
||||
|
||||
// not yet implemented security modes
|
||||
case SecurityManager::SECURITY_MODE_NO_ACCESS:
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM:
|
||||
/**< Require encryption and MITM protection. */
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM:
|
||||
/**< Require signing or encryption, but no MITM protection. */
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM:
|
||||
/**< Require signing or encryption, and MITM protection. */
|
||||
default:
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// update security settings for given connection
|
||||
uint32_t result = sd_ble_gap_authenticate(connectionHandle, ¶ms);
|
||||
|
||||
if (result == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else {
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
ret_code_t
|
||||
dm_handler(dm_handle_t const *p_handle, dm_event_t const *p_event, ret_code_t event_result)
|
||||
{
|
||||
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
||||
nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
|
||||
|
||||
switch (p_event->event_id) {
|
||||
case DM_EVT_SECURITY_SETUP: /* started */ {
|
||||
const ble_gap_sec_params_t *peerParams = &p_event->event_param.p_gap_param->params.sec_params_request.peer_params;
|
||||
securityManager.processSecuritySetupInitiatedEvent(p_event->event_param.p_gap_param->conn_handle,
|
||||
peerParams->bond,
|
||||
peerParams->mitm,
|
||||
(SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps);
|
||||
break;
|
||||
}
|
||||
case DM_EVT_SECURITY_SETUP_COMPLETE:
|
||||
securityManager.
|
||||
processSecuritySetupCompletedEvent(p_event->event_param.p_gap_param->conn_handle,
|
||||
(SecurityManager::SecurityCompletionStatus_t)(p_event->event_param.p_gap_param->params.auth_status.auth_status));
|
||||
break;
|
||||
case DM_EVT_LINK_SECURED: {
|
||||
unsigned securityMode = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.sm;
|
||||
unsigned level = p_event->event_param.p_gap_param->params.conn_sec_update.conn_sec.sec_mode.lv;
|
||||
SecurityManager::SecurityMode_t resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS;
|
||||
switch (securityMode) {
|
||||
case 1:
|
||||
switch (level) {
|
||||
case 1:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK;
|
||||
break;
|
||||
case 2:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
|
||||
break;
|
||||
case 3:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (level) {
|
||||
case 1:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM;
|
||||
break;
|
||||
case 2:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
securityManager.processLinkSecuredEvent(p_event->event_param.p_gap_param->conn_handle, resolvedSecurityMode);
|
||||
break;
|
||||
}
|
||||
case DM_EVT_DEVICE_CONTEXT_STORED:
|
||||
securityManager.processSecurityContextStoredEvent(p_event->event_param.p_gap_param->conn_handle);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist)
|
||||
{
|
||||
if (!btle_hasInitializedSecurity()) {
|
||||
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
}
|
||||
ret_code_t err = dm_whitelist_create(&applicationInstance, p_whitelist);
|
||||
if (err == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else if (err == NRF_ERROR_NULL) {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
} else {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool
|
||||
btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk)
|
||||
{
|
||||
/*
|
||||
* Use a helper function from the Nordic SDK to test whether the BLE
|
||||
* address can be generated using the IRK.
|
||||
*/
|
||||
return im_address_resolve(p_addr, p_irk);
|
||||
}
|
||||
|
||||
void
|
||||
btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address)
|
||||
{
|
||||
/* Set type to resolvable */
|
||||
address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
|
||||
|
||||
/*
|
||||
* Assign a random number to the most significant 3 bytes
|
||||
* of the address.
|
||||
*/
|
||||
address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E;
|
||||
address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F;
|
||||
address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C;
|
||||
|
||||
/* Calculate the hash and store it in the top half of the address */
|
||||
ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,130 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _BTLE_SECURITY_H_
|
||||
#define _BTLE_SECURITY_H_
|
||||
|
||||
#include "ble/Gap.h"
|
||||
#include "ble/SecurityManager.h"
|
||||
|
||||
/**
|
||||
* Function to test whether the SecurityManager has been initialized.
|
||||
* Possible by a call to @ref btle_initializeSecurity().
|
||||
*
|
||||
* @return True if the SecurityManager was previously initialized, false
|
||||
* otherwise.
|
||||
*/
|
||||
bool btle_hasInitializedSecurity(void);
|
||||
|
||||
/**
|
||||
* Enable Nordic's Device Manager, which brings in functionality from the
|
||||
* stack's Security Manager. The Security Manager implements the actual
|
||||
* cryptographic algorithms and protocol exchanges that allow two devices to
|
||||
* securely exchange data and privately detect each other.
|
||||
*
|
||||
* @param[in] enableBonding Allow for bonding.
|
||||
* @param[in] requireMITM Require protection for man-in-the-middle attacks.
|
||||
* @param[in] iocaps To specify IO capabilities of this peripheral,
|
||||
* such as availability of a display or keyboard to
|
||||
* support out-of-band exchanges of security data.
|
||||
* @param[in] passkey To specify a static passkey.
|
||||
*
|
||||
* @return BLE_ERROR_NONE on success.
|
||||
*/
|
||||
ble_error_t btle_initializeSecurity(bool enableBonding = true,
|
||||
bool requireMITM = true,
|
||||
SecurityManager::SecurityIOCapabilities_t iocaps = SecurityManager::IO_CAPS_NONE,
|
||||
const SecurityManager::Passkey_t passkey = NULL);
|
||||
|
||||
/**
|
||||
* Get the security status of a link.
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* Handle to identify the connection.
|
||||
* @param[out] securityStatusP
|
||||
* security status.
|
||||
*
|
||||
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
|
||||
*/
|
||||
ble_error_t btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP);
|
||||
|
||||
/**
|
||||
* Set the security mode on a connection. Useful for elevating the security mode
|
||||
* once certain conditions are met, e.g., a particular service is found.
|
||||
*
|
||||
* @param[in] connectionHandle
|
||||
* Handle to identify the connection.
|
||||
* @param[in] securityMode
|
||||
* security mode.
|
||||
*
|
||||
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
|
||||
*/
|
||||
ble_error_t btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode);
|
||||
|
||||
/**
|
||||
* Function for deleting all peer device context and all related bonding
|
||||
* information from the database.
|
||||
*
|
||||
* @retval BLE_ERROR_NONE On success, else an error code indicating reason for failure.
|
||||
* @retval BLE_ERROR_INVALID_STATE If the API is called without module initialization and/or
|
||||
* application registration.
|
||||
*/
|
||||
ble_error_t btle_purgeAllBondingState(void);
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
/**
|
||||
* Query the SoftDevice bond table to extract a whitelist containing the BLE
|
||||
* addresses and IRKs of bonded devices.
|
||||
*
|
||||
* @param[in/out] p_whitelist
|
||||
* (on input) p_whitelist->addr_count and
|
||||
* p_whitelist->irk_count specify the maximum number of
|
||||
* addresses and IRKs added to the whitelist structure.
|
||||
* (on output) *p_whitelist is a whitelist containing the
|
||||
* addresses and IRKs of the bonded devices.
|
||||
*
|
||||
* @return BLE_ERROR_NONE Or appropriate error code indicating reason for failure.
|
||||
*/
|
||||
ble_error_t btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* Function to test whether a BLE address is generated using an IRK.
|
||||
*
|
||||
* @param[in] p_addr
|
||||
* Pointer to a BLE address.
|
||||
* @param[in] p_irk
|
||||
* Pointer to an IRK.
|
||||
*
|
||||
* @return True if p_addr can be generated using p_irk, false otherwise.
|
||||
*/
|
||||
bool btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk);
|
||||
|
||||
/**
|
||||
* Function to generate a private resolvable BLE address.
|
||||
*
|
||||
* @param[out] p_addr
|
||||
* The output address.
|
||||
* @param[in] p_irk
|
||||
* A reference to a IRK.
|
||||
*
|
||||
* @note This function does not generate a secure address since the prand number in the
|
||||
* resolvable address is not truly random. Therefore, the output of this function
|
||||
* is only meant to be used by the application internally but never exported.
|
||||
*/
|
||||
void btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address);
|
||||
|
||||
#endif /* _BTLE_SECURITY_H_ */
|
|
@ -0,0 +1,437 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#if defined(S130) || defined(S132) || defined(S140)
|
||||
#include "btle.h"
|
||||
|
||||
#include "nRF5xn.h"
|
||||
|
||||
extern "C" {
|
||||
#include "peer_manager.h"
|
||||
#include "id_manager.h"
|
||||
#include "fds.h"
|
||||
}
|
||||
|
||||
#include "btle_security.h"
|
||||
|
||||
static bool initialized = false;
|
||||
|
||||
static void pm_handler(pm_evt_t const *p_event);
|
||||
static bool _enc_in_progress = false; // helper flag for distinguish between state of link connected and link connected in progres of encryption establishing.
|
||||
volatile static uint32_t async_ret_code; // busy loop support variable for asyncronous API.
|
||||
|
||||
// default security parameters. Avoid "holes" between member assigments in order to compile by gcc++11.
|
||||
static ble_gap_sec_params_t securityParameters = {
|
||||
.bond = true, /**< Perform bonding. */
|
||||
.mitm = true, /**< Man In The Middle protection required. */
|
||||
.lesc = false, /**< Enable LE Secure Connection pairing. */
|
||||
.keypress = false, /**< Enable generation of keypress notifications. */
|
||||
.io_caps = SecurityManager::IO_CAPS_NONE, /**< IO capabilities, see @ref BLE_GAP_IO_CAPS. */
|
||||
.oob = 0, /**< Out Of Band data available. */
|
||||
.min_key_size = 16, /**< Minimum encryption key size in octets between 7 and 16. If 0 then not applicable in this instance. */
|
||||
.max_key_size = 16, /**< Maximum encryption key size in octets between min_key_size and 16. */
|
||||
.kdist_own = {
|
||||
.enc = 0, /**< Long Term Key and Master Identification. */
|
||||
.id = 0, /**< Identity Resolving Key and Identity Address Information. */
|
||||
.sign = 0, /**< Connection Signature Resolving Key. */
|
||||
.link = 0 /**< Derive the Link Key from the LTK. */
|
||||
}, /**< Key distribution bitmap: keys that the local device will distribute. */
|
||||
.kdist_peer = {
|
||||
.enc = 1, /**< Long Term Key and Master Identification. */
|
||||
.id = 1, /**< Identity Resolving Key and Identity Address Information. */
|
||||
.sign = 0, /**< Connection Signature Resolving Key. */
|
||||
.link = 0 /**< Derive the Link Key from the LTK. */
|
||||
} /**< Key distribution bitmap: keys that the peripheral device will distribute. */
|
||||
};
|
||||
|
||||
bool
|
||||
btle_hasInitializedSecurity(void)
|
||||
{
|
||||
return initialized;
|
||||
}
|
||||
|
||||
|
||||
ble_error_t
|
||||
btle_initializeSecurity(bool enableBonding,
|
||||
bool requireMITM,
|
||||
SecurityManager::SecurityIOCapabilities_t iocaps,
|
||||
const SecurityManager::Passkey_t passkey)
|
||||
{
|
||||
/* guard against multiple initializations */
|
||||
if (initialized) {
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ret_code_t rc;
|
||||
if (passkey) {
|
||||
ble_opt_t opts;
|
||||
opts.gap_opt.passkey.p_passkey = const_cast<uint8_t *>(passkey);
|
||||
if ((rc = sd_ble_opt_set(BLE_GAP_OPT_PASSKEY, &opts)) != NRF_SUCCESS) {
|
||||
switch (rc) {
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
case NRF_ERROR_INVALID_PARAM:
|
||||
default:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
case NRF_ERROR_BUSY:
|
||||
return BLE_STACK_BUSY;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// update default security parameters with function call parameters
|
||||
securityParameters.bond = enableBonding;
|
||||
securityParameters.mitm = requireMITM;
|
||||
securityParameters.io_caps = iocaps;
|
||||
|
||||
if (enableBonding) {
|
||||
securityParameters.kdist_own.enc = 1;
|
||||
securityParameters.kdist_own.id = 1;
|
||||
} else {
|
||||
securityParameters.kdist_own.enc = 0;
|
||||
securityParameters.kdist_own.id = 0;
|
||||
}
|
||||
rc = pm_sec_params_set(&securityParameters);
|
||||
|
||||
if (rc == NRF_SUCCESS) {
|
||||
rc = pm_register(pm_handler);
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
case NRF_SUCCESS:
|
||||
initialized = true;
|
||||
return BLE_ERROR_NONE;
|
||||
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
|
||||
case NRF_ERROR_INVALID_PARAM:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
|
||||
initialized = true;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_purgeAllBondingState(void)
|
||||
{
|
||||
ret_code_t rc;
|
||||
|
||||
async_ret_code = NRF_ERROR_BUSY;
|
||||
|
||||
rc = pm_peers_delete(); // it is asynhronous API
|
||||
|
||||
if (rc == NRF_SUCCESS)
|
||||
{
|
||||
// waiting for respond from pm_handler
|
||||
while (async_ret_code == NRF_ERROR_BUSY) {
|
||||
// busy-loop
|
||||
}
|
||||
|
||||
rc = async_ret_code;
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
case NRF_SUCCESS:
|
||||
return BLE_ERROR_NONE;
|
||||
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_getLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::LinkSecurityStatus_t *securityStatusP)
|
||||
{
|
||||
ret_code_t rc;
|
||||
pm_conn_sec_status_t conn_sec_status;
|
||||
|
||||
rc = pm_conn_sec_status_get(connectionHandle, &conn_sec_status);
|
||||
|
||||
if (rc == NRF_SUCCESS)
|
||||
{
|
||||
if (conn_sec_status.encrypted) {
|
||||
*securityStatusP = SecurityManager::ENCRYPTED;
|
||||
}
|
||||
else if (conn_sec_status.connected) {
|
||||
if (_enc_in_progress) {
|
||||
*securityStatusP = SecurityManager::ENCRYPTION_IN_PROGRESS;
|
||||
}
|
||||
else {
|
||||
*securityStatusP = SecurityManager::NOT_ENCRYPTED;
|
||||
}
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t
|
||||
btle_setLinkSecurity(Gap::Handle_t connectionHandle, SecurityManager::SecurityMode_t securityMode)
|
||||
{
|
||||
// use default and updated parameters as starting point
|
||||
// and modify structure based on security mode.
|
||||
ret_code_t rc;
|
||||
|
||||
switch (securityMode) {
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK:
|
||||
/**< Require no protection, open link. */
|
||||
securityParameters.bond = false;
|
||||
securityParameters.mitm = false;
|
||||
securityParameters.kdist_own.enc = 0;
|
||||
break;
|
||||
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM:
|
||||
/**< Require encryption, but no MITM protection. */
|
||||
securityParameters.bond = true;
|
||||
securityParameters.mitm = false;
|
||||
securityParameters.kdist_own.enc = 1;
|
||||
break;
|
||||
|
||||
// not yet implemented security modes
|
||||
case SecurityManager::SECURITY_MODE_NO_ACCESS:
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM:
|
||||
/**< Require encryption and MITM protection. */
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM:
|
||||
/**< Require signing or encryption, but no MITM protection. */
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM:
|
||||
/**< Require signing or encryption, and MITM protection. */
|
||||
default:
|
||||
return BLE_ERROR_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
// update security settings for given connection
|
||||
|
||||
rc = pm_sec_params_set(&securityParameters);
|
||||
|
||||
if (rc == NRF_SUCCESS) {
|
||||
rc = pm_conn_secure(connectionHandle, false);
|
||||
}
|
||||
|
||||
switch (rc) {
|
||||
case NRF_SUCCESS:
|
||||
initialized = true;
|
||||
return BLE_ERROR_NONE;
|
||||
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
|
||||
case NRF_ERROR_INVALID_PARAM:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void pm_handler(pm_evt_t const *p_event)
|
||||
{
|
||||
nRF5xn &ble = nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
||||
nRF5xSecurityManager &securityManager = (nRF5xSecurityManager &) ble.getSecurityManager();
|
||||
ret_code_t err_code;
|
||||
SecurityManager::SecurityMode_t resolvedSecurityMode;
|
||||
|
||||
switch (p_event->evt_id) {
|
||||
case PM_EVT_CONN_SEC_START: /* started */ {
|
||||
const ble_gap_sec_params_t *peerParams = &securityParameters;
|
||||
securityManager.processSecuritySetupInitiatedEvent(p_event->conn_handle,
|
||||
peerParams->bond,
|
||||
peerParams->mitm,
|
||||
(SecurityManager::SecurityIOCapabilities_t)peerParams->io_caps);
|
||||
_enc_in_progress = true;
|
||||
break;
|
||||
}
|
||||
case PM_EVT_CONN_SEC_SUCCEEDED:
|
||||
// Update the rank of the peer.
|
||||
if (p_event->params.conn_sec_succeeded.procedure == PM_LINK_SECURED_PROCEDURE_BONDING)
|
||||
{
|
||||
err_code = pm_peer_rank_highest(p_event->peer_id);
|
||||
}
|
||||
|
||||
securityManager.
|
||||
processSecuritySetupCompletedEvent(p_event->conn_handle,
|
||||
SecurityManager::SEC_STATUS_SUCCESS);// SEC_STATUS_SUCCESS of SecurityCompletionStatus_t
|
||||
|
||||
ble_gap_conn_sec_t conn_sec;
|
||||
sd_ble_gap_conn_sec_get(p_event->conn_handle, &conn_sec);
|
||||
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_NO_ACCESS;
|
||||
|
||||
switch (conn_sec.sec_mode.sm) {
|
||||
case 1:
|
||||
switch (conn_sec.sec_mode.lv) {
|
||||
case 1:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK;
|
||||
break;
|
||||
case 2:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM;
|
||||
break;
|
||||
case 3:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
switch (conn_sec.sec_mode.lv) {
|
||||
case 1:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_NO_MITM;
|
||||
break;
|
||||
case 2:
|
||||
resolvedSecurityMode = SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
securityManager.processLinkSecuredEvent(p_event->conn_handle, resolvedSecurityMode);
|
||||
|
||||
_enc_in_progress = false;
|
||||
break;
|
||||
|
||||
case PM_EVT_CONN_SEC_FAILED:
|
||||
SecurityManager::SecurityCompletionStatus_t securityCompletionStatus;
|
||||
|
||||
if ((uint32_t)p_event->params.conn_sec_failed.error >= PM_CONN_SEC_ERROR_BASE ) {
|
||||
securityCompletionStatus = SecurityManager::SEC_STATUS_UNSPECIFIED;
|
||||
} else {
|
||||
securityCompletionStatus =
|
||||
(SecurityManager::SecurityCompletionStatus_t)p_event->params.conn_sec_failed.error;
|
||||
}
|
||||
|
||||
securityManager.
|
||||
processSecuritySetupCompletedEvent(p_event->conn_handle, securityCompletionStatus);
|
||||
|
||||
_enc_in_progress = false;
|
||||
break;
|
||||
|
||||
case PM_EVT_BONDED_PEER_CONNECTED:
|
||||
pm_peer_rank_highest(p_event->peer_id);
|
||||
break;
|
||||
|
||||
case PM_EVT_PEER_DATA_UPDATE_SUCCEEDED:
|
||||
if (p_event->params.peer_data_update_succeeded.action == PM_PEER_DATA_OP_UPDATE)
|
||||
{
|
||||
securityManager.processSecurityContextStoredEvent(p_event->conn_handle);
|
||||
}
|
||||
break;
|
||||
|
||||
case PM_EVT_PEER_DATA_UPDATE_FAILED:
|
||||
break;
|
||||
|
||||
case PM_EVT_PEERS_DELETE_SUCCEEDED:
|
||||
async_ret_code = NRF_SUCCESS; // respond SUCCESS to the busy-loop in f. btle_purgeAllBondingState
|
||||
break;
|
||||
|
||||
case PM_EVT_PEERS_DELETE_FAILED:
|
||||
async_ret_code = NRF_ERROR_INTERNAL; // respond FAILURE to the busy-loop in f. btle_purgeAllBondingState
|
||||
break;
|
||||
|
||||
case PM_EVT_STORAGE_FULL:
|
||||
// Run garbage collection on the flash.
|
||||
err_code = fds_gc();
|
||||
if (err_code == FDS_ERR_BUSY || err_code == FDS_ERR_NO_SPACE_IN_QUEUES)
|
||||
{
|
||||
// Retry.
|
||||
}
|
||||
else
|
||||
{
|
||||
APP_ERROR_CHECK(err_code);
|
||||
}
|
||||
break;//PM_EVT_STORAGE_FULL
|
||||
|
||||
case PM_EVT_CONN_SEC_CONFIG_REQ:{
|
||||
// A connected peer (central) is trying to pair, but the Peer Manager already has a bond
|
||||
// for that peer. Setting allow_repairing to false rejects the pairing request.
|
||||
// If this event is ignored (pm_conn_sec_config_reply is not called in the event
|
||||
// handler), the Peer Manager assumes allow_repairing to be false.
|
||||
pm_conn_sec_config_t conn_sec_config = {.allow_repairing = true};
|
||||
pm_conn_sec_config_reply(p_event->conn_handle, &conn_sec_config);
|
||||
}
|
||||
break;//PM_EVT_CONN_SEC_CONFIG_REQ
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
ble_error_t
|
||||
btle_createWhitelistFromBondTable(ble_gap_whitelist_t *p_whitelist)
|
||||
{
|
||||
if (!btle_hasInitializedSecurity()) {
|
||||
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
}
|
||||
ret_code_t err = pm_whitelist_create( NULL, BLE_GAP_WHITELIST_ADDR_MAX_COUNT, p_whitelist);
|
||||
if (err == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
} else if (err == NRF_ERROR_NULL) {
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
} else {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
bool
|
||||
btle_matchAddressAndIrk(ble_gap_addr_t const * p_addr, ble_gap_irk_t const * p_irk)
|
||||
{
|
||||
/*
|
||||
* Use a helper function from the Nordic SDK to test whether the BLE
|
||||
* address can be generated using the IRK.
|
||||
*/
|
||||
return im_address_resolve(p_addr, p_irk);
|
||||
}
|
||||
|
||||
void
|
||||
btle_generateResolvableAddress(const ble_gap_irk_t &irk, ble_gap_addr_t &address)
|
||||
{
|
||||
/* Set type to resolvable */
|
||||
address.addr_type = BLE_GAP_ADDR_TYPE_RANDOM_PRIVATE_RESOLVABLE;
|
||||
|
||||
/*
|
||||
* Assign a random number to the most significant 3 bytes
|
||||
* of the address.
|
||||
*/
|
||||
address.addr[BLE_GAP_ADDR_LEN - 3] = 0x8E;
|
||||
address.addr[BLE_GAP_ADDR_LEN - 2] = 0x4F;
|
||||
address.addr[BLE_GAP_ADDR_LEN - 1] = 0x7C;
|
||||
|
||||
/* Calculate the hash and store it in the top half of the address */
|
||||
ah(irk.irk, &address.addr[BLE_GAP_ADDR_LEN - 3], address.addr);
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,364 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "custom_helper.h"
|
||||
|
||||
/*
|
||||
* The current version of the soft-device doesn't handle duplicate 128-bit UUIDs
|
||||
* very well. It is therefore necessary to filter away duplicates before
|
||||
* passing long UUIDs to sd_ble_uuid_vs_add(). The following types and data
|
||||
* structures involved in maintaining a local cache of 128-bit UUIDs.
|
||||
*/
|
||||
typedef struct {
|
||||
UUID::LongUUIDBytes_t uuid;
|
||||
uint8_t type;
|
||||
} converted_uuid_table_entry_t;
|
||||
|
||||
static unsigned uuidTableEntries = 0; /* current usage of the table */
|
||||
converted_uuid_table_entry_t convertedUUIDTable[UUID_TABLE_MAX_ENTRIES];
|
||||
|
||||
void custom_reset_128bits_uuid_table() {
|
||||
uuidTableEntries = 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* lookup the cache of previously converted 128-bit UUIDs to find a type value.
|
||||
* @param uuid base 128-bit UUID
|
||||
* @param recoveredType the type field of the 3-byte nRF's uuid.
|
||||
* @return true if a match is found.
|
||||
*/
|
||||
static bool
|
||||
lookupConvertedUUIDTable(const UUID::LongUUIDBytes_t uuid, uint8_t *recoveredType)
|
||||
{
|
||||
unsigned i;
|
||||
for (i = 0; i < uuidTableEntries; i++) {
|
||||
unsigned 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)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (convertedUUIDTable[i].uuid[byteIndex] != uuid[byteIndex]) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (byteIndex == UUID::LENGTH_OF_LONG_UUID) {
|
||||
*recoveredType = convertedUUIDTable[i].type;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static void
|
||||
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, UUID::LENGTH_OF_LONG_UUID);
|
||||
convertedUUIDTable[uuidTableEntries].uuid[2] = 0;
|
||||
convertedUUIDTable[uuidTableEntries].uuid[3] = 0;
|
||||
convertedUUIDTable[uuidTableEntries].type = type;
|
||||
uuidTableEntries++;
|
||||
}
|
||||
|
||||
/**
|
||||
* The nRF transport has its own 3-byte representation of a UUID. If the user-
|
||||
* specified UUID is 128-bits wide, then the UUID base needs to be added to the
|
||||
* soft-device and converted to a 3-byte handle before being used further. This
|
||||
* function is responsible for this translation of user-specified UUIDs into
|
||||
* nRF's representation.
|
||||
*
|
||||
* @param[in] uuid
|
||||
* user-specified UUID
|
||||
* @return nRF
|
||||
* 3-byte UUID (containing a type and 16-bit UUID) representation
|
||||
* to be used with SVC calls.
|
||||
*/
|
||||
ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid)
|
||||
{
|
||||
ble_uuid_t nordicUUID;
|
||||
nordicUUID.uuid = uuid.getShortUUID();
|
||||
nordicUUID.type = BLE_UUID_TYPE_UNKNOWN; /* to be set below */
|
||||
|
||||
if (uuid.shortOrLong() == UUID::UUID_TYPE_SHORT) {
|
||||
nordicUUID.type = BLE_UUID_TYPE_BLE;
|
||||
} else {
|
||||
if (!lookupConvertedUUIDTable(uuid.getBaseUUID(), &nordicUUID.type)) {
|
||||
nordicUUID.type = custom_add_uuid_base(uuid.getBaseUUID());
|
||||
addToConvertedUUIDTable(uuid.getBaseUUID(), nordicUUID.type);
|
||||
}
|
||||
}
|
||||
|
||||
return nordicUUID;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Adds the base UUID to the custom service. All UUIDs used
|
||||
by this service are based on this 128-bit UUID.
|
||||
|
||||
@note This UUID needs to be added to the SoftDevice stack before
|
||||
adding the service's primary service via
|
||||
'sd_ble_gatts_service_add'
|
||||
|
||||
@param[in] p_uuid_base A pointer to the 128-bit UUID array (8*16)
|
||||
|
||||
@returns The UUID type.
|
||||
A return value of 0 should be considered an error.
|
||||
|
||||
@retval 0x00 BLE_UUID_TYPE_UNKNOWN
|
||||
@retval 0x01 BLE_UUID_TYPE_BLE
|
||||
@retval 0x02 BLE_UUID_TYPE_VENDOR_BEGIN
|
||||
|
||||
@section EXAMPLE
|
||||
@code
|
||||
|
||||
// Take note that bytes 2/3 are blank since these are used to identify
|
||||
// the primary service and individual characteristics
|
||||
#define CFG_CUSTOM_UUID_BASE "\x6E\x40\x00\x00\xB5\xA3\xF3\x93\xE0\xA9\xE5\x0E\x24\xDC\xCA\x9E"
|
||||
|
||||
uint8_t uuid_type = custom_add_uuid_base(CFG_CUSTOM_UUID_BASE);
|
||||
ASSERT(uuid_type > 0, ERROR_NOT_FOUND);
|
||||
|
||||
// We can now safely add the primary service and any characteristics
|
||||
// for our custom service ...
|
||||
|
||||
@endcode
|
||||
*/
|
||||
/**************************************************************************/
|
||||
uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base)
|
||||
{
|
||||
ble_uuid128_t base_uuid;
|
||||
uint8_t uuid_type = 0;
|
||||
|
||||
for (unsigned i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
|
||||
base_uuid.uuid128[i] = p_uuid_base[i];
|
||||
}
|
||||
|
||||
ASSERT_INT( ERROR_NONE, sd_ble_uuid_vs_add( &base_uuid, &uuid_type ), 0);
|
||||
|
||||
return uuid_type;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
error_t custom_decode_uuid_base(uint8_t const *const p_uuid_base,
|
||||
ble_uuid_t *p_uuid)
|
||||
{
|
||||
UUID::LongUUIDBytes_t uuid_base_le;
|
||||
|
||||
for (uint8_t i = 0; i < UUID::LENGTH_OF_LONG_UUID; i++) {
|
||||
uuid_base_le[i] = p_uuid_base[i];
|
||||
}
|
||||
|
||||
ASSERT_STATUS( sd_ble_uuid_decode(UUID::LENGTH_OF_LONG_UUID, uuid_base_le, p_uuid));
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Adds a new characteristic to the custom service, assigning
|
||||
properties, a UUID add-on value, etc.
|
||||
|
||||
@param[in] service_handle
|
||||
@param[in] p_uuid The 16-bit value to add to the base UUID
|
||||
for this characteristic (normally >1
|
||||
since 1 is typically used by the primary
|
||||
service).
|
||||
@param[in] char_props The characteristic properties, as
|
||||
defined by ble_gatt_char_props_t
|
||||
@param[in] max_length The maximum length of this characeristic
|
||||
@param[in] has_variable_len Whether the characteristic data has
|
||||
variable length.
|
||||
@param[out] p_char_handle
|
||||
|
||||
@returns
|
||||
@retval ERROR_NONE Everything executed normally
|
||||
*/
|
||||
/**************************************************************************/
|
||||
error_t custom_add_in_characteristic(uint16_t service_handle,
|
||||
ble_uuid_t *p_uuid,
|
||||
uint8_t properties,
|
||||
SecurityManager::SecurityMode_t requiredSecurity,
|
||||
uint8_t *p_data,
|
||||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
bool has_variable_len,
|
||||
const uint8_t *userDescriptionDescriptorValuePtr,
|
||||
uint16_t userDescriptionDescriptorValueLen,
|
||||
bool readAuthorization,
|
||||
bool writeAuthorization,
|
||||
ble_gatts_char_handles_t *p_char_handle)
|
||||
{
|
||||
/* Characteristic metadata */
|
||||
ble_gatts_attr_md_t cccd_md;
|
||||
ble_gatt_char_props_t char_props;
|
||||
|
||||
memcpy(&char_props, &properties, 1);
|
||||
|
||||
if (char_props.notify || char_props.indicate) {
|
||||
/* Notification requires cccd */
|
||||
memclr_( &cccd_md, sizeof(ble_gatts_attr_md_t));
|
||||
cccd_md.vloc = BLE_GATTS_VLOC_STACK;
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.read_perm);
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&cccd_md.write_perm);
|
||||
}
|
||||
|
||||
ble_gatts_char_md_t char_md = {0};
|
||||
|
||||
char_md.char_props = char_props;
|
||||
char_md.p_cccd_md =
|
||||
(char_props.notify || char_props.indicate) ? &cccd_md : NULL;
|
||||
if ((userDescriptionDescriptorValueLen > 0) && (userDescriptionDescriptorValuePtr != NULL)) {
|
||||
char_md.p_char_user_desc = const_cast<uint8_t *>(userDescriptionDescriptorValuePtr);
|
||||
char_md.char_user_desc_max_size = userDescriptionDescriptorValueLen;
|
||||
char_md.char_user_desc_size = userDescriptionDescriptorValueLen;
|
||||
}
|
||||
|
||||
/* Attribute declaration */
|
||||
ble_gatts_attr_md_t attr_md = {0};
|
||||
|
||||
attr_md.rd_auth = readAuthorization;
|
||||
attr_md.wr_auth = writeAuthorization;
|
||||
|
||||
attr_md.vloc = BLE_GATTS_VLOC_STACK;
|
||||
/* Always set variable size */
|
||||
attr_md.vlen = has_variable_len;
|
||||
|
||||
if (char_props.read || char_props.notify || char_props.indicate) {
|
||||
switch (requiredSecurity) {
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.read_perm);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
if (char_props.write || char_props.write_wo_resp) {
|
||||
switch (requiredSecurity) {
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_OPEN_LINK :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_NO_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_ENCRYPTION_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_ENC_WITH_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_NO_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_NO_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
case SecurityManager::SECURITY_MODE_SIGNED_WITH_MITM :
|
||||
BLE_GAP_CONN_SEC_MODE_SET_SIGNED_WITH_MITM(&attr_md.write_perm);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
}
|
||||
|
||||
ble_gatts_attr_t attr_char_value = {0};
|
||||
|
||||
attr_char_value.p_uuid = p_uuid;
|
||||
attr_char_value.p_attr_md = &attr_md;
|
||||
attr_char_value.init_len = length;
|
||||
attr_char_value.max_len = max_length;
|
||||
attr_char_value.p_value = p_data;
|
||||
|
||||
ASSERT_STATUS ( sd_ble_gatts_characteristic_add(service_handle,
|
||||
&char_md,
|
||||
&attr_char_value,
|
||||
p_char_handle));
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Adds a new descriptor to the custom service, assigning
|
||||
value, a UUID add-on value, etc.
|
||||
|
||||
@param[in] char_handle
|
||||
@param[in] p_uuid The 16-bit value to add to the base UUID
|
||||
for this descriptor (normally >1
|
||||
since 1 is typically used by the primary
|
||||
service).
|
||||
@param[in] max_length The maximum length of this descriptor
|
||||
@param[in] has_variable_len Whether the characteristic data has
|
||||
variable length.
|
||||
|
||||
@returns
|
||||
@retval ERROR_NONE Everything executed normally
|
||||
*/
|
||||
/**************************************************************************/
|
||||
error_t custom_add_in_descriptor(uint16_t char_handle,
|
||||
ble_uuid_t *p_uuid,
|
||||
uint8_t *p_data,
|
||||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
bool has_variable_len,
|
||||
uint16_t *p_desc_handle)
|
||||
{
|
||||
/* Descriptor metadata */
|
||||
ble_gatts_attr_md_t desc_md = {0};
|
||||
|
||||
desc_md.vloc = BLE_GATTS_VLOC_STACK;
|
||||
/* Always set variable size */
|
||||
desc_md.vlen = has_variable_len;
|
||||
|
||||
/* Make it readable and writable */
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.read_perm);
|
||||
BLE_GAP_CONN_SEC_MODE_SET_OPEN(&desc_md.write_perm);
|
||||
|
||||
ble_gatts_attr_t attr_desc = {0};
|
||||
|
||||
attr_desc.p_uuid = p_uuid;
|
||||
attr_desc.p_attr_md = &desc_md;
|
||||
attr_desc.init_len = length;
|
||||
attr_desc.max_len = max_length;
|
||||
attr_desc.p_value = p_data;
|
||||
|
||||
ASSERT_STATUS ( sd_ble_gatts_descriptor_add(char_handle,
|
||||
&attr_desc,
|
||||
p_desc_handle));
|
||||
|
||||
return ERROR_NONE;
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _CUSTOM_HELPER_H_
|
||||
#define _CUSTOM_HELPER_H_
|
||||
|
||||
#include "common/common.h"
|
||||
#include "headers/ble.h"
|
||||
#include "ble/UUID.h"
|
||||
#include "ble/GattCharacteristic.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define UUID_TABLE_MAX_ENTRIES (4) /* This is the maximum number of 128-bit UUIDs with distinct bases that
|
||||
* we expect to be in use; increase this limit if needed. */
|
||||
|
||||
/**
|
||||
* Reset the table of 128bits uuids.
|
||||
* This table is used to keep track of vendors uuids added to the softdevice.
|
||||
* It is important to reset it before disabling the softdevice otherwise the
|
||||
* next time the softdevice will be enabled, this table will not be synchronmized
|
||||
* with the softdevice table.
|
||||
*/
|
||||
void custom_reset_128bits_uuid_table();
|
||||
uint8_t custom_add_uuid_base(uint8_t const *const p_uuid_base);
|
||||
error_t custom_decode_uuid(uint8_t const *const p_uuid_base,
|
||||
ble_uuid_t *p_uuid);
|
||||
ble_uuid_t custom_convert_to_nordic_uuid(const UUID &uuid);
|
||||
|
||||
error_t custom_add_in_characteristic(uint16_t service_handle,
|
||||
ble_uuid_t *p_uuid,
|
||||
uint8_t properties,
|
||||
SecurityManager::SecurityMode_t requiredSecurity,
|
||||
uint8_t *p_data,
|
||||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
bool has_variable_len,
|
||||
const uint8_t *userDescriptionDescriptorValuePtr,
|
||||
uint16_t userDescriptionDescriptorValueLen,
|
||||
bool readAuthorization,
|
||||
bool writeAuthorization,
|
||||
ble_gatts_char_handles_t *p_char_handle);
|
||||
|
||||
error_t custom_add_in_descriptor(uint16_t char_handle,
|
||||
ble_uuid_t *p_uuid,
|
||||
uint8_t *p_data,
|
||||
uint16_t length,
|
||||
uint16_t max_length,
|
||||
bool has_variable_len,
|
||||
uint16_t *p_desc_handle);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // ifndef _CUSTOM_HELPER_H_
|
|
@ -0,0 +1,103 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file ansi_esc_code.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, hathach (tinyusb.org)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
This file is part of the tinyusb stack.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \file
|
||||
* \brief TBD
|
||||
*
|
||||
* \note TBD
|
||||
*/
|
||||
|
||||
/** \ingroup TBD
|
||||
* \defgroup TBD
|
||||
* \brief TBD
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _ANSI_ESC_CODE_H_
|
||||
#define _ANSI_ESC_CODE_H_
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define CSI_CODE(seq) "\33[" seq
|
||||
#define CSI_SGR(x) CSI_CODE(#x) "m"
|
||||
|
||||
//------------- Cursor movement -------------//
|
||||
#define ANSI_CURSOR_UP(n) CSI_CODE(#n "A")
|
||||
#define ANSI_CURSOR_DOWN(n) CSI_CODE(#n "B")
|
||||
#define ANSI_CURSOR_FORWARD(n) CSI_CODE(#n "C")
|
||||
#define ANSI_CURSOR_BACKWARD(n) CSI_CODE(#n "D")
|
||||
#define ANSI_CURSOR_LINE_DOWN(n) CSI_CODE(#n "E")
|
||||
#define ANSI_CURSOR_LINE_UP(n) CSI_CODE(#n "F")
|
||||
#define ANSI_CURSOR_POSITION(n, m) CSI_CODE(#n ";" #m "H")
|
||||
|
||||
#define ANSI_ERASE_SCREEN(n) CSI_CODE(#n "J")
|
||||
#define ANSI_ERASE_LINE(n) CSI_CODE(#n "K")
|
||||
|
||||
/** text color */
|
||||
#define ANSI_TEXT_BLACK CSI_SGR(30)
|
||||
#define ANSI_TEXT_RED CSI_SGR(31)
|
||||
#define ANSI_TEXT_GREEN CSI_SGR(32)
|
||||
#define ANSI_TEXT_YELLOW CSI_SGR(33)
|
||||
#define ANSI_TEXT_BLUE CSI_SGR(34)
|
||||
#define ANSI_TEXT_MAGENTA CSI_SGR(35)
|
||||
#define ANSI_TEXT_CYAN CSI_SGR(36)
|
||||
#define ANSI_TEXT_WHITE CSI_SGR(37)
|
||||
#define ANSI_TEXT_DEFAULT CSI_SGR(39)
|
||||
|
||||
/** background color */
|
||||
#define ANSI_BG_BLACK CSI_SGR(40)
|
||||
#define ANSI_BG_RED CSI_SGR(41)
|
||||
#define ANSI_BG_GREEN CSI_SGR(42)
|
||||
#define ANSI_BG_YELLOW CSI_SGR(43)
|
||||
#define ANSI_BG_BLUE CSI_SGR(44)
|
||||
#define ANSI_BG_MAGENTA CSI_SGR(45)
|
||||
#define ANSI_BG_CYAN CSI_SGR(46)
|
||||
#define ANSI_BG_WHITE CSI_SGR(47)
|
||||
#define ANSI_BG_DEFAULT CSI_SGR(49)
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _TUSB_ANSI_ESC_CODE_H_ */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,197 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file assertion.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, K. Townsend (microBuilder.eu)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \file
|
||||
* \brief TBD
|
||||
*
|
||||
* \note TBD
|
||||
*/
|
||||
|
||||
/** \ingroup TBD
|
||||
* \defgroup TBD
|
||||
* \brief TBD
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _ASSERTION_H_
|
||||
#define _ASSERTION_H_
|
||||
|
||||
#include "projectconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C"
|
||||
{
|
||||
#endif
|
||||
|
||||
static inline void debugger_breakpoint(void) ATTR_ALWAYS_INLINE;
|
||||
static inline void debugger_breakpoint(void)
|
||||
{
|
||||
#ifndef _TEST_
|
||||
__asm("BKPT #0\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Compile-time Assert
|
||||
//--------------------------------------------------------------------+
|
||||
#if defined __COUNTER__ && __COUNTER__ != __COUNTER__
|
||||
#define _ASSERT_COUNTER __COUNTER__
|
||||
#else
|
||||
#define _ASSERT_COUNTER __LINE__
|
||||
#endif
|
||||
|
||||
#define ASSERT_STATIC(const_expr, message) enum { XSTRING_CONCAT_(static_assert_, _ASSERT_COUNTER) = 1/(!!(const_expr)) }
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Assert Helper
|
||||
//--------------------------------------------------------------------+
|
||||
//#ifndef _TEST_
|
||||
// #define ASSERT_MESSAGE(format, ...) _PRINTF("Assert at %s: %s: %d: " format "\n", __BASE_FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
//#else
|
||||
// #define ASSERT_MESSAGE(format, ...) _PRINTF("%d:note: Assert " format "\n", __LINE__, __VA_ARGS__)
|
||||
//#endif
|
||||
|
||||
#if CFG_DEBUG == 3
|
||||
#define ASSERT_MESSAGE(format, ...) debugger_breakpoint()
|
||||
#elif CFG_DEBUG == 2
|
||||
#define ASSERT_MESSAGE(format, ...) printf("Assert at %s: %s: %d: " format "\n", __BASE_FILE__, __PRETTY_FUNCTION__, __LINE__, __VA_ARGS__)
|
||||
#else
|
||||
#define ASSERT_MESSAGE(format, ...)
|
||||
#endif
|
||||
|
||||
#define ASSERT_ERROR_HANDLER(x, para) \
|
||||
return (x)
|
||||
|
||||
#define ASSERT_DEFINE_WITH_HANDLER(error_handler, handler_para, setup_statement, condition, error, format, ...) \
|
||||
do{\
|
||||
setup_statement;\
|
||||
if (!(condition)) {\
|
||||
ASSERT_MESSAGE(format, __VA_ARGS__);\
|
||||
error_handler(error, handler_para);\
|
||||
}\
|
||||
}while(0)
|
||||
|
||||
#define ASSERT_DEFINE(...) ASSERT_DEFINE_WITH_HANDLER(ASSERT_ERROR_HANDLER, NULL, __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// error_t Status Assert TODO use ASSERT_DEFINE
|
||||
//--------------------------------------------------------------------+
|
||||
#define ASSERT_STATUS_MESSAGE(sts, message) \
|
||||
ASSERT_DEFINE(error_t status = (error_t)(sts),\
|
||||
ERROR_NONE == status, status, "%s: %s", ErrorStr[status], message)
|
||||
|
||||
#define ASSERT_STATUS(sts) \
|
||||
ASSERT_DEFINE(error_t status = (error_t)(sts),\
|
||||
ERROR_NONE == status, status, "error = %d", status)
|
||||
|
||||
#define ASSERT_STATUS_RET_VOID(sts) \
|
||||
ASSERT_DEFINE(error_t status = (error_t)(sts),\
|
||||
ERROR_NONE == status, (void) 0, "error = %d", status)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Logical Assert
|
||||
//--------------------------------------------------------------------+
|
||||
#define ASSERT_TRUE(condition , error) ASSERT_DEFINE( , (condition), error, "%s", "evaluated to false")
|
||||
#define ASSERT_FALSE(condition , error) ASSERT_DEFINE( ,!(condition), error, "%s", "evaluated to true")
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Pointer Assert
|
||||
//--------------------------------------------------------------------+
|
||||
#define ASSERT_PTR(...) ASSERT_PTR_NOT_NULL(__VA_ARGS__)
|
||||
#define ASSERT_PTR_NOT_NULL(pointer, error) ASSERT_DEFINE( , NULL != (pointer), error, "%s", "pointer is NULL")
|
||||
#define ASSERT_PTR_NULL(pointer, error) ASSERT_DEFINE( , NULL == (pointer), error, "%s", "pointer is not NULL")
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Integral Assert
|
||||
//--------------------------------------------------------------------+
|
||||
#define ASSERT_XXX_EQUAL(type_format, expected, actual, error) \
|
||||
ASSERT_DEFINE(\
|
||||
uint32_t exp = (expected); uint32_t act = (actual),\
|
||||
exp==act,\
|
||||
error,\
|
||||
"expected " type_format ", actual " type_format, exp, act)
|
||||
|
||||
#define ASSERT_XXX_WITHIN(type_format, lower, upper, actual, error) \
|
||||
ASSERT_DEFINE(\
|
||||
uint32_t low = (lower); uint32_t up = (upper); uint32_t act = (actual),\
|
||||
(low <= act) && (act <= up),\
|
||||
error,\
|
||||
"expected within " type_format " - " type_format ", actual " type_format, low, up, act)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Integer Assert
|
||||
//--------------------------------------------------------------------+
|
||||
#define ASSERT_INT(...) ASSERT_INT_EQUAL(__VA_ARGS__)
|
||||
#define ASSERT_INT_EQUAL(...) ASSERT_XXX_EQUAL("%d", __VA_ARGS__)
|
||||
#define ASSERT_INT_WITHIN(...) ASSERT_XXX_WITHIN("%d", __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Hex Assert
|
||||
//--------------------------------------------------------------------+
|
||||
#define ASSERT_HEX(...) ASSERT_HEX_EQUAL(__VA_ARGS__)
|
||||
#define ASSERT_HEX_EQUAL(...) ASSERT_XXX_EQUAL("0x%x", __VA_ARGS__)
|
||||
#define ASSERT_HEX_WITHIN(...) ASSERT_XXX_WITHIN("0x%x", __VA_ARGS__)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// Bin Assert
|
||||
//--------------------------------------------------------------------+
|
||||
#define BIN8_PRINTF_PATTERN "%d%d%d%d%d%d%d%d"
|
||||
#define BIN8_PRINTF_CONVERT(byte) \
|
||||
((byte) & 0x80 ? 1 : 0), \
|
||||
((byte) & 0x40 ? 1 : 0), \
|
||||
((byte) & 0x20 ? 1 : 0), \
|
||||
((byte) & 0x10 ? 1 : 0), \
|
||||
((byte) & 0x08 ? 1 : 0), \
|
||||
((byte) & 0x04 ? 1 : 0), \
|
||||
((byte) & 0x02 ? 1 : 0), \
|
||||
((byte) & 0x01 ? 1 : 0)
|
||||
|
||||
#define ASSERT_BIN8(...) ASSERT_BIN8_EQUAL(__VA_ARGS__)
|
||||
#define ASSERT_BIN8_EQUAL(expected, actual, error)\
|
||||
ASSERT_DEFINE(\
|
||||
uint8_t exp = (expected); uint8_t act = (actual),\
|
||||
exp==act,\
|
||||
error,\
|
||||
"expected " BIN8_PRINTF_PATTERN ", actual " BIN8_PRINTF_PATTERN, BIN8_PRINTF_CONVERT(exp), BIN8_PRINTF_CONVERT(act) )
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _ASSERTION_H_ */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,96 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file binary.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, K. Townsend (microBuilder.eu)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \ingroup TBD
|
||||
* \defgroup TBD
|
||||
* \brief TBD
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _BINARY_H_
|
||||
#define _BINARY_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/// n-th Bit
|
||||
#define BIT(n) (1 << (n))
|
||||
|
||||
/// set n-th bit of x to 1
|
||||
#define BIT_SET(x, n) ( (x) | BIT(n) )
|
||||
|
||||
/// clear n-th bit of x
|
||||
#define BIT_CLR(x, n) ( (x) & (~BIT(n)) )
|
||||
|
||||
/// test n-th bit of x
|
||||
#define BIT_TEST(x, n) ( (x) & BIT(n) )
|
||||
|
||||
#if defined(__GNUC__) && !defined(__CC_ARM) // keil does not support binary format
|
||||
|
||||
#define BIN8(x) ((uint8_t) (0b##x))
|
||||
#define BIN16(b1, b2) ((uint16_t) (0b##b1##b2))
|
||||
#define BIN32(b1, b2, b3, b4) ((uint32_t) (0b##b1##b2##b3##b4))
|
||||
|
||||
#else
|
||||
|
||||
// internal macro of B8, B16, B32
|
||||
#define _B8__(x) (((x&0x0000000FUL)?1:0) \
|
||||
+((x&0x000000F0UL)?2:0) \
|
||||
+((x&0x00000F00UL)?4:0) \
|
||||
+((x&0x0000F000UL)?8:0) \
|
||||
+((x&0x000F0000UL)?16:0) \
|
||||
+((x&0x00F00000UL)?32:0) \
|
||||
+((x&0x0F000000UL)?64:0) \
|
||||
+((x&0xF0000000UL)?128:0))
|
||||
|
||||
#define BIN8(d) ((uint8_t) _B8__(0x##d##UL))
|
||||
#define BIN16(dmsb,dlsb) (((uint16_t)BIN8(dmsb)<<8) + BIN8(dlsb))
|
||||
#define BIN32(dmsb,db2,db3,dlsb) \
|
||||
(((uint32_t)BIN8(dmsb)<<24) \
|
||||
+ ((uint32_t)BIN8(db2)<<16) \
|
||||
+ ((uint32_t)BIN8(db3)<<8) \
|
||||
+ BIN8(dlsb))
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BINARY_H_ */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,151 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file ble_error.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, K. Townsend (microBuilder.eu)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \file
|
||||
* \brief Error Header
|
||||
*
|
||||
* \note TBD
|
||||
*/
|
||||
|
||||
/** \ingroup Group_Common
|
||||
* \defgroup Group_Error Error Codes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _BLE_ERROR_H_
|
||||
#define _BLE_ERROR_H_
|
||||
|
||||
#include "projectconfig.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
/*=======================================================================
|
||||
NORDIC GLOBAL ERRORS 0x0000 .. 0x00FF
|
||||
-----------------------------------------------------------------------
|
||||
Errors mapped from nrf_error.h
|
||||
-----------------------------------------------------------------------*/
|
||||
ERROR_NONE = 0x0000 , ///< Successful command
|
||||
ERROR_SVC_HANDLER_MISSING = 0x0001 , ///< SVC handler is missing
|
||||
ERROR_SOFTDEVICE_NOT_ENABLED = 0x0002 , ///< SoftDevice has not been enabled
|
||||
ERROR_INTERNAL = 0x0003 , ///< Internal Error
|
||||
ERROR_NO_MEM = 0x0004 , ///< No Memory for operation
|
||||
ERROR_NOT_FOUND = 0x0005 , ///< Not found
|
||||
ERROR_NOT_SUPPORTED = 0x0006 , ///< Not supported
|
||||
ERROR_INVALID_PARAM = 0x0007 , ///< Invalid Parameter
|
||||
ERROR_INVALID_STATE = 0x0008 , ///< Invalid state, operation disallowed in this state
|
||||
ERROR_INVALID_LENGTH = 0x0009 , ///< Invalid Length
|
||||
ERROR_INVALID_FLAGS = 0x000A , ///< Invalid Flags
|
||||
ERROR_INVALID_DATA = 0x000B , ///< Invalid Data
|
||||
ERROR_DATA_SIZE = 0x000C , ///< Data size exceeds limit
|
||||
ERROR_TIMEOUT = 0x000D , ///< Operation timed out
|
||||
ERROR_NULL = 0x000E , ///< Null Pointer
|
||||
ERROR_FORBIDDEN = 0x000F , ///< Forbidden Operation
|
||||
ERROR_INVALID_ADDR = 0x0010 , ///< Bad Memory Address
|
||||
ERROR_BUSY = 0x0011 , ///< Busy
|
||||
/*=======================================================================*/
|
||||
|
||||
ERROR_INVALIDPARAMETER = 0x0100 , /**< An invalid parameter value was provided */
|
||||
ERROR_I2C_XFER_FAILED = 0x0101 , /**< an failed attempt to make I2C transfer */
|
||||
|
||||
/*=======================================================================
|
||||
SIMPLE BINARY PROTOCOL ERRORS 0x0120 .. 0x013F
|
||||
-----------------------------------------------------------------------
|
||||
Errors relating to the simple binary protocol (/src//protocol)
|
||||
-----------------------------------------------------------------------*/
|
||||
ERROR_PROT_INVALIDMSGTYPE = 0x121, /**< Unexpected msg type encountered */
|
||||
ERROR_PROT_INVALIDCOMMANDID = 0x122, /**< Unknown or out of range command ID */
|
||||
ERROR_PROT_INVALIDPAYLOAD = 0x123, /**< Message payload has a problem (invalid len, etc.) */
|
||||
/*=======================================================================*/
|
||||
|
||||
//------------- based on Nordic SDM nrf_error_sdm.h -------------//
|
||||
ERROR_SDM_LFCLK_SOURCE_UNKNOWN = 0x1000 , ///< Unknown lfclk source
|
||||
ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION = 0x1001 , ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts)
|
||||
ERROR_SDM_INCORRECT_CLENR0 = 0x1002 , ///< Incorrect CLENR0 (can be caused by erronous SoftDevice flashing)
|
||||
|
||||
//------------- based on Nordic SOC nrf_error_soc.h -------------//
|
||||
/* Mutex Errors */
|
||||
ERROR_SOC_MUTEX_ALREADY_TAKEN = 0x2000 , ///< Mutex already taken
|
||||
|
||||
/* NVIC errors */
|
||||
ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE = 0x2001 , ///< NVIC interrupt not available
|
||||
ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED = 0x2002 , ///< NVIC interrupt priority not allowed
|
||||
ERROR_SOC_NVIC_SHOULD_NOT_RETURN = 0x2003 , ///< NVIC should not return
|
||||
|
||||
/* Power errors */
|
||||
ERROR_SOC_POWER_MODE_UNKNOWN = 0x2004 , ///< Power mode unknown
|
||||
ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN = 0x2005 , ///< Power POF threshold unknown
|
||||
ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN = 0x2006 , ///< Power off should not return
|
||||
|
||||
/* Rand errors */
|
||||
ERROR_SOC_RAND_NOT_ENOUGH_VALUES = 0x2007 , ///< RAND not enough values
|
||||
|
||||
/* PPI errors */
|
||||
ERROR_SOC_PPI_INVALID_CHANNEL = 0x2008 , ///< Invalid PPI Channel
|
||||
ERROR_SOC_PPI_INVALID_GROUP = 0x2009 , ///< Invalid PPI Group
|
||||
|
||||
//------------- based on Nordic STK (ble) ble_err.h -------------//
|
||||
ERROR_BLE_INVALID_CONN_HANDLE = 0x3001 , /**< Invalid connection handle. */
|
||||
ERROR_BLE_INVALID_ATTR_HANDLE = 0x3002 , /**< Invalid attribute handle. */
|
||||
ERROR_BLE_NO_TX_BUFFERS = 0x3003 , /**< Buffer capacity exceeded. */
|
||||
|
||||
// L2CAP
|
||||
ERROR_BLE_L2CAP_CID_IN_USE = 0x3100 , /**< CID already in use. */
|
||||
|
||||
// GAP
|
||||
ERROR_BLE_GAP_UUID_LIST_MISMATCH = 0x3200 , /**< UUID list does not contain an integral number of UUIDs. */
|
||||
ERROR_BLE_GAP_DISCOVERABLE_WITH_WHITELIST = 0x3201 , /**< Use of Whitelist not permitted with discoverable advertising. */
|
||||
ERROR_BLE_GAP_INVALID_BLE_ADDR = 0x3202 , /**< The upper two bits of the address do not correspond to the specified address type. */
|
||||
|
||||
// GATTC
|
||||
ERROR_BLE_GATTC_PROC_NOT_PERMITTED = 0x3300 ,
|
||||
|
||||
// GATTS
|
||||
ERROR_BLEGATTS_INVALID_ATTR_TYPE = 0x3400 , /**< Invalid attribute type. */
|
||||
ERROR_BLEGATTS_SYS_ATTR_MISSING = 0x3401 , /**< System Attributes missing. */
|
||||
|
||||
}error_t;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _BLE_ERROR_H_ */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,236 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file common.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, K. Townsend (microBuilder.eu)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \defgroup Group_Common Common Files
|
||||
* @{
|
||||
*
|
||||
* \defgroup Group_CommonH common.h
|
||||
*
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _COMMON_H_
|
||||
#define _COMMON_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INCLUDES
|
||||
//--------------------------------------------------------------------+
|
||||
|
||||
//------------- Standard Header -------------//
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
|
||||
//------------- General Header -------------//
|
||||
#include "projectconfig.h"
|
||||
#include "compiler.h"
|
||||
#include "assertion.h"
|
||||
#include "binary.h"
|
||||
#include "ble_error.h"
|
||||
|
||||
//------------- MCU header -------------//
|
||||
//#include "nrf.h"
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// TYPEDEFS
|
||||
//--------------------------------------------------------------------+
|
||||
typedef unsigned char byte_t;
|
||||
typedef float float32_t;
|
||||
typedef double float64_t;
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// MACROS
|
||||
//--------------------------------------------------------------------+
|
||||
#define STRING_(x) #x // stringify without expand
|
||||
#define XSTRING_(x) STRING_(x) // expand then stringify
|
||||
#define STRING_CONCAT_(a, b) a##b // concat without expand
|
||||
#define XSTRING_CONCAT_(a, b) STRING_CONCAT_(a, b) // expand then concat
|
||||
|
||||
#define U16_HIGH_U8(u16) ((uint8_t) (((u16) >> 8) & 0x00ff))
|
||||
#define U16_LOW_U8(u16) ((uint8_t) ((u16) & 0x00ff))
|
||||
#define U16_TO_U8S_BE(u16) U16_HIGH_U8(u16), U16_LOW_U8(u16)
|
||||
#define U16_TO_U8S_LE(u16) U16_LOW_U8(u16), U16_HIGH_U8(u16)
|
||||
|
||||
#define U32_B1_U8(u32) ((uint8_t) (((u32) >> 24) & 0x000000ff)) // MSB
|
||||
#define U32_B2_U8(u32) ((uint8_t) (((u32) >> 16) & 0x000000ff))
|
||||
#define U32_B3_U8(u32) ((uint8_t) (((u32) >> 8) & 0x000000ff))
|
||||
#define U32_B4_U8(u32) ((uint8_t) ((u32) & 0x000000ff)) // LSB
|
||||
|
||||
#define U32_TO_U8S_BE(u32) U32_B1_U8(u32), U32_B2_U8(u32), U32_B3_U8(u32), U32_B4_U8(u32)
|
||||
#define U32_TO_U8S_LE(u32) U32_B4_U8(u32), U32_B3_U8(u32), U32_B2_U8(u32), U32_B1_U8(u32)
|
||||
|
||||
//--------------------------------------------------------------------+
|
||||
// INLINE FUNCTION
|
||||
//--------------------------------------------------------------------+
|
||||
#define memclr_(buffer, size) memset(buffer, 0, size)
|
||||
|
||||
//------------- Conversion -------------//
|
||||
/// form an uint32_t from 4 x uint8_t
|
||||
static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t u32_from_u8(uint8_t b1, uint8_t b2, uint8_t b3, uint8_t b4)
|
||||
{
|
||||
return (b1 << 24) + (b2 << 16) + (b3 << 8) + b4;
|
||||
}
|
||||
|
||||
static inline uint8_t u16_high_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t u16_high_u8(uint16_t u16)
|
||||
{
|
||||
return (uint8_t) ((u16 >> 8) & 0x00ff);
|
||||
}
|
||||
|
||||
static inline uint8_t u16_low_u8(uint16_t u16) ATTR_CONST ATTR_ALWAYS_INLINE;
|
||||
static inline uint8_t u16_low_u8(uint16_t u16)
|
||||
{
|
||||
return (uint8_t) (u16 & 0x00ff);
|
||||
}
|
||||
|
||||
//------------- Min -------------//
|
||||
static inline uint8_t min8_of(uint8_t x, uint8_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint8_t min8_of(uint8_t x, uint8_t y)
|
||||
{
|
||||
return (x < y) ? x : y;
|
||||
}
|
||||
|
||||
static inline uint16_t min16_of(uint16_t x, uint16_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint16_t min16_of(uint16_t x, uint16_t y)
|
||||
{
|
||||
return (x < y) ? x : y;
|
||||
}
|
||||
|
||||
static inline uint32_t min32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t min32_of(uint32_t x, uint32_t y)
|
||||
{
|
||||
return (x < y) ? x : y;
|
||||
}
|
||||
|
||||
//------------- Max -------------//
|
||||
static inline uint32_t max32_of(uint32_t x, uint32_t y) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t max32_of(uint32_t x, uint32_t y)
|
||||
{
|
||||
return (x > y) ? x : y;
|
||||
}
|
||||
|
||||
//------------- Align -------------//
|
||||
static inline uint32_t align32 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t align32 (uint32_t value)
|
||||
{
|
||||
return (value & 0xFFFFFFE0UL);
|
||||
}
|
||||
|
||||
static inline uint32_t align16 (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t align16 (uint32_t value)
|
||||
{
|
||||
return (value & 0xFFFFFFF0UL);
|
||||
}
|
||||
|
||||
static inline uint32_t align_n (uint32_t alignment, uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t align_n (uint32_t alignment, uint32_t value)
|
||||
{
|
||||
return value & (~(alignment-1));
|
||||
}
|
||||
|
||||
static inline uint32_t align4k (uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t align4k (uint32_t value)
|
||||
{
|
||||
return (value & 0xFFFFF000UL);
|
||||
}
|
||||
|
||||
static inline uint32_t offset4k(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint32_t offset4k(uint32_t value)
|
||||
{
|
||||
return (value & 0xFFFUL);
|
||||
}
|
||||
|
||||
//------------- Mathematics -------------//
|
||||
/// inclusive range checking
|
||||
static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline bool is_in_range(uint32_t lower, uint32_t value, uint32_t upper)
|
||||
{
|
||||
return (lower <= value) && (value <= upper);
|
||||
}
|
||||
|
||||
/// exclusive range checking
|
||||
static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline bool is_in_range_exclusive(uint32_t lower, uint32_t value, uint32_t upper)
|
||||
{
|
||||
return (lower < value) && (value < upper);
|
||||
}
|
||||
|
||||
static inline uint8_t log2_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint8_t log2_of(uint32_t value)
|
||||
{
|
||||
uint8_t result = 0; // log2 of a value is its MSB's position
|
||||
|
||||
while (value >>= 1)
|
||||
{
|
||||
result++;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
// return the number of set bits in value
|
||||
static inline uint8_t cardinality_of(uint32_t value) ATTR_ALWAYS_INLINE ATTR_CONST;
|
||||
static inline uint8_t cardinality_of(uint32_t value)
|
||||
{
|
||||
// Brian Kernighan's method goes through as many iterations as there are set bits. So if we have a 32-bit word with only
|
||||
// the high bit set, then it will only go once through the loop
|
||||
// Published in 1988, the C Programming Language 2nd Ed. (by Brian W. Kernighan and Dennis M. Ritchie)
|
||||
// mentions this in exercise 2-9. On April 19, 2006 Don Knuth pointed out to me that this method
|
||||
// "was first published by Peter Wegner in CACM 3 (1960), 322. (Also discovered independently by Derrick Lehmer and
|
||||
// published in 1964 in a book edited by Beckenbach.)"
|
||||
uint8_t count;
|
||||
for (count = 0; value; count++)
|
||||
{
|
||||
value &= value - 1; // clear the least significant bit set
|
||||
}
|
||||
|
||||
return count;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _COMMON_H_ */
|
||||
|
||||
/** @} */
|
||||
/** @} */
|
|
@ -0,0 +1,160 @@
|
|||
/**************************************************************************/
|
||||
/*!
|
||||
@file compiler.h
|
||||
@author hathach (tinyusb.org)
|
||||
|
||||
@section LICENSE
|
||||
|
||||
Software License Agreement (BSD License)
|
||||
|
||||
Copyright (c) 2013, K. Townsend (microBuilder.eu)
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
1. Redistributions of source code must retain the above copyright
|
||||
notice, this list of conditions and the following disclaimer.
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
3. Neither the name of the copyright holders nor the
|
||||
names of its contributors may be used to endorse or promote products
|
||||
derived from this software without specific prior written permission.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
|
||||
EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY
|
||||
DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION HOWEVER CAUSED AND
|
||||
ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
INCLUDING NEGLIGENCE OR OTHERWISE ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
|
||||
/** \file
|
||||
* \brief GCC Header
|
||||
*/
|
||||
|
||||
/** \ingroup Group_Compiler
|
||||
* \defgroup Group_GCC GNU GCC
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef _COMPILER_GCC_H_
|
||||
#define _COMPILER_GCC_H_
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "projectconfig.h"
|
||||
|
||||
//#ifndef __GNUC__
|
||||
// #define ATTR_ALWAYS_INLINE
|
||||
// #define ATTR_CONST
|
||||
//#else
|
||||
|
||||
#ifdef _TEST_
|
||||
#define ATTR_ALWAYS_INLINE
|
||||
#define STATIC_
|
||||
#define INLINE_
|
||||
#else
|
||||
#define STATIC_ static
|
||||
#define INLINE_ inline
|
||||
|
||||
#if CFG_DEBUG == 3
|
||||
#define ATTR_ALWAYS_INLINE // no inline for debug = 3
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
|
||||
#define ALIGN_OF(x) __alignof__(x)
|
||||
|
||||
/// Normally, the compiler places the objects it generates in sections like data or bss & function in text. Sometimes, however, you need additional sections, or you need certain particular variables to appear in special sections, for example to map to special hardware. The section attribute specifies that a variable (or function) lives in a particular section
|
||||
#define ATTR_SECTION(section) __attribute__ ((#section))
|
||||
|
||||
/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, an error that includes message is diagnosed. This is useful for compile-time checking
|
||||
#define ATTR_ERROR(Message) __attribute__ ((error(Message)))
|
||||
|
||||
/// If this attribute is used on a function declaration and a call to such a function is not eliminated through dead code elimination or other optimizations, a warning that includes message is diagnosed. This is useful for compile-time checking
|
||||
#define ATTR_WARNING(Message) __attribute__ ((warning(Message)))
|
||||
|
||||
/**
|
||||
* \defgroup Group_VariableAttr Variable Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
/// This attribute specifies a minimum alignment for the variable or structure field, measured in bytes
|
||||
#define ATTR_ALIGNED(Bytes) __attribute__ ((aligned(Bytes)))
|
||||
|
||||
/// The packed attribute specifies that a variable or structure field should have the smallest possible alignment—one byte for a variable, and one bit for a field, unless you specify a larger value with the aligned attribute
|
||||
#define ATTR_PACKED __attribute__ ((packed))
|
||||
|
||||
#define ATTR_PREPACKED
|
||||
|
||||
#define ATTR_PACKED_STRUCT(x) x __attribute__ ((packed))
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* \defgroup Group_FuncAttr Function Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
#ifndef ATTR_ALWAYS_INLINE
|
||||
/// Generally, functions are not inlined unless optimization is specified. For functions declared inline, this attribute inlines the function even if no optimization level is specified
|
||||
#define ATTR_ALWAYS_INLINE __attribute__ ((always_inline))
|
||||
#endif
|
||||
|
||||
/// The nonnull attribute specifies that some function parameters should be non-null pointers. f the compiler determines that a null pointer is passed in an argument slot marked as non-null, and the -Wnonnull option is enabled, a warning is issued. All pointer arguments are marked as non-null
|
||||
#define ATTR_NON_NULL __attribute__ ((nonull))
|
||||
|
||||
/// Many functions have no effects except the return value and their return value depends only on the parameters and/or global variables. Such a function can be subject to common subexpression elimination and loop optimization just as an arithmetic operator would be. These functions should be declared with the attribute pure
|
||||
#define ATTR_PURE __attribute__ ((pure))
|
||||
|
||||
/// Many functions do not examine any values except their arguments, and have no effects except the return value. Basically this is just slightly more strict class than the pure attribute below, since function is not allowed to read global memory.
|
||||
/// Note that a function that has pointer arguments and examines the data pointed to must not be declared const. Likewise, a function that calls a non-const function usually must not be const. It does not make sense for a const function to return void
|
||||
#define ATTR_CONST __attribute__ ((const))
|
||||
|
||||
/// The deprecated attribute results in a warning if the function is used anywhere in the source file. This is useful when identifying functions that are expected to be removed in a future version of a program. The warning also includes the location of the declaration of the deprecated function, to enable users to easily find further information about why the function is deprecated, or what they should do instead. Note that the warnings only occurs for uses
|
||||
#define ATTR_DEPRECATED __attribute__ ((deprecated))
|
||||
|
||||
/// Same as the deprecated attribute with optional message in the warning
|
||||
#define ATTR_DEPRECATED_MESS(mess) __attribute__ ((deprecated(mess)))
|
||||
|
||||
/// The weak attribute causes the declaration to be emitted as a weak symbol rather than a global. This is primarily useful in defining library functions that can be overridden in user code
|
||||
#define ATTR_WEAK __attribute__ ((weak))
|
||||
|
||||
/// The alias attribute causes the declaration to be emitted as an alias for another symbol, which must be specified
|
||||
#define ATTR_ALIAS(func) __attribute__ ((alias(#func)))
|
||||
|
||||
/// The weakref attribute marks a declaration as a weak reference. It is equivalent with weak + alias attribute, but require function is static
|
||||
#define ATTR_WEAKREF(func) __attribute__ ((weakref(#func)))
|
||||
|
||||
/// The warn_unused_result attribute causes a warning to be emitted if a caller of the function with this attribute does not use its return value. This is useful for functions where not checking the result is either a security problem or always a bug
|
||||
#define ATTR_WARN_UNUSED_RESULT __attribute__ ((warn_unused_result))
|
||||
|
||||
/// This attribute, attached to a function, means that code must be emitted for the function even if it appears that the function is not referenced. This is useful, for example, when the function is referenced only in inline assembly.
|
||||
#define ATTR_USED __attribute__ ((used))
|
||||
|
||||
/// This attribute, attached to a function, means that the function is meant to be possibly unused. GCC does not produce a warning for this function.
|
||||
#define ATTR_UNUSED __attribute__ ((unused))
|
||||
|
||||
#elif defined (__ICCARM__) //IAR
|
||||
#define ATTR_ALWAYS_INLINE // IAR dosn't provide such a syntax extension in function's prototypes.
|
||||
#define ATTR_CONST // IAR dosn't provide such a syntax extension in function's prototypes.
|
||||
#endif
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* _COMPILER_GCC_H_ */
|
||||
|
||||
/// @}
|
|
@ -0,0 +1,325 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
||||
#include "ble_err.h"
|
||||
#include "ble/DiscoveredCharacteristicDescriptor.h"
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::nRF5xCharacteristicDescriptorDiscoverer() :
|
||||
discoveryRunning() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::~nRF5xCharacteristicDescriptorDiscoverer() {
|
||||
// nothing to do
|
||||
}
|
||||
|
||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::launch(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
||||
) {
|
||||
Gap::Handle_t connHandle = characteristic.getConnectionHandle();
|
||||
// it is ok to deduce that the start handle for descriptors is after
|
||||
// the characteristic declaration and the characteristic value declaration
|
||||
// see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] (3.3)
|
||||
Gap::Handle_t descriptorStartHandle = characteristic.getDeclHandle() + 2;
|
||||
Gap::Handle_t descriptorEndHandle = characteristic.getLastHandle();
|
||||
|
||||
// check if there is any descriptor to discover
|
||||
if (descriptorEndHandle < descriptorStartHandle) {
|
||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t termParams = {
|
||||
characteristic,
|
||||
BLE_ERROR_NONE
|
||||
};
|
||||
terminationCallback.call(&termParams);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
// check if we can run this discovery
|
||||
if (isConnectionInUse(connHandle)) {
|
||||
return BLE_STACK_BUSY;
|
||||
}
|
||||
|
||||
// get a new discovery slot, if none are available, just return
|
||||
Discovery* discovery = getAvailableDiscoverySlot();
|
||||
if(discovery == NULL) {
|
||||
return BLE_STACK_BUSY;
|
||||
}
|
||||
|
||||
// try to launch the discovery
|
||||
ble_error_t err = gattc_descriptors_discover(connHandle, descriptorStartHandle, descriptorEndHandle);
|
||||
if(!err) {
|
||||
// commit the new discovery to its slot
|
||||
*discovery = Discovery(characteristic, discoveryCallback, terminationCallback);
|
||||
}
|
||||
|
||||
return err;
|
||||
}
|
||||
|
||||
bool nRF5xCharacteristicDescriptorDiscoverer::isActive(const DiscoveredCharacteristic& characteristic) const {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].getCharacteristic() == characteristic) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::requestTerminate(const DiscoveredCharacteristic& characteristic) {
|
||||
Discovery* discovery = findRunningDiscovery(characteristic);
|
||||
if(discovery) {
|
||||
// call terminate anyway
|
||||
terminate(discovery, BLE_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors) {
|
||||
Discovery* discovery = findRunningDiscovery(connectionHandle);
|
||||
// the discovery has been removed
|
||||
if(!discovery) {
|
||||
return;
|
||||
}
|
||||
|
||||
for (uint16_t i = 0; i < descriptors.count; ++i) {
|
||||
const ble_gattc_desc_t& desc = descriptors.descs[i];
|
||||
const ble_uuid_t& uuid = desc.uuid;
|
||||
|
||||
if (uuid.type == BLE_UUID_TYPE_BLE) {
|
||||
discovery->process(
|
||||
desc.handle, UUID(uuid.uuid)
|
||||
);
|
||||
} else {
|
||||
// discover attribute infos of the descriptor
|
||||
ble_error_t err = gattc_attr_info_discover(connectionHandle, desc.handle, desc.handle);
|
||||
if (err) {
|
||||
terminate(discovery, err);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// prepare the next discovery request (if needed)
|
||||
uint16_t startHandle = descriptors.descs[descriptors.count - 1].handle + 1;
|
||||
uint16_t endHandle = discovery->getCharacteristic().getLastHandle();
|
||||
|
||||
if(startHandle > endHandle) {
|
||||
terminate(discovery, BLE_ERROR_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
|
||||
if(err) {
|
||||
terminate(discovery, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::processAttributeInformation(
|
||||
uint16_t connectionHandle, const ble_gattc_evt_attr_info_disc_rsp_t& infos) {
|
||||
Discovery* discovery = findRunningDiscovery(connectionHandle);
|
||||
// the discovery has been removed
|
||||
if(!discovery) {
|
||||
return;
|
||||
}
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
// for all UUIDS found, process the discovery
|
||||
for (uint16_t i = 0; i < infos.count; ++i) {
|
||||
bool use_16bits_uuids = infos.format == BLE_GATTC_ATTR_INFO_FORMAT_16BIT;
|
||||
const ble_gattc_attr_info_t& attr_info = infos.attr_info[i];
|
||||
UUID uuid = use_16bits_uuids ? UUID(attr_info.info.uuid16.uuid) : UUID(attr_info.info.uuid128.uuid128, UUID::LSB);
|
||||
discovery->process(attr_info.handle, uuid);
|
||||
}
|
||||
// prepare the next round of descriptors discovery
|
||||
uint16_t startHandle = infos.attr_info[infos.count - 1].handle + 1;
|
||||
#else
|
||||
uint16_t startHandle;
|
||||
// for all UUIDS found, process the discovery
|
||||
if (infos.format == BLE_GATTC_ATTR_INFO_FORMAT_16BIT) {
|
||||
|
||||
for (uint16_t i = 0; i < infos.count; ++i) {
|
||||
UUID uuid = UUID(infos.info.attr_info16[i].uuid.uuid);
|
||||
discovery->process(infos.info.attr_info16[i].handle, uuid);
|
||||
}
|
||||
|
||||
// prepare the next round of descriptors discovery
|
||||
startHandle = infos.info.attr_info16[infos.count - 1].handle + 1;
|
||||
} else {
|
||||
for (uint16_t i = 0; i < infos.count; ++i) {
|
||||
UUID uuid = UUID(infos.info.attr_info128[i].uuid.uuid128, UUID::LSB);
|
||||
discovery->process(infos.info.attr_info128[i].handle, uuid);
|
||||
}
|
||||
|
||||
// prepare the next round of descriptors discovery
|
||||
startHandle = infos.info.attr_info128[infos.count - 1].handle + 1;
|
||||
}
|
||||
#endif
|
||||
uint16_t endHandle = discovery->getCharacteristic().getLastHandle();
|
||||
|
||||
if(startHandle > endHandle) {
|
||||
terminate(discovery, BLE_ERROR_NONE);
|
||||
return;
|
||||
}
|
||||
|
||||
ble_error_t err = gattc_descriptors_discover(connectionHandle, startHandle, endHandle);
|
||||
if(err) {
|
||||
terminate(discovery, err);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::terminate(uint16_t handle, ble_error_t err) {
|
||||
Discovery* discovery = findRunningDiscovery(handle);
|
||||
// the discovery has already been terminated
|
||||
if(!discovery) {
|
||||
return;
|
||||
}
|
||||
|
||||
terminate(discovery, err);
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::terminate(Discovery* discovery, ble_error_t err) {
|
||||
// temporary copy, user code can try to launch a new discovery in the onTerminate
|
||||
// callback. So, this discovery should not appear in such case.
|
||||
Discovery tmp = *discovery;
|
||||
*discovery = Discovery();
|
||||
tmp.terminate(err);
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(const DiscoveredCharacteristic& characteristic) {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if((discoveryRunning[i].getCharacteristic() == characteristic) &&
|
||||
(discoveryRunning[i].isEmpty() == false)) {
|
||||
return &discoveryRunning[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::findRunningDiscovery(uint16_t handle) {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if((discoveryRunning[i].getCharacteristic().getConnectionHandle() == handle) &&
|
||||
(discoveryRunning[i].isEmpty() == false)) {
|
||||
return &discoveryRunning[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery*
|
||||
nRF5xCharacteristicDescriptorDiscoverer::getAvailableDiscoverySlot() {
|
||||
for(size_t i = 0; i < MAXIMUM_CONCURRENT_CONNECTIONS_COUNT; ++i) {
|
||||
if(discoveryRunning[i].isEmpty()) {
|
||||
return &discoveryRunning[i];
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool nRF5xCharacteristicDescriptorDiscoverer::isConnectionInUse(uint16_t connHandle) {
|
||||
return findRunningDiscovery(connHandle) != NULL;
|
||||
}
|
||||
|
||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_descriptors_discover(
|
||||
uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
|
||||
|
||||
ble_gattc_handle_range_t discoveryRange = {
|
||||
start_handle,
|
||||
end_handle
|
||||
};
|
||||
uint32_t err = sd_ble_gattc_descriptors_discover(connection_handle, &discoveryRange);
|
||||
|
||||
switch(err) {
|
||||
case NRF_SUCCESS:
|
||||
return BLE_ERROR_NONE;
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
case NRF_ERROR_BUSY:
|
||||
return BLE_STACK_BUSY;
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
ble_error_t nRF5xCharacteristicDescriptorDiscoverer::gattc_attr_info_discover(
|
||||
uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle) {
|
||||
ble_gattc_handle_range_t handle_range = { start_handle, end_handle };
|
||||
uint32_t err = sd_ble_gattc_attr_info_discover(connection_handle, &handle_range);
|
||||
|
||||
switch(err) {
|
||||
case NRF_SUCCESS:
|
||||
return BLE_ERROR_NONE;
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
return BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
case NRF_ERROR_BUSY:
|
||||
return BLE_STACK_BUSY;
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
default:
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// implementation of nRF5xCharacteristicDescriptorDiscoverer::Discovery
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery() :
|
||||
characteristic(), onDiscovery(), onTerminate() {
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer::Discovery::Discovery(
|
||||
const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb) :
|
||||
characteristic(c), onDiscovery(dCb), onTerminate(tCb) {
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::Discovery::process(
|
||||
GattAttribute::Handle_t handle, const UUID& uuid) {
|
||||
CharacteristicDescriptorDiscovery::DiscoveryCallbackParams_t params = {
|
||||
characteristic,
|
||||
DiscoveredCharacteristicDescriptor(
|
||||
characteristic.getGattClient(),
|
||||
characteristic.getConnectionHandle(),
|
||||
handle,
|
||||
uuid
|
||||
)
|
||||
};
|
||||
onDiscovery.call(¶ms);
|
||||
}
|
||||
|
||||
void nRF5xCharacteristicDescriptorDiscoverer::Discovery::terminate(ble_error_t err) {
|
||||
CharacteristicDescriptorDiscovery::TerminationCallbackParams_t params = {
|
||||
characteristic,
|
||||
err
|
||||
};
|
||||
|
||||
onTerminate.call(¶ms);
|
||||
}
|
||||
|
||||
bool nRF5xCharacteristicDescriptorDiscoverer::Discovery::isEmpty() const {
|
||||
return *this == Discovery();
|
||||
}
|
||||
|
||||
const DiscoveredCharacteristic& nRF5xCharacteristicDescriptorDiscoverer::Discovery::getCharacteristic() const {
|
||||
return characteristic;
|
||||
}
|
|
@ -0,0 +1,227 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
|
||||
#define __NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__
|
||||
|
||||
#include "ble/Gap.h"
|
||||
#include "ble/DiscoveredCharacteristic.h"
|
||||
#include "ble/CharacteristicDescriptorDiscovery.h"
|
||||
#include "ble/GattClient.h"
|
||||
#include "ble_gattc.h"
|
||||
|
||||
/**
|
||||
* @brief Manage the discovery of Characteristic descriptors
|
||||
* @details is a bridge between BLE API and Nordic stack regarding Characteristic
|
||||
* Descriptor discovery. The BLE API can launch, monitor and ask for termination
|
||||
* of a discovery. The Nordic stack will provide new descriptors and indicate when
|
||||
* the discovery is done.
|
||||
*/
|
||||
class nRF5xCharacteristicDescriptorDiscoverer
|
||||
{
|
||||
typedef CharacteristicDescriptorDiscovery::DiscoveryCallback_t DiscoveryCallback_t;
|
||||
typedef CharacteristicDescriptorDiscovery::TerminationCallback_t TerminationCallback_t;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Construct a new characteristic descriptor discoverer.
|
||||
*/
|
||||
nRF5xCharacteristicDescriptorDiscoverer();
|
||||
|
||||
/**
|
||||
* @brief Destroy a characteristic descriptor discoverer.
|
||||
*/
|
||||
~nRF5xCharacteristicDescriptorDiscoverer();
|
||||
|
||||
/**
|
||||
* Launch a new characteristic descriptor discovery for a given DiscoveredCharacteristic.
|
||||
* @param characteristic The characteristic owning the descriptors to discover.
|
||||
* @param discoveryCallback The callback called when a descriptor is discovered.
|
||||
* @param terminationCallback The callback called when the discovery process end.
|
||||
* @return BLE_ERROR_NONE if characteristic descriptor discovery is launched successfully;
|
||||
* else an appropriate error.
|
||||
* @note: this will be called by BLE API side.
|
||||
*/
|
||||
ble_error_t launch(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const DiscoveryCallback_t& discoveryCallback,
|
||||
const TerminationCallback_t& terminationCallback
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief indicate if a characteristic descriptor discovery is active for a
|
||||
* given DiscoveredCharacteristic.
|
||||
* @param characteristic The characteristic for whom the descriptor might be
|
||||
* currently discovered.
|
||||
* @return true if descriptors of characteristic are discovered, false otherwise.
|
||||
* @note: this will be called by BLE API side.
|
||||
*/
|
||||
bool isActive(const DiscoveredCharacteristic& characteristic) const;
|
||||
|
||||
/**
|
||||
* @brief request the termination of characteristic descriptor discovery
|
||||
* for a give DiscoveredCharacteristic
|
||||
* @param characteristic The characteristic for whom the descriptor discovery
|
||||
* should be stopped.
|
||||
* @note: this will be called by BLE API side.
|
||||
*/
|
||||
void requestTerminate(const DiscoveredCharacteristic& characteristic);
|
||||
|
||||
/**
|
||||
* @brief process descriptors discovered from the Nordic stack.
|
||||
* @param connectionHandle The connection handle upon which descriptors has been
|
||||
* discovered.
|
||||
* @param descriptors Discovered descriptors.
|
||||
* @note This will be called by the Nordic stack.
|
||||
*/
|
||||
void process(uint16_t connectionHandle, const ble_gattc_evt_desc_disc_rsp_t& descriptors);
|
||||
|
||||
/**
|
||||
* @brief Called by the Nordic stack when the discovery is over.
|
||||
* @param The connection handle upon which the discovery process is done.
|
||||
* @param err An error if the termination is due to an error.
|
||||
*/
|
||||
void terminate(uint16_t connectionHandle, ble_error_t err);
|
||||
|
||||
/**
|
||||
* @brief process attribute informations from the Nordic stack.
|
||||
* @param connectionHandle The connection handle upon which
|
||||
* attribute informations has been fetch.
|
||||
* @param infos Informations around attribute, in that case the
|
||||
* 128bit UUID of a descriptor.
|
||||
* @note This will be called by the Nordic stack.
|
||||
*/
|
||||
void processAttributeInformation(uint16_t handle, const ble_gattc_evt_attr_info_disc_rsp_t& infos);
|
||||
|
||||
private:
|
||||
// protection against copy construction and assignment
|
||||
nRF5xCharacteristicDescriptorDiscoverer(const nRF5xCharacteristicDescriptorDiscoverer&);
|
||||
nRF5xCharacteristicDescriptorDiscoverer& operator=(const nRF5xCharacteristicDescriptorDiscoverer&);
|
||||
|
||||
/**
|
||||
* @brief Discovery process, it store the DiscoveredCharacteristic, the
|
||||
* discovery callback and the termination callback.
|
||||
*/
|
||||
class Discovery {
|
||||
public:
|
||||
/**
|
||||
* @brief Construct an empty discovery, such can be considerate as a not running discovery.
|
||||
* @note #isEmpty function will return true
|
||||
*/
|
||||
Discovery();
|
||||
|
||||
/**
|
||||
* @brief Construct a valid discovery process.
|
||||
*
|
||||
* @param c the characteristic from whom descriptors will be discovered.
|
||||
* @param dCb The discovery callback called each time a descriptor is discovered.
|
||||
* @param tCb The termination callback called when the discovery terminate.
|
||||
*
|
||||
* @note #isEmpty function will return false
|
||||
*/
|
||||
Discovery(const DiscoveredCharacteristic& c, const DiscoveryCallback_t& dCb, const TerminationCallback_t& tCb);
|
||||
|
||||
/**
|
||||
* @brief Process the discovery of a descriptor.
|
||||
*
|
||||
* @param handle The attribute handle of the descriptor found
|
||||
* @param uuid The UUID of the descriptor found.
|
||||
*/
|
||||
void process(GattAttribute::Handle_t handle, const UUID& uuid);
|
||||
|
||||
/**
|
||||
* @brief Terminate the discovery process.
|
||||
*
|
||||
* @param err Error associate with the termination
|
||||
* @note after this call #isEmpty function will return true.
|
||||
*/
|
||||
void terminate(ble_error_t err);
|
||||
|
||||
/**
|
||||
* @brief check if the discovery process is empty or not. Empty discovery are
|
||||
* not running.
|
||||
*
|
||||
* @detail Discovery are empty after:
|
||||
* - a default construction
|
||||
* - a copy construction form a default constructed
|
||||
* - an assignment from a default constructed Discovery
|
||||
* @return true if the Discovery is empty and false otherwise.
|
||||
*/
|
||||
bool isEmpty() const;
|
||||
|
||||
/**
|
||||
* @brief return the characteristic from whom descriptors are discovered.
|
||||
* @return the characteristic from whom descriptors are discovered.
|
||||
*/
|
||||
const DiscoveredCharacteristic& getCharacteristic() const;
|
||||
|
||||
/**
|
||||
* @brief equal to operator, test if two discovery process are equal
|
||||
*
|
||||
* @param lhs left hand side of the expression
|
||||
* @param rhs right hand side of the expression
|
||||
* @return true if lhs == rhs
|
||||
*/
|
||||
friend bool operator==(const Discovery& lhs, const Discovery& rhs) {
|
||||
return lhs.characteristic == rhs.characteristic &&
|
||||
lhs.onDiscovery == rhs.onDiscovery &&
|
||||
lhs.onTerminate == rhs.onTerminate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief not equal to operator, test if two discovery process are not equal
|
||||
*
|
||||
* @param lhs left hand side of the expression
|
||||
* @param rhs right hand side of the expression
|
||||
* @return true if lhs != rhs
|
||||
*/
|
||||
friend bool operator!=(const Discovery& lhs, const Discovery& rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
private:
|
||||
DiscoveredCharacteristic characteristic;
|
||||
DiscoveryCallback_t onDiscovery;
|
||||
TerminationCallback_t onTerminate;
|
||||
};
|
||||
|
||||
// find a running discovery process
|
||||
Discovery* findRunningDiscovery(const DiscoveredCharacteristic& characteristic);
|
||||
Discovery* findRunningDiscovery(uint16_t handle);
|
||||
|
||||
// Called to terminate a discovery is over.
|
||||
void terminate(Discovery* discovery, ble_error_t err);
|
||||
|
||||
// get one slot for a discovery process
|
||||
Discovery* getAvailableDiscoverySlot();
|
||||
|
||||
// indicate if a connection is already running a discovery
|
||||
bool isConnectionInUse(uint16_t connHandle);
|
||||
|
||||
// low level start of a discovery
|
||||
static ble_error_t gattc_descriptors_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle);
|
||||
|
||||
// discovery of 128bits UUIDS
|
||||
static ble_error_t gattc_attr_info_discover(uint16_t connection_handle, uint16_t start_handle, uint16_t end_handle);
|
||||
|
||||
// count of concurrent connections which can run a descriptor discovery process
|
||||
static const size_t MAXIMUM_CONCURRENT_CONNECTIONS_COUNT = 3;
|
||||
|
||||
// array of running discoveries
|
||||
Discovery discoveryRunning[MAXIMUM_CONCURRENT_CONNECTIONS_COUNT];
|
||||
};
|
||||
|
||||
#endif /*__NRF_CHARACTERISTIC_DESCRIPTOR_DISCOVERY_H__*/
|
|
@ -0,0 +1,63 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nRF5xDiscoveredCharacteristic.h"
|
||||
#include "nRF5xGattClient.h"
|
||||
#include "ble_gatt.h"
|
||||
|
||||
void
|
||||
nRF5xDiscoveredCharacteristic::setup(nRF5xGattClient *gattcIn,
|
||||
Gap::Handle_t connectionHandleIn,
|
||||
ble_gatt_char_props_t propsIn,
|
||||
GattAttribute::Handle_t declHandleIn,
|
||||
GattAttribute::Handle_t valueHandleIn)
|
||||
{
|
||||
gattc = gattcIn;
|
||||
connHandle = connectionHandleIn;
|
||||
declHandle = declHandleIn;
|
||||
valueHandle = valueHandleIn;
|
||||
|
||||
props._broadcast = propsIn.broadcast;
|
||||
props._read = propsIn.read;
|
||||
props._writeWoResp = propsIn.write_wo_resp;
|
||||
props._write = propsIn.write;
|
||||
props._notify = propsIn.notify;
|
||||
props._indicate = propsIn.indicate;
|
||||
props._authSignedWrite = propsIn.auth_signed_wr;
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xDiscoveredCharacteristic::setup(nRF5xGattClient *gattcIn,
|
||||
Gap::Handle_t connectionHandleIn,
|
||||
UUID::ShortUUIDBytes_t uuidIn,
|
||||
ble_gatt_char_props_t propsIn,
|
||||
GattAttribute::Handle_t declHandleIn,
|
||||
GattAttribute::Handle_t valueHandleIn)
|
||||
{
|
||||
gattc = gattcIn;
|
||||
connHandle = connectionHandleIn;
|
||||
uuid = uuidIn;
|
||||
declHandle = declHandleIn;
|
||||
valueHandle = valueHandleIn;
|
||||
|
||||
props._broadcast = propsIn.broadcast;
|
||||
props._read = propsIn.read;
|
||||
props._writeWoResp = propsIn.write_wo_resp;
|
||||
props._write = propsIn.write;
|
||||
props._notify = propsIn.notify;
|
||||
props._indicate = propsIn.indicate;
|
||||
props._authSignedWrite = propsIn.auth_signed_wr;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF_DISCOVERED_CHARACTERISTIC_H__
|
||||
#define __NRF_DISCOVERED_CHARACTERISTIC_H__
|
||||
|
||||
#include "ble/DiscoveredCharacteristic.h"
|
||||
#include "ble_gatt.h"
|
||||
|
||||
class nRF5xGattClient; /* forward declaration */
|
||||
|
||||
class nRF5xDiscoveredCharacteristic : public DiscoveredCharacteristic {
|
||||
public:
|
||||
void setup(nRF5xGattClient *gattcIn,
|
||||
Gap::Handle_t connectionHandleIn,
|
||||
ble_gatt_char_props_t propsIn,
|
||||
GattAttribute::Handle_t declHandleIn,
|
||||
GattAttribute::Handle_t valueHandleIn);
|
||||
|
||||
void setup(nRF5xGattClient *gattcIn,
|
||||
Gap::Handle_t connectionHandleIn,
|
||||
UUID::ShortUUIDBytes_t uuidIn,
|
||||
ble_gatt_char_props_t propsIn,
|
||||
GattAttribute::Handle_t declHandleIn,
|
||||
GattAttribute::Handle_t valueHandleIn);
|
||||
|
||||
void setLastHandle(GattAttribute::Handle_t last) {
|
||||
lastHandle = last;
|
||||
}
|
||||
};
|
||||
|
||||
#endif /* __NRF_DISCOVERED_CHARACTERISTIC_H__ */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,276 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF5x_GAP_H__
|
||||
#define __NRF5x_GAP_H__
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#else
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
#ifndef YOTTA_CFG_WHITELIST_MAX_SIZE
|
||||
#define YOTTA_CFG_WHITELIST_MAX_SIZE BLE_GAP_WHITELIST_ADDR_MAX_COUNT
|
||||
#elif YOTTA_CFG_WHITELIST_MAX_SIZE > BLE_GAP_WHITELIST_ADDR_MAX_COUNT
|
||||
#undef YOTTA_CFG_WHITELIST_MAX_SIZE
|
||||
#define YOTTA_CFG_WHITELIST_MAX_SIZE BLE_GAP_WHITELIST_ADDR_MAX_COUNT
|
||||
#endif
|
||||
#ifndef YOTTA_CFG_IRK_TABLE_MAX_SIZE
|
||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
||||
#define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_DEVICE_IDENTITIES_MAX_COUNT
|
||||
#else
|
||||
#define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT
|
||||
#endif
|
||||
#elif YOTTA_CFG_IRK_TABLE_MAX_SIZE > BLE_GAP_WHITELIST_IRK_MAX_COUNT
|
||||
#undef YOTTA_CFG_IRK_TABLE_MAX_SIZE
|
||||
#define YOTTA_CFG_IRK_TABLE_MAX_SIZE BLE_GAP_WHITELIST_IRK_MAX_COUNT
|
||||
#endif
|
||||
#include "ble/blecommon.h"
|
||||
#include "headers/ble.h"
|
||||
#include "ble/GapAdvertisingParams.h"
|
||||
#include "ble/GapAdvertisingData.h"
|
||||
#include "ble/Gap.h"
|
||||
#include "ble/GapScanningParams.h"
|
||||
|
||||
#include "nrf_soc.h"
|
||||
|
||||
extern "C" {
|
||||
#include "ble_radio_notification.h"
|
||||
#include "app_util_platform.h"
|
||||
}
|
||||
|
||||
#include "btle_security.h"
|
||||
|
||||
void radioNotificationStaticCallback(bool param);
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
\brief
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
class nRF5xGap : public Gap
|
||||
{
|
||||
public:
|
||||
/* Functions that must be implemented from Gap */
|
||||
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 GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MIN);}
|
||||
virtual uint16_t getMinNonConnectableAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_NONCON_INTERVAL_MIN);}
|
||||
virtual uint16_t getMaxAdvertisingInterval(void) const {return GapAdvertisingParams::ADVERTISEMENT_DURATION_UNITS_TO_MS(BLE_GAP_ADV_INTERVAL_MAX);}
|
||||
|
||||
virtual ble_error_t startAdvertising(const GapAdvertisingParams &);
|
||||
virtual ble_error_t stopAdvertising(void);
|
||||
virtual ble_error_t connect(const Address_t, BLEProtocol::AddressType_t peerAddrType, const ConnectionParams_t *connectionParams, const GapScanningParams *scanParams);
|
||||
virtual ble_error_t disconnect(Handle_t connectionHandle, DisconnectionReason_t reason);
|
||||
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(GapAdvertisingData::Appearance appearance);
|
||||
virtual ble_error_t getAppearance(GapAdvertisingData::Appearance *appearanceP);
|
||||
|
||||
virtual ble_error_t setTxPower(int8_t txPower);
|
||||
virtual void getPermittedTxPowerValues(const int8_t **valueArrayPP, size_t *countP);
|
||||
|
||||
void setConnectionHandle(uint16_t con_handle);
|
||||
uint16_t getConnectionHandle(void);
|
||||
|
||||
virtual ble_error_t getPreferredConnectionParams(ConnectionParams_t *params);
|
||||
virtual ble_error_t setPreferredConnectionParams(const ConnectionParams_t *params);
|
||||
virtual ble_error_t updateConnectionParams(Handle_t handle, const ConnectionParams_t *params);
|
||||
|
||||
virtual ble_error_t reset(void);
|
||||
|
||||
/*
|
||||
* The following functions are part of the whitelisting experimental API.
|
||||
* Therefore, this functionality can change in the near future.
|
||||
*/
|
||||
virtual uint8_t getMaxWhitelistSize(void) const;
|
||||
virtual ble_error_t getWhitelist(Gap::Whitelist_t &whitelistOut) const;
|
||||
virtual ble_error_t setWhitelist(const Gap::Whitelist_t &whitelistIn);
|
||||
|
||||
virtual ble_error_t setAdvertisingPolicyMode(AdvertisingPolicyMode_t mode);
|
||||
virtual ble_error_t setScanningPolicyMode(ScanningPolicyMode_t mode);
|
||||
virtual ble_error_t setInitiatorPolicyMode(InitiatorPolicyMode_t mode);
|
||||
virtual Gap::AdvertisingPolicyMode_t getAdvertisingPolicyMode(void) const;
|
||||
virtual Gap::ScanningPolicyMode_t getScanningPolicyMode(void) const;
|
||||
virtual Gap::InitiatorPolicyMode_t getInitiatorPolicyMode(void) const;
|
||||
|
||||
virtual ble_error_t initRadioNotification(void) {
|
||||
if (ble_radio_notification_init(APP_IRQ_PRIORITY_HIGH /*MID*/, NRF_RADIO_NOTIFICATION_DISTANCE_800US, radioNotificationStaticCallback) == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_UNSPECIFIED;
|
||||
}
|
||||
|
||||
/* Observer role is not supported by S110, return BLE_ERROR_NOT_IMPLEMENTED */
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
virtual ble_error_t startRadioScan(const GapScanningParams &scanningParams);
|
||||
virtual ble_error_t stopScan(void);
|
||||
#endif
|
||||
|
||||
private:
|
||||
/*
|
||||
* Whitelisting API related structures and helper functions.
|
||||
*/
|
||||
|
||||
/* Policy modes set by the user. By default these are set to ignore the whitelist */
|
||||
Gap::AdvertisingPolicyMode_t advertisingPolicyMode;
|
||||
Gap::ScanningPolicyMode_t scanningPolicyMode;
|
||||
|
||||
/* Internal representation of a whitelist */
|
||||
uint8_t whitelistAddressesSize;
|
||||
ble_gap_addr_t whitelistAddresses[YOTTA_CFG_WHITELIST_MAX_SIZE];
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
/*
|
||||
* An internal function used to populate the ble_gap_whitelist_t that will be used by
|
||||
* the SoftDevice for filtering requests. This function is needed because for the BLE
|
||||
* API the whitelist is just a collection of keys, but for the stack it also includes
|
||||
* the IRK table.
|
||||
*/
|
||||
ble_error_t generateStackWhitelist(ble_gap_whitelist_t &whitelist);
|
||||
#endif
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
||||
/* internal type for passing a whitelist and a identities list. */
|
||||
typedef struct
|
||||
{
|
||||
ble_gap_addr_t addrs[YOTTA_CFG_WHITELIST_MAX_SIZE];
|
||||
uint32_t addrs_cnt;
|
||||
|
||||
ble_gap_id_key_t identities[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
|
||||
uint32_t identities_cnt;
|
||||
} GapWhiteAndIdentityList_t;
|
||||
|
||||
/* Function for preparing setting of the whitelist feature and the identity-resolving feature (privacy).*/
|
||||
ble_error_t getStackWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList);
|
||||
|
||||
/* Function for applying setting of the whitelist feature and identity-resolving feature (privacy).*/
|
||||
ble_error_t applyWhiteIdentityList(GapWhiteAndIdentityList_t &whiteAndIdentityList);
|
||||
|
||||
/* Function for introducing whitelist feature and the identity-resolving feature setting into SoftDevice.
|
||||
*
|
||||
* This function incorporates getStackWhiteIdentityList and applyWhiteIdentityList together. */
|
||||
ble_error_t updateWhiteAndIdentityListInStack(void);
|
||||
#endif
|
||||
|
||||
private:
|
||||
bool radioNotificationCallbackParam; /* parameter to be passed into the Timeout-generated radio notification callback. */
|
||||
Timeout radioNotificationTimeout;
|
||||
|
||||
/*
|
||||
* A helper function to post radio notification callbacks with low interrupt priority.
|
||||
*/
|
||||
void postRadioNotificationCallback(void) {
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
/*
|
||||
* In mbed OS, all user-facing BLE events (interrupts) are posted to the
|
||||
* MINAR scheduler to be executed as callbacks in thread mode. MINAR guards
|
||||
* its critical sections from interrupts by acquiring CriticalSectionLock,
|
||||
* which results in a call to sd_nvic_critical_region_enter(). Thus, it is
|
||||
* safe to invoke MINAR APIs from interrupt context as long as those
|
||||
* interrupts are blocked by sd_nvic_critical_region_enter().
|
||||
*
|
||||
* Radio notifications are a special case for the above. The Radio
|
||||
* Notification IRQ is handled at a very high priority--higher than the
|
||||
* level blocked by sd_nvic_critical_region_enter(). Thus Radio Notification
|
||||
* events can preempt MINAR's critical sections. Using MINAR APIs (such as
|
||||
* posting an event) directly in processRadioNotification() may result in a
|
||||
* race condition ending in a hard-fault.
|
||||
*
|
||||
* The solution is to *not* call MINAR APIs directly from the Radio
|
||||
* Notification handling; i.e. to do the bulk of RadioNotification
|
||||
* processing at a reduced priority which respects MINAR's critical
|
||||
* sections. Unfortunately, on a cortex-M0, there is no clean way to demote
|
||||
* priority for the currently executing interrupt--we wouldn't want to
|
||||
* demote the radio notification handling anyway because it is sensitive to
|
||||
* timing, and the system expects to finish this handling very quickly. The
|
||||
* workaround is to employ a Timeout to trigger
|
||||
* postRadioNotificationCallback() after a very short delay (~0 us) and post
|
||||
* the MINAR callback that context.
|
||||
*
|
||||
* !!!WARNING!!! Radio notifications are very time critical events. The
|
||||
* current solution is expected to work under the assumption that
|
||||
* postRadioNotificationCalback() will be executed BEFORE the next radio
|
||||
* notification event is generated.
|
||||
*/
|
||||
minar::Scheduler::postCallback(
|
||||
mbed::util::FunctionPointer1<void, bool>(&radioNotificationCallback, &FunctionPointerWithContext<bool>::call).bind(radioNotificationCallbackParam)
|
||||
);
|
||||
#else
|
||||
/*
|
||||
* In mbed classic, all user-facing BLE events execute callbacks in interrupt
|
||||
* mode. Radio Notifications are a special case because its IRQ is handled at
|
||||
* a very high priority. Thus Radio Notification events can preempt other
|
||||
* operations that require interaction with the SoftDevice such as advertising
|
||||
* payload updates and changing the Gap state. Therefore, executing a Radio
|
||||
* Notification callback directly from processRadioNotification() may result
|
||||
* in a race condition ending in a hard-fault.
|
||||
*
|
||||
* The solution is to *not* execute the Radio Notification callback directly
|
||||
* from the Radio Notification handling; i.e. to do the bulk of the
|
||||
* Radio Notification processing at a reduced priority. Unfortunately, on a
|
||||
* cortex-M0, there is no clean way to demote priority for the currently
|
||||
* executing interrupt--we wouldn't want to demote the radio notification
|
||||
* handling anyway because it is sensitive to timing, and the system expects
|
||||
* to finish this handling very quickly. The workaround is to employ a Timeout
|
||||
* to trigger postRadioNotificationCallback() after a very short delay (~0 us)
|
||||
* and execute the callback in that context.
|
||||
*
|
||||
* !!!WARNING!!! Radio notifications are very time critical events. The
|
||||
* current solution is expected to work under the assumption that
|
||||
* postRadioNotificationCalback() will be executed BEFORE the next radio
|
||||
* notification event is generated.
|
||||
*/
|
||||
radioNotificationCallback.call(radioNotificationCallbackParam);
|
||||
#endif /* #ifdef YOTTA_CFG_MBED_OS */
|
||||
}
|
||||
|
||||
/**
|
||||
* A helper function to process radio-notification events; to be called internally.
|
||||
* @param param [description]
|
||||
*/
|
||||
void processRadioNotificationEvent(bool param) {
|
||||
radioNotificationCallbackParam = param;
|
||||
radioNotificationTimeout.attach_us(mbed::callback(this, &nRF5xGap::postRadioNotificationCallback), 0);
|
||||
}
|
||||
friend void radioNotificationStaticCallback(bool param); /* allow invocations of processRadioNotificationEvent() */
|
||||
|
||||
private:
|
||||
uint16_t m_connectionHandle;
|
||||
|
||||
/*
|
||||
* Allow instantiation from nRF5xn when required.
|
||||
*/
|
||||
friend class nRF5xn;
|
||||
|
||||
nRF5xGap() :
|
||||
advertisingPolicyMode(Gap::ADV_POLICY_IGNORE_WHITELIST),
|
||||
scanningPolicyMode(Gap::SCAN_POLICY_IGNORE_WHITELIST),
|
||||
whitelistAddressesSize(0) {
|
||||
m_connectionHandle = BLE_CONN_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
nRF5xGap(nRF5xGap const &);
|
||||
void operator=(nRF5xGap const &);
|
||||
};
|
||||
|
||||
#endif // ifndef __NRF5x_GAP_H__
|
|
@ -0,0 +1,50 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nRF5xGattClient.h"
|
||||
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
ble_error_t
|
||||
nRF5xGattClient::launchServiceDiscovery(Gap::Handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t sc,
|
||||
ServiceDiscovery::CharacteristicCallback_t cc,
|
||||
const UUID &matchingServiceUUIDIn,
|
||||
const UUID &matchingCharacteristicUUIDIn)
|
||||
{
|
||||
return _discovery.launch(connectionHandle, sc, cc, matchingServiceUUIDIn, matchingCharacteristicUUIDIn);
|
||||
}
|
||||
|
||||
ble_error_t nRF5xGattClient::discoverCharacteristicDescriptors(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback)
|
||||
{
|
||||
return _characteristicDescriptorDiscoverer.launch(
|
||||
characteristic,
|
||||
discoveryCallback,
|
||||
terminationCallback
|
||||
);
|
||||
}
|
||||
|
||||
bool nRF5xGattClient::isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const {
|
||||
return _characteristicDescriptorDiscoverer.isActive(characteristic);
|
||||
}
|
||||
|
||||
void nRF5xGattClient::terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic) {
|
||||
return _characteristicDescriptorDiscoverer.requestTerminate(characteristic);
|
||||
}
|
||||
|
||||
#endif
|
|
@ -0,0 +1,218 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF51822_GATT_CLIENT_H__
|
||||
#define __NRF51822_GATT_CLIENT_H__
|
||||
|
||||
#include "ble/GattClient.h"
|
||||
#include "nRF5xServiceDiscovery.h"
|
||||
#include "nRF5xCharacteristicDescriptorDiscoverer.h"
|
||||
|
||||
class nRF5xGattClient : public GattClient
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* When using S110, all Gatt client features will return
|
||||
* BLE_ERROR_NOT_IMPLEMENTED
|
||||
*/
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
|
||||
/**
|
||||
* Launch service discovery. Once launched, service discovery will remain
|
||||
* active with callbacks being issued back into the application for matching
|
||||
* services/characteristics. isActive() can be used to determine status; and
|
||||
* a termination callback (if setup) will be invoked at the end. Service
|
||||
* discovery can be terminated prematurely if needed using terminate().
|
||||
*
|
||||
* @param connectionHandle
|
||||
* Handle for the connection with the peer.
|
||||
* @param sc
|
||||
* This is the application callback for matching service. Taken as
|
||||
* NULL by default. Note: service discovery may still be active
|
||||
* when this callback is issued; calling asynchronous BLE-stack
|
||||
* APIs from within this application callback might cause the
|
||||
* stack to abort service discovery. If this becomes an issue, it
|
||||
* may be better to make local copy of the discoveredService and
|
||||
* wait for service discovery to terminate before operating on the
|
||||
* service.
|
||||
* @param cc
|
||||
* This is the application callback for matching characteristic.
|
||||
* Taken as NULL by default. Note: service discovery may still be
|
||||
* active when this callback is issued; calling asynchronous
|
||||
* BLE-stack APIs from within this application callback might cause
|
||||
* the stack to abort service discovery. If this becomes an issue,
|
||||
* it may be better to make local copy of the discoveredCharacteristic
|
||||
* and wait for service discovery to terminate before operating on the
|
||||
* characteristic.
|
||||
* @param matchingServiceUUID
|
||||
* UUID based filter for specifying a service in which the application is
|
||||
* interested. By default it is set as the wildcard UUID_UNKNOWN,
|
||||
* in which case it matches all services. If characteristic-UUID
|
||||
* filter (below) is set to the wildcard value, then a service
|
||||
* callback will be invoked for the matching service (or for every
|
||||
* service if the service filter is a wildcard).
|
||||
* @param matchingCharacteristicUUIDIn
|
||||
* UUID based filter for specifying characteristic in which the application
|
||||
* is interested. By default it is set as the wildcard UUID_UKNOWN
|
||||
* to match against any characteristic. If both service-UUID
|
||||
* filter and characteristic-UUID filter are used with non- wildcard
|
||||
* values, then only a single characteristic callback is
|
||||
* invoked for the matching characteristic.
|
||||
*
|
||||
* @Note Using wildcard values for both service-UUID and characteristic-
|
||||
* UUID will result in complete service discovery--callbacks being
|
||||
* called for every service and characteristic.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if service discovery is launched successfully; else an appropriate error.
|
||||
*/
|
||||
virtual ble_error_t launchServiceDiscovery(Gap::Handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t sc = NULL,
|
||||
ServiceDiscovery::CharacteristicCallback_t cc = NULL,
|
||||
const UUID &matchingServiceUUID = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN),
|
||||
const UUID &matchingCharacteristicUUIDIn = UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN));
|
||||
|
||||
virtual void onServiceDiscoveryTermination(ServiceDiscovery::TerminationCallback_t callback) {
|
||||
_discovery.onTermination(callback);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is service-discovery currently active?
|
||||
*/
|
||||
virtual bool isServiceDiscoveryActive(void) const {
|
||||
return _discovery.isActive();
|
||||
}
|
||||
|
||||
/**
|
||||
* Terminate an ongoing service-discovery. This should result in an
|
||||
* invocation of the TerminationCallback if service-discovery is active.
|
||||
*/
|
||||
virtual void terminateServiceDiscovery(void) {
|
||||
_discovery.terminate();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Implementation of GattClient::discoverCharacteristicDescriptors
|
||||
* @see GattClient::discoverCharacteristicDescriptors
|
||||
*/
|
||||
virtual ble_error_t discoverCharacteristicDescriptors(
|
||||
const DiscoveredCharacteristic& characteristic,
|
||||
const CharacteristicDescriptorDiscovery::DiscoveryCallback_t& discoveryCallback,
|
||||
const CharacteristicDescriptorDiscovery::TerminationCallback_t& terminationCallback
|
||||
);
|
||||
|
||||
/**
|
||||
* @brief Implementation of GattClient::isCharacteristicDiscoveryActive
|
||||
* @see GattClient::isCharacteristicDiscoveryActive
|
||||
*/
|
||||
virtual bool isCharacteristicDescriptorsDiscoveryActive(const DiscoveredCharacteristic& characteristic) const;
|
||||
|
||||
/**
|
||||
* @brief Implementation of GattClient::terminateCharacteristicDiscovery
|
||||
* @see GattClient::terminateCharacteristicDiscovery
|
||||
*/
|
||||
virtual void terminateCharacteristicDescriptorsDiscovery(const DiscoveredCharacteristic& characteristic);
|
||||
|
||||
virtual ble_error_t read(Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, uint16_t offset) const {
|
||||
uint32_t rc = sd_ble_gattc_read(connHandle, attributeHandle, offset);
|
||||
if (rc == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
switch (rc) {
|
||||
case NRF_ERROR_BUSY:
|
||||
return BLE_STACK_BUSY;
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
default:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
virtual ble_error_t write(GattClient::WriteOp_t cmd, Gap::Handle_t connHandle, GattAttribute::Handle_t attributeHandle, size_t length, const uint8_t *value) const {
|
||||
ble_gattc_write_params_t writeParams;
|
||||
writeParams.write_op = cmd;
|
||||
writeParams.flags = 0; /* this is inconsequential */
|
||||
writeParams.handle = attributeHandle;
|
||||
writeParams.offset = 0;
|
||||
writeParams.len = length;
|
||||
writeParams.p_value = const_cast<uint8_t *>(value);
|
||||
|
||||
uint32_t rc = sd_ble_gattc_write(connHandle, &writeParams);
|
||||
if (rc == NRF_SUCCESS) {
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
switch (rc) {
|
||||
case NRF_ERROR_BUSY:
|
||||
return BLE_STACK_BUSY;
|
||||
case BLE_ERROR_NO_TX_PACKETS:
|
||||
return BLE_ERROR_NO_MEM;
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
default:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear nRF5xGattClient's state.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if successful.
|
||||
*/
|
||||
virtual ble_error_t reset(void) {
|
||||
/* Clear all state that is from the parent, including private members */
|
||||
if (GattClient::reset() != BLE_ERROR_NONE) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Clear derived class members */
|
||||
_discovery.reset();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
public:
|
||||
/*
|
||||
* Allow instantiation from nRF5xn when required.
|
||||
*/
|
||||
friend class nRF5xn;
|
||||
|
||||
nRF5xGattClient() : _discovery(this) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
nRF5xServiceDiscovery& discovery() {
|
||||
return _discovery;
|
||||
}
|
||||
|
||||
nRF5xCharacteristicDescriptorDiscoverer& characteristicDescriptorDiscoverer() {
|
||||
return _characteristicDescriptorDiscoverer;
|
||||
}
|
||||
|
||||
private:
|
||||
nRF5xGattClient(const nRF5xGattClient &);
|
||||
const nRF5xGattClient& operator=(const nRF5xGattClient &);
|
||||
|
||||
private:
|
||||
nRF5xServiceDiscovery _discovery;
|
||||
nRF5xCharacteristicDescriptorDiscoverer _characteristicDescriptorDiscoverer;
|
||||
|
||||
#endif // if !S110
|
||||
};
|
||||
|
||||
#endif // ifndef __NRF51822_GATT_CLIENT_H__
|
|
@ -0,0 +1,792 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nRF5xGattServer.h"
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#else
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
|
||||
#include "common/common.h"
|
||||
#include "btle/custom/custom_helper.h"
|
||||
|
||||
#include "nRF5xn.h"
|
||||
|
||||
namespace {
|
||||
|
||||
static const ble_gatts_rw_authorize_reply_params_t write_auth_queue_full_reply = {
|
||||
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
|
||||
.params = {
|
||||
.write = {
|
||||
.gatt_status = BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_offset_reply = {
|
||||
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
|
||||
.params = {
|
||||
.write = {
|
||||
.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID_OFFSET
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ble_gatts_rw_authorize_reply_params_t write_auth_succes_reply = {
|
||||
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
|
||||
.params = {
|
||||
.write = {
|
||||
.gatt_status = BLE_GATT_STATUS_SUCCESS,
|
||||
.update = 0
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
static const ble_gatts_rw_authorize_reply_params_t write_auth_invalid_reply = {
|
||||
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
|
||||
.params = {
|
||||
.write = {
|
||||
.gatt_status = BLE_GATT_STATUS_ATTERR_INVALID
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Adds a new service to the GATT table on the peripheral
|
||||
|
||||
@returns ble_error_t
|
||||
|
||||
@retval BLE_ERROR_NONE
|
||||
Everything executed properly
|
||||
|
||||
@section EXAMPLE
|
||||
|
||||
@code
|
||||
|
||||
@endcode
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ble_error_t nRF5xGattServer::addService(GattService &service)
|
||||
{
|
||||
/* ToDo: Make sure this service UUID doesn't already exist (?) */
|
||||
/* ToDo: Basic validation */
|
||||
|
||||
/* Add the service to the nRF51 */
|
||||
ble_uuid_t nordicUUID;
|
||||
nordicUUID = custom_convert_to_nordic_uuid(service.getUUID());
|
||||
|
||||
uint16_t serviceHandle;
|
||||
ASSERT_TRUE( ERROR_NONE ==
|
||||
sd_ble_gatts_service_add(BLE_GATTS_SRVC_TYPE_PRIMARY,
|
||||
&nordicUUID,
|
||||
&serviceHandle),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||
service.setHandle(serviceHandle);
|
||||
|
||||
/* Add characteristics to the service */
|
||||
for (uint8_t i = 0; i < service.getCharacteristicCount(); i++) {
|
||||
if (characteristicCount >= BLE_TOTAL_CHARACTERISTICS) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
GattCharacteristic *p_char = service.getCharacteristic(i);
|
||||
|
||||
/* Skip any incompletely defined, read-only characteristics. */
|
||||
if ((p_char->getValueAttribute().getValuePtr() == NULL) &&
|
||||
(p_char->getValueAttribute().getLength() == 0) &&
|
||||
(p_char->getProperties() == GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_READ)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nordicUUID = custom_convert_to_nordic_uuid(p_char->getValueAttribute().getUUID());
|
||||
|
||||
/* The user-description descriptor is a special case which needs to be
|
||||
* handled at the time of adding the characteristic. The following block
|
||||
* is meant to discover its presence. */
|
||||
const uint8_t *userDescriptionDescriptorValuePtr = NULL;
|
||||
uint16_t userDescriptionDescriptorValueLen = 0;
|
||||
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
|
||||
GattAttribute *p_desc = p_char->getDescriptor(j);
|
||||
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) {
|
||||
userDescriptionDescriptorValuePtr = p_desc->getValuePtr();
|
||||
userDescriptionDescriptorValueLen = p_desc->getLength();
|
||||
}
|
||||
}
|
||||
|
||||
ASSERT_TRUE ( ERROR_NONE ==
|
||||
custom_add_in_characteristic(BLE_GATT_HANDLE_INVALID,
|
||||
&nordicUUID,
|
||||
p_char->getProperties(),
|
||||
p_char->getRequiredSecurity(),
|
||||
p_char->getValueAttribute().getValuePtr(),
|
||||
p_char->getValueAttribute().getLength(),
|
||||
p_char->getValueAttribute().getMaxLength(),
|
||||
p_char->getValueAttribute().hasVariableLength(),
|
||||
userDescriptionDescriptorValuePtr,
|
||||
userDescriptionDescriptorValueLen,
|
||||
p_char->isReadAuthorizationEnabled(),
|
||||
p_char->isWriteAuthorizationEnabled(),
|
||||
&nrfCharacteristicHandles[characteristicCount]),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||
|
||||
/* Update the characteristic handle */
|
||||
p_characteristics[characteristicCount] = p_char;
|
||||
p_char->getValueAttribute().setHandle(nrfCharacteristicHandles[characteristicCount].value_handle);
|
||||
characteristicCount++;
|
||||
|
||||
/* Add optional descriptors if any */
|
||||
for (uint8_t j = 0; j < p_char->getDescriptorCount(); j++) {
|
||||
if (descriptorCount >= BLE_TOTAL_DESCRIPTORS) {
|
||||
return BLE_ERROR_NO_MEM;
|
||||
}
|
||||
|
||||
GattAttribute *p_desc = p_char->getDescriptor(j);
|
||||
/* skip the user-description-descriptor here; this has already been handled when adding the characteristic (above). */
|
||||
if (p_desc->getUUID() == BLE_UUID_DESCRIPTOR_CHAR_USER_DESC) {
|
||||
continue;
|
||||
}
|
||||
|
||||
nordicUUID = custom_convert_to_nordic_uuid(p_desc->getUUID());
|
||||
|
||||
ASSERT_TRUE(ERROR_NONE ==
|
||||
custom_add_in_descriptor(BLE_GATT_HANDLE_INVALID,
|
||||
&nordicUUID,
|
||||
p_desc->getValuePtr(),
|
||||
p_desc->getLength(),
|
||||
p_desc->getMaxLength(),
|
||||
p_desc->hasVariableLength(),
|
||||
&nrfDescriptorHandles[descriptorCount]),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE);
|
||||
|
||||
p_descriptors[descriptorCount] = p_desc;
|
||||
p_desc->setHandle(nrfDescriptorHandles[descriptorCount]);
|
||||
descriptorCount++;
|
||||
}
|
||||
}
|
||||
|
||||
serviceCount++;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Reads the value of a characteristic, based on the service
|
||||
and characteristic index fields
|
||||
|
||||
@param[in] attributeHandle
|
||||
The handle of the GattCharacteristic to read from
|
||||
@param[in] buffer
|
||||
Buffer to hold the the characteristic's value
|
||||
(raw byte array in LSB format)
|
||||
@param[in/out] len
|
||||
input: Length in bytes to be read.
|
||||
output: Total length of attribute value upon successful return.
|
||||
|
||||
@returns ble_error_t
|
||||
|
||||
@retval BLE_ERROR_NONE
|
||||
Everything executed properly
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ble_error_t nRF5xGattServer::read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
|
||||
{
|
||||
return read(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, lengthP);
|
||||
}
|
||||
|
||||
ble_error_t nRF5xGattServer::read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP)
|
||||
{
|
||||
ble_gatts_value_t value = {
|
||||
.len = *lengthP,
|
||||
.offset = 0,
|
||||
.p_value = buffer,
|
||||
};
|
||||
|
||||
ASSERT_TRUE( ERROR_NONE ==
|
||||
sd_ble_gatts_value_get(connectionHandle, attributeHandle, &value),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE);
|
||||
*lengthP = value.len;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Updates the value of a characteristic, based on the service
|
||||
and characteristic index fields
|
||||
|
||||
@param[in] charHandle
|
||||
The handle of the GattCharacteristic to write to
|
||||
@param[in] buffer
|
||||
Data to use when updating the characteristic's value
|
||||
(raw byte array in LSB format)
|
||||
@param[in] len
|
||||
The number of bytes in buffer
|
||||
|
||||
@returns ble_error_t
|
||||
|
||||
@retval BLE_ERROR_NONE
|
||||
Everything executed properly
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ble_error_t nRF5xGattServer::write(GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
|
||||
{
|
||||
return write(BLE_CONN_HANDLE_INVALID, attributeHandle, buffer, len, localOnly);
|
||||
}
|
||||
|
||||
ble_error_t nRF5xGattServer::write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, const uint8_t buffer[], uint16_t len, bool localOnly)
|
||||
{
|
||||
ble_error_t returnValue = BLE_ERROR_NONE;
|
||||
|
||||
ble_gatts_value_t value = {
|
||||
.len = len,
|
||||
.offset = 0,
|
||||
.p_value = const_cast<uint8_t *>(buffer),
|
||||
};
|
||||
|
||||
if (localOnly) {
|
||||
/* Only update locally regardless of notify/indicate */
|
||||
ASSERT_INT( ERROR_NONE,
|
||||
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
int characteristicIndex = resolveValueHandleToCharIndex(attributeHandle);
|
||||
if ((characteristicIndex != -1) &&
|
||||
(p_characteristics[characteristicIndex]->getProperties() & (GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) {
|
||||
/* HVX update for the characteristic value */
|
||||
ble_gatts_hvx_params_t hvx_params;
|
||||
|
||||
hvx_params.handle = attributeHandle;
|
||||
hvx_params.type =
|
||||
(p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) ? BLE_GATT_HVX_NOTIFICATION : BLE_GATT_HVX_INDICATION;
|
||||
hvx_params.offset = 0;
|
||||
hvx_params.p_data = const_cast<uint8_t *>(buffer);
|
||||
hvx_params.p_len = &len;
|
||||
|
||||
if (connectionHandle == BLE_CONN_HANDLE_INVALID) { /* use the default connection handle if the caller hasn't specified a valid connectionHandle. */
|
||||
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
|
||||
connectionHandle = gap.getConnectionHandle();
|
||||
}
|
||||
error_t error = (error_t) sd_ble_gatts_hvx(connectionHandle, &hvx_params);
|
||||
if (error != ERROR_NONE) {
|
||||
switch (error) {
|
||||
case ERROR_BLE_NO_TX_BUFFERS: /* Notifications consume application buffers. The return value can be used for resending notifications. */
|
||||
case ERROR_BUSY:
|
||||
returnValue = BLE_STACK_BUSY;
|
||||
break;
|
||||
|
||||
case ERROR_INVALID_STATE:
|
||||
case ERROR_BLEGATTS_SYS_ATTR_MISSING:
|
||||
returnValue = BLE_ERROR_INVALID_STATE;
|
||||
break;
|
||||
|
||||
default :
|
||||
ASSERT_INT( ERROR_NONE,
|
||||
sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value),
|
||||
BLE_ERROR_PARAM_OUT_OF_RANGE );
|
||||
|
||||
/* Notifications consume application buffers. The return value can
|
||||
* be used for resending notifications. */
|
||||
returnValue = BLE_STACK_BUSY;
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
uint32_t err = sd_ble_gatts_value_set(connectionHandle, attributeHandle, &value);
|
||||
switch(err) {
|
||||
case NRF_SUCCESS:
|
||||
returnValue = BLE_ERROR_NONE;
|
||||
break;
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
case NRF_ERROR_INVALID_PARAM:
|
||||
returnValue = BLE_ERROR_INVALID_PARAM;
|
||||
break;
|
||||
case NRF_ERROR_NOT_FOUND:
|
||||
case NRF_ERROR_DATA_SIZE:
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
case BLE_ERROR_GATTS_INVALID_ATTR_TYPE:
|
||||
returnValue = BLE_ERROR_PARAM_OUT_OF_RANGE;
|
||||
break;
|
||||
case NRF_ERROR_FORBIDDEN:
|
||||
returnValue = BLE_ERROR_OPERATION_NOT_PERMITTED;
|
||||
break;
|
||||
default:
|
||||
returnValue = BLE_ERROR_UNSPECIFIED;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return returnValue;
|
||||
}
|
||||
|
||||
ble_error_t nRF5xGattServer::areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP)
|
||||
{
|
||||
/* Forward the call with the default connection handle. */
|
||||
nRF5xGap &gap = (nRF5xGap &) nRF5xn::Instance(BLE::DEFAULT_INSTANCE).getGap();
|
||||
return areUpdatesEnabled(gap.getConnectionHandle(), characteristic, enabledP);
|
||||
}
|
||||
|
||||
ble_error_t nRF5xGattServer::areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP)
|
||||
{
|
||||
int characteristicIndex = resolveValueHandleToCharIndex(characteristic.getValueHandle());
|
||||
if (characteristicIndex == -1) {
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
/* Read the cccd value from the GATT server. */
|
||||
GattAttribute::Handle_t cccdHandle = nrfCharacteristicHandles[characteristicIndex].cccd_handle;
|
||||
uint16_t cccdValue;
|
||||
uint16_t length = sizeof(cccdValue);
|
||||
ble_error_t rc = read(connectionHandle, cccdHandle, reinterpret_cast<uint8_t *>(&cccdValue), &length);
|
||||
if (rc != BLE_ERROR_NONE) {
|
||||
return rc;
|
||||
}
|
||||
if (length != sizeof(cccdValue)) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Check for NOTFICATION or INDICATION in CCCD. */
|
||||
if ((cccdValue & BLE_GATT_HVX_NOTIFICATION) || (cccdValue & BLE_GATT_HVX_INDICATION)) {
|
||||
*enabledP = true;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Clear nRF5xGattServer's state.
|
||||
|
||||
@returns ble_error_t
|
||||
|
||||
@retval BLE_ERROR_NONE
|
||||
Everything executed properly
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ble_error_t nRF5xGattServer::reset(void)
|
||||
{
|
||||
/* Clear all state that is from the parent, including private members */
|
||||
if (GattServer::reset() != BLE_ERROR_NONE) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Clear derived class members */
|
||||
memset(p_characteristics, 0, sizeof(p_characteristics));
|
||||
memset(p_descriptors, 0, sizeof(p_descriptors));
|
||||
memset(nrfCharacteristicHandles, 0, sizeof(ble_gatts_char_handles_t));
|
||||
memset(nrfDescriptorHandles, 0, sizeof(nrfDescriptorHandles));
|
||||
descriptorCount = 0;
|
||||
|
||||
releaseAllWriteRequests();
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Callback handler for events getting pushed up from the SD
|
||||
*/
|
||||
/**************************************************************************/
|
||||
void nRF5xGattServer::hwCallback(ble_evt_t *p_ble_evt)
|
||||
{
|
||||
GattAttribute::Handle_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 = gattsEventP->params.write.handle;
|
||||
int characteristicIndex = resolveCCCDHandleToCharIndex(handle_value);
|
||||
if ((characteristicIndex != -1) &&
|
||||
(p_characteristics[characteristicIndex]->getProperties() &
|
||||
(GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE | GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY))) {
|
||||
|
||||
uint16_t cccd_value = (gattsEventP->params.write.data[1] << 8) | gattsEventP->params.write.data[0]; /* Little Endian but M0 may be mis-aligned */
|
||||
|
||||
if (((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_INDICATE) && (cccd_value & BLE_GATT_HVX_INDICATION)) ||
|
||||
((p_characteristics[characteristicIndex]->getProperties() & GattCharacteristic::BLE_GATT_CHAR_PROPERTIES_NOTIFY) && (cccd_value & BLE_GATT_HVX_NOTIFICATION))) {
|
||||
eventType = GattServerEvents::GATT_EVENT_UPDATES_ENABLED;
|
||||
} else {
|
||||
eventType = GattServerEvents::GATT_EVENT_UPDATES_DISABLED;
|
||||
}
|
||||
|
||||
handleEvent(eventType, p_characteristics[characteristicIndex]->getValueHandle());
|
||||
return;
|
||||
}
|
||||
|
||||
/* 2.) Changes to the characteristic value will be handled with other events below */
|
||||
eventType = GattServerEvents::GATT_EVENT_DATA_WRITTEN;
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_GATTS_EVT_HVC:
|
||||
/* Indication confirmation received */
|
||||
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(gattsEventP->conn_handle, NULL, 0, 0);
|
||||
return;
|
||||
|
||||
case BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST:
|
||||
switch (gattsEventP->params.authorize_request.type) {
|
||||
case BLE_GATTS_AUTHORIZE_TYPE_READ:
|
||||
eventType = GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ;
|
||||
handle_value = gattsEventP->params.authorize_request.request.read.handle;
|
||||
break;
|
||||
case BLE_GATTS_AUTHORIZE_TYPE_WRITE:
|
||||
eventType = GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ;
|
||||
handle_value = gattsEventP->params.authorize_request.request.write.handle;
|
||||
break;
|
||||
default:
|
||||
return;
|
||||
}
|
||||
break;
|
||||
|
||||
case BLE_EVT_USER_MEM_REQUEST: {
|
||||
uint16_t conn_handle = p_ble_evt->evt.common_evt.conn_handle;
|
||||
|
||||
// allocate a new long request for this connection
|
||||
// NOTE: we don't care about the result at this stage,
|
||||
// it is not possible to cancel the operation anyway.
|
||||
// If the request was not allocated then it will gracefully failled
|
||||
// at subsequent stages.
|
||||
allocateLongWriteRequest(conn_handle);
|
||||
sd_ble_user_mem_reply(conn_handle, NULL);
|
||||
return;
|
||||
}
|
||||
|
||||
default:
|
||||
return;
|
||||
}
|
||||
|
||||
int characteristicIndex = resolveValueHandleToCharIndex(handle_value);
|
||||
if (characteristicIndex == -1) {
|
||||
// filter out the case were the request is a long one,
|
||||
// and there is no attribute handle provided
|
||||
uint8_t write_op = gattsEventP->params.authorize_request.request.write.op;
|
||||
if (eventType != GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ ||
|
||||
(write_op != BLE_GATTS_OP_EXEC_WRITE_REQ_NOW &&
|
||||
write_op != BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
/* Find index (charHandle) in the pool */
|
||||
switch (eventType) {
|
||||
case GattServerEvents::GATT_EVENT_DATA_WRITTEN: {
|
||||
GattWriteCallbackParams cbParams = {
|
||||
.connHandle = gattsEventP->conn_handle,
|
||||
.handle = handle_value,
|
||||
.writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.write.op),
|
||||
.offset = gattsEventP->params.write.offset,
|
||||
.len = gattsEventP->params.write.len,
|
||||
.data = gattsEventP->params.write.data
|
||||
};
|
||||
handleDataWrittenEvent(&cbParams);
|
||||
break;
|
||||
}
|
||||
case GattServerEvents::GATT_EVENT_WRITE_AUTHORIZATION_REQ: {
|
||||
uint16_t conn_handle = gattsEventP->conn_handle;
|
||||
const ble_gatts_evt_write_t& input_req = gattsEventP->params.authorize_request.request.write;
|
||||
const uint16_t max_size = getBiggestCharacteristicSize();
|
||||
|
||||
// this is a long write request, handle it here.
|
||||
switch (input_req.op) {
|
||||
case BLE_GATTS_OP_PREP_WRITE_REQ: {
|
||||
// verify that the request is not outside of the possible range
|
||||
if ((input_req.offset + input_req.len) > max_size) {
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply);
|
||||
releaseLongWriteRequest(conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// find the write request
|
||||
long_write_request_t* req = findLongWriteRequest(conn_handle);
|
||||
if (!req) {
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
|
||||
return;
|
||||
}
|
||||
|
||||
// initialize the first request by setting the offset
|
||||
if (req->length == 0) {
|
||||
req->attr_handle = input_req.handle;
|
||||
req->offset = input_req.offset;
|
||||
} else {
|
||||
// it should be the subsequent write
|
||||
if ((req->offset + req->length) != input_req.offset) {
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_offset_reply);
|
||||
releaseLongWriteRequest(conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// it is not allowed to write multiple characteristic with the same request
|
||||
if (input_req.handle != req->attr_handle) {
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
|
||||
releaseLongWriteRequest(conn_handle);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// start the copy of what is in input
|
||||
memcpy(req->data + req->length, input_req.data, input_req.len);
|
||||
|
||||
// update the lenght of the data written
|
||||
req->length = req->length + input_req.len;
|
||||
|
||||
// success, signal it to the softdevice
|
||||
ble_gatts_rw_authorize_reply_params_t reply = {
|
||||
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
|
||||
.params = {
|
||||
.write = {
|
||||
.gatt_status = BLE_GATT_STATUS_SUCCESS,
|
||||
.update = 1,
|
||||
.offset = input_req.offset,
|
||||
.len = input_req.len,
|
||||
.p_data = input_req.data
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &reply);
|
||||
} return;
|
||||
|
||||
case BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL: {
|
||||
releaseLongWriteRequest(conn_handle);
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply);
|
||||
} return;
|
||||
|
||||
case BLE_GATTS_OP_EXEC_WRITE_REQ_NOW: {
|
||||
long_write_request_t* req = findLongWriteRequest(conn_handle);
|
||||
if (!req) {
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
|
||||
return;
|
||||
}
|
||||
|
||||
GattWriteAuthCallbackParams cbParams = {
|
||||
.connHandle = conn_handle,
|
||||
.handle = req->attr_handle,
|
||||
.offset = req->offset,
|
||||
.len = req->length,
|
||||
.data = req->data,
|
||||
.authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
|
||||
* set to AUTH_CALLBACK_REPLY_SUCCESS if the client
|
||||
* request is to proceed. */
|
||||
};
|
||||
uint16_t write_authorization = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams);
|
||||
|
||||
// the user code didn't provide the write authorization,
|
||||
// just leave here.
|
||||
if (write_authorization != AUTH_CALLBACK_REPLY_SUCCESS) {
|
||||
// report the status of the operation in any cases
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
|
||||
releaseLongWriteRequest(conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
// FIXME can't use ::write here, this function doesn't take the offset into account ...
|
||||
ble_gatts_value_t value = {
|
||||
.len = req->length,
|
||||
.offset = req->offset,
|
||||
.p_value = req->data
|
||||
};
|
||||
uint32_t update_err = sd_ble_gatts_value_set(conn_handle, req->attr_handle, &value);
|
||||
if (update_err) {
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_invalid_reply);
|
||||
releaseLongWriteRequest(conn_handle);
|
||||
return;
|
||||
}
|
||||
|
||||
sd_ble_gatts_rw_authorize_reply(conn_handle, &write_auth_succes_reply);
|
||||
|
||||
GattWriteCallbackParams writeParams = {
|
||||
.connHandle = conn_handle,
|
||||
.handle = req->attr_handle,
|
||||
.writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(input_req.op),
|
||||
.offset = req->offset,
|
||||
.len = req->length,
|
||||
.data = req->data,
|
||||
};
|
||||
handleDataWrittenEvent(&writeParams);
|
||||
releaseLongWriteRequest(conn_handle);
|
||||
} return;
|
||||
}
|
||||
|
||||
GattWriteAuthCallbackParams cbParams = {
|
||||
.connHandle = gattsEventP->conn_handle,
|
||||
.handle = handle_value,
|
||||
.offset = gattsEventP->params.authorize_request.request.write.offset,
|
||||
.len = gattsEventP->params.authorize_request.request.write.len,
|
||||
.data = gattsEventP->params.authorize_request.request.write.data,
|
||||
.authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
|
||||
* set to AUTH_CALLBACK_REPLY_SUCCESS if the client
|
||||
* request is to proceed. */
|
||||
};
|
||||
|
||||
ble_gatts_rw_authorize_reply_params_t reply = {
|
||||
.type = BLE_GATTS_AUTHORIZE_TYPE_WRITE,
|
||||
.params = {
|
||||
.write = {
|
||||
.gatt_status = p_characteristics[characteristicIndex]->authorizeWrite(&cbParams),
|
||||
.update = 1,
|
||||
.offset = cbParams.offset,
|
||||
.len = cbParams.len,
|
||||
.p_data = cbParams.data
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (reply.params.write.gatt_status != BLE_GATT_STATUS_SUCCESS)
|
||||
{
|
||||
reply.params.write.update = 0;
|
||||
}
|
||||
|
||||
sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply);
|
||||
|
||||
/*
|
||||
* If write-authorization is enabled for a characteristic,
|
||||
* AUTHORIZATION_REQ event (if replied with true) is *not*
|
||||
* followed by another DATA_WRITTEN event; so we still need
|
||||
* to invoke handleDataWritten(), much the same as we would
|
||||
* have done if write-authorization had not been enabled.
|
||||
*/
|
||||
if (reply.params.write.gatt_status == BLE_GATT_STATUS_SUCCESS) {
|
||||
GattWriteCallbackParams cbParams = {
|
||||
.connHandle = gattsEventP->conn_handle,
|
||||
.handle = handle_value,
|
||||
.writeOp = static_cast<GattWriteCallbackParams::WriteOp_t>(gattsEventP->params.authorize_request.request.write.op),
|
||||
.offset = gattsEventP->params.authorize_request.request.write.offset,
|
||||
.len = gattsEventP->params.authorize_request.request.write.len,
|
||||
.data = gattsEventP->params.authorize_request.request.write.data,
|
||||
};
|
||||
handleDataWrittenEvent(&cbParams);
|
||||
}
|
||||
break;
|
||||
}
|
||||
case GattServerEvents::GATT_EVENT_READ_AUTHORIZATION_REQ: {
|
||||
GattReadAuthCallbackParams cbParams = {
|
||||
.connHandle = gattsEventP->conn_handle,
|
||||
.handle = handle_value,
|
||||
.offset = gattsEventP->params.authorize_request.request.read.offset,
|
||||
.len = 0,
|
||||
.data = NULL,
|
||||
.authorizationReply = AUTH_CALLBACK_REPLY_SUCCESS /* the callback handler must leave this member
|
||||
* set to AUTH_CALLBACK_REPLY_SUCCESS if the client
|
||||
* request is to proceed. */
|
||||
};
|
||||
|
||||
ble_gatts_rw_authorize_reply_params_t reply = {
|
||||
.type = BLE_GATTS_AUTHORIZE_TYPE_READ,
|
||||
.params = {
|
||||
.read = {
|
||||
.gatt_status = p_characteristics[characteristicIndex]->authorizeRead(&cbParams)
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
if (cbParams.authorizationReply == BLE_GATT_STATUS_SUCCESS) {
|
||||
if (cbParams.data != NULL) {
|
||||
reply.params.read.update = 1;
|
||||
reply.params.read.offset = cbParams.offset;
|
||||
reply.params.read.len = cbParams.len;
|
||||
reply.params.read.p_data = cbParams.data;
|
||||
}
|
||||
}
|
||||
|
||||
sd_ble_gatts_rw_authorize_reply(gattsEventP->conn_handle, &reply);
|
||||
break;
|
||||
}
|
||||
|
||||
default:
|
||||
handleEvent(eventType, handle_value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
uint16_t nRF5xGattServer::getBiggestCharacteristicSize() const {
|
||||
uint16_t result = 0;
|
||||
for (size_t i = 0; i < characteristicCount; ++i) {
|
||||
uint16_t current_size = p_characteristics[i]->getValueAttribute().getMaxLength();
|
||||
if (current_size > result) {
|
||||
result = current_size;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
nRF5xGattServer::long_write_request_t* nRF5xGattServer::allocateLongWriteRequest(uint16_t connection_handle) {
|
||||
for (size_t i = 0; i < TOTAL_CONCURRENT_LONG_WRITE_REQUESTS; ++i) {
|
||||
long_write_request_t& req = long_write_requests[i];
|
||||
if (req.data == NULL) {
|
||||
uint16_t block_size = getBiggestCharacteristicSize();
|
||||
req.data = static_cast<uint8_t*>(malloc(block_size));
|
||||
req.offset = 0;
|
||||
req.length = 0;
|
||||
req.conn_handle = connection_handle;
|
||||
return &req;
|
||||
}
|
||||
}
|
||||
// if nothing has been found then return null
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool nRF5xGattServer::releaseLongWriteRequest(uint16_t connection_handle) {
|
||||
long_write_request_t* req = findLongWriteRequest(connection_handle);
|
||||
if (!req) {
|
||||
return false;
|
||||
}
|
||||
|
||||
free(req->data);
|
||||
req->data = NULL;
|
||||
|
||||
// the other fields are not relevant, return now
|
||||
return true;
|
||||
}
|
||||
|
||||
nRF5xGattServer::long_write_request_t* nRF5xGattServer::findLongWriteRequest(uint16_t connection_handle) {
|
||||
for (size_t i = 0; i < TOTAL_CONCURRENT_LONG_WRITE_REQUESTS; ++i) {
|
||||
long_write_request_t& req = long_write_requests[i];
|
||||
if (req.data != NULL && req.conn_handle == connection_handle) {
|
||||
return &req;
|
||||
}
|
||||
}
|
||||
// if nothing has been found then return null
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void nRF5xGattServer::releaseAllWriteRequests() {
|
||||
for (size_t i = 0; i < TOTAL_CONCURRENT_LONG_WRITE_REQUESTS; ++i) {
|
||||
long_write_request_t& req = long_write_requests[i];
|
||||
if (req.data != NULL) {
|
||||
free(req.data);
|
||||
req.data = NULL;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,158 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF51822_GATT_SERVER_H__
|
||||
#define __NRF51822_GATT_SERVER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ble/blecommon.h"
|
||||
#include "headers/ble.h" /* nordic ble */
|
||||
#include "ble/Gap.h"
|
||||
#include "ble/GattServer.h"
|
||||
|
||||
class nRF5xGattServer : public GattServer
|
||||
{
|
||||
public:
|
||||
/* Functions that must be implemented from GattServer */
|
||||
virtual ble_error_t addService(GattService &);
|
||||
virtual ble_error_t read(GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP);
|
||||
virtual ble_error_t read(Gap::Handle_t connectionHandle, GattAttribute::Handle_t attributeHandle, uint8_t buffer[], uint16_t *lengthP);
|
||||
virtual ble_error_t write(GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false);
|
||||
virtual ble_error_t write(Gap::Handle_t connectionHandle, GattAttribute::Handle_t, const uint8_t[], uint16_t, bool localOnly = false);
|
||||
virtual ble_error_t areUpdatesEnabled(const GattCharacteristic &characteristic, bool *enabledP);
|
||||
virtual ble_error_t areUpdatesEnabled(Gap::Handle_t connectionHandle, const GattCharacteristic &characteristic, bool *enabledP);
|
||||
virtual ble_error_t reset(void);
|
||||
|
||||
/* nRF51 Functions */
|
||||
void eventCallback(void);
|
||||
void hwCallback(ble_evt_t *p_ble_evt);
|
||||
|
||||
|
||||
private:
|
||||
const static unsigned BLE_TOTAL_CHARACTERISTICS = 20;
|
||||
const static unsigned BLE_TOTAL_DESCRIPTORS = 8;
|
||||
const static unsigned TOTAL_CONCURRENT_LONG_WRITE_REQUESTS = 3;
|
||||
|
||||
private:
|
||||
struct long_write_request_t {
|
||||
// the connection handle for a long write request
|
||||
uint16_t conn_handle;
|
||||
|
||||
// the attribute handle for the long write request
|
||||
// This implementation folow the bluetooth route
|
||||
// where a write request target a single characteristic
|
||||
// (see BLUETOOTH SPECIFICATION Version 4.2 [Vol 3, Part G] - 4.9.4)
|
||||
uint16_t attr_handle;
|
||||
|
||||
// offset of the transaction
|
||||
uint16_t offset;
|
||||
|
||||
// length of the data
|
||||
uint16_t length;
|
||||
|
||||
// current data
|
||||
uint8_t* data;
|
||||
};
|
||||
|
||||
|
||||
private:
|
||||
/**
|
||||
* resolve a value attribute to its owning characteristic.
|
||||
* @param valueHandle the value handle to be resolved.
|
||||
* @return characteristic index if a resolution is found, else -1.
|
||||
*/
|
||||
int resolveValueHandleToCharIndex(GattAttribute::Handle_t valueHandle) const {
|
||||
unsigned charIndex;
|
||||
for (charIndex = 0; charIndex < characteristicCount; charIndex++) {
|
||||
if (nrfCharacteristicHandles[charIndex].value_handle == valueHandle) {
|
||||
return charIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* resolve a CCCD attribute handle to its owning characteristic.
|
||||
* @param cccdHandle the CCCD handle to be resolved.
|
||||
* @return characteristic index if a resolution is found, else -1.
|
||||
*/
|
||||
int resolveCCCDHandleToCharIndex(GattAttribute::Handle_t cccdHandle) const {
|
||||
unsigned charIndex;
|
||||
for (charIndex = 0; charIndex < characteristicCount; charIndex++) {
|
||||
if (nrfCharacteristicHandles[charIndex].cccd_handle == cccdHandle) {
|
||||
return charIndex;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the biggest size used by a characteristic in the server
|
||||
*/
|
||||
uint16_t getBiggestCharacteristicSize() const;
|
||||
|
||||
/**
|
||||
* Allocate a new write long request. return null if no requests are available.
|
||||
* @param connection_handle The connection handle to be associated with the request.
|
||||
* @return the allocated request or NULL if no requests are available.
|
||||
*/
|
||||
long_write_request_t* allocateLongWriteRequest(uint16_t connection_handle);
|
||||
|
||||
/**
|
||||
* Release a long write request and free a slot for subsequent write long requests.
|
||||
* @param connection_handle The connection handle associated with the request
|
||||
* @return true if the request where allocated and was release, false otherwise.
|
||||
*/
|
||||
bool releaseLongWriteRequest(uint16_t connection_handle);
|
||||
|
||||
/**
|
||||
* Find a long write request from a characteristic handle
|
||||
* @param connection_handle The connection handle associated with the request.
|
||||
* @return a pointer to the request if found otherwise NULL.
|
||||
*/
|
||||
long_write_request_t* findLongWriteRequest(uint16_t connection_handle);
|
||||
|
||||
/**
|
||||
* Release all pending write requests.
|
||||
*/
|
||||
void releaseAllWriteRequests();
|
||||
|
||||
private:
|
||||
GattCharacteristic *p_characteristics[BLE_TOTAL_CHARACTERISTICS];
|
||||
ble_gatts_char_handles_t nrfCharacteristicHandles[BLE_TOTAL_CHARACTERISTICS];
|
||||
GattAttribute *p_descriptors[BLE_TOTAL_DESCRIPTORS];
|
||||
uint8_t descriptorCount;
|
||||
uint16_t nrfDescriptorHandles[BLE_TOTAL_DESCRIPTORS];
|
||||
long_write_request_t long_write_requests[TOTAL_CONCURRENT_LONG_WRITE_REQUESTS];
|
||||
|
||||
/*
|
||||
* Allow instantiation from nRF5xn when required.
|
||||
*/
|
||||
friend class nRF5xn;
|
||||
|
||||
nRF5xGattServer() : GattServer(), p_characteristics(), nrfCharacteristicHandles(), p_descriptors(), descriptorCount(0), nrfDescriptorHandles(), long_write_requests() {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
private:
|
||||
nRF5xGattServer(const nRF5xGattServer &);
|
||||
const nRF5xGattServer& operator=(const nRF5xGattServer &);
|
||||
};
|
||||
|
||||
#endif // ifndef __NRF51822_GATT_SERVER_H__
|
|
@ -0,0 +1,177 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF51822_SECURITY_MANAGER_H__
|
||||
#define __NRF51822_SECURITY_MANAGER_H__
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
#include "nRF5xGap.h"
|
||||
#include "ble/SecurityManager.h"
|
||||
#include "btle_security.h"
|
||||
|
||||
class nRF5xSecurityManager : public SecurityManager
|
||||
{
|
||||
public:
|
||||
/* Functions that must be implemented from SecurityManager */
|
||||
virtual ble_error_t init(bool enableBonding,
|
||||
bool requireMITM,
|
||||
SecurityIOCapabilities_t iocaps,
|
||||
const Passkey_t passkey) {
|
||||
return btle_initializeSecurity(enableBonding, requireMITM, iocaps, passkey);
|
||||
}
|
||||
|
||||
virtual ble_error_t getLinkSecurity(Gap::Handle_t connectionHandle, LinkSecurityStatus_t *securityStatusP) {
|
||||
return btle_getLinkSecurity(connectionHandle, securityStatusP);
|
||||
}
|
||||
|
||||
virtual ble_error_t setLinkSecurity(Gap::Handle_t connectionHandle, SecurityMode_t securityMode) {
|
||||
return btle_setLinkSecurity(connectionHandle, securityMode);
|
||||
}
|
||||
|
||||
virtual ble_error_t purgeAllBondingState(void) {
|
||||
return btle_purgeAllBondingState();
|
||||
}
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
/**
|
||||
* @brief Returns a list of addresses from peers in the stacks bond table.
|
||||
*
|
||||
* @param[in/out] addresses
|
||||
* (on input) @ref Gap::Whitelist_t structure where at
|
||||
* most addresses.capacity addresses from bonded peers will
|
||||
* be stored.
|
||||
* (on output) A copy of the addresses from bonded peers.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if successful.
|
||||
*
|
||||
* @todo check whether remove this function (because it is never called)
|
||||
*/
|
||||
virtual ble_error_t getAddressesFromBondTable(Gap::Whitelist_t &addresses) const {
|
||||
uint8_t i;
|
||||
|
||||
ble_gap_whitelist_t whitelistFromBondTable;
|
||||
ble_gap_addr_t *addressPtr[YOTTA_CFG_WHITELIST_MAX_SIZE];
|
||||
ble_gap_irk_t *irkPtr[YOTTA_CFG_IRK_TABLE_MAX_SIZE];
|
||||
|
||||
/* Initialize the structure so that we get as many addreses as the whitelist can hold */
|
||||
whitelistFromBondTable.addr_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE;
|
||||
whitelistFromBondTable.pp_addrs = addressPtr;
|
||||
whitelistFromBondTable.irk_count = YOTTA_CFG_IRK_TABLE_MAX_SIZE;
|
||||
whitelistFromBondTable.pp_irks = irkPtr;
|
||||
|
||||
ble_error_t error = createWhitelistFromBondTable(whitelistFromBondTable);
|
||||
if (error != BLE_ERROR_NONE) {
|
||||
addresses.size = 0;
|
||||
return error;
|
||||
}
|
||||
|
||||
/* Put all the addresses in the structure */
|
||||
for (i = 0; i < whitelistFromBondTable.addr_count; ++i) {
|
||||
if (i >= addresses.capacity) {
|
||||
/* Ran out of space in the output Gap::Whitelist_t */
|
||||
addresses.size = i;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
memcpy(&addresses.addresses[i], whitelistFromBondTable.pp_addrs[i], sizeof(BLEProtocol::Address_t));
|
||||
}
|
||||
|
||||
/* Update the current address count */
|
||||
addresses.size = i;
|
||||
|
||||
/* The assumption here is that the underlying implementation of
|
||||
* createWhitelistFromBondTable() will not return the private resolvable
|
||||
* addresses (which is the case in the SoftDevice). Rather it returns the
|
||||
* IRKs, so we need to generate the private resolvable address by ourselves.
|
||||
*/
|
||||
for (i = 0; i < whitelistFromBondTable.irk_count; ++i) {
|
||||
if (i + addresses.size >= addresses.capacity) {
|
||||
/* Ran out of space in the output Gap::Whitelist_t */
|
||||
addresses.size += i;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
btle_generateResolvableAddress(
|
||||
*whitelistFromBondTable.pp_irks[i],
|
||||
(ble_gap_addr_t &) addresses.addresses[i + addresses.size]
|
||||
);
|
||||
}
|
||||
|
||||
/* Update the current address count */
|
||||
addresses.size += i;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
#endif
|
||||
/**
|
||||
* @brief Clear nRF5xSecurityManager's state.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if successful.
|
||||
*/
|
||||
virtual ble_error_t reset(void)
|
||||
{
|
||||
if (SecurityManager::reset() != BLE_ERROR_NONE) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
bool hasInitialized(void) const {
|
||||
return btle_hasInitializedSecurity();
|
||||
}
|
||||
|
||||
public:
|
||||
/*
|
||||
* Allow instantiation from nRF5xn when required.
|
||||
*/
|
||||
friend class nRF5xn;
|
||||
|
||||
nRF5xSecurityManager() {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
private:
|
||||
nRF5xSecurityManager(const nRF5xSecurityManager &);
|
||||
const nRF5xSecurityManager& operator=(const nRF5xSecurityManager &);
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
/*
|
||||
* Expose an interface that allows us to query the SoftDevice bond table
|
||||
* and extract a whitelist.
|
||||
*/
|
||||
ble_error_t createWhitelistFromBondTable(ble_gap_whitelist_t &whitelistFromBondTable) const {
|
||||
return btle_createWhitelistFromBondTable(&whitelistFromBondTable);
|
||||
}
|
||||
#endif
|
||||
/*
|
||||
* Given a BLE address and a IRK this function check whether the address
|
||||
* can be generated from the IRK. To do so, this function uses the hash
|
||||
* function and algorithm described in the Bluetooth low Energy
|
||||
* Specification. Internally, Nordic SDK functions are used.
|
||||
*/
|
||||
bool matchAddressAndIrk(ble_gap_addr_t *address, ble_gap_irk_t *irk) const {
|
||||
return btle_matchAddressAndIrk(address, irk);
|
||||
}
|
||||
|
||||
/*
|
||||
* Give nRF5xGap access to createWhitelistFromBondTable() and
|
||||
* matchAddressAndIrk()
|
||||
*/
|
||||
friend class nRF5xGap;
|
||||
};
|
||||
|
||||
#endif // ifndef __NRF51822_SECURITY_MANAGER_H__
|
|
@ -0,0 +1,331 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "nRF5xServiceDiscovery.h"
|
||||
|
||||
ble_error_t
|
||||
nRF5xServiceDiscovery::launchCharacteristicDiscovery(Gap::Handle_t connectionHandle,
|
||||
Gap::Handle_t startHandle,
|
||||
Gap::Handle_t endHandle)
|
||||
{
|
||||
characteristicDiscoveryStarted(connectionHandle);
|
||||
|
||||
ble_gattc_handle_range_t handleRange = {
|
||||
.start_handle = startHandle,
|
||||
.end_handle = endHandle
|
||||
};
|
||||
uint32_t rc = sd_ble_gattc_characteristics_discover(connectionHandle, &handleRange);
|
||||
ble_error_t err = BLE_ERROR_NONE;
|
||||
|
||||
switch (rc) {
|
||||
case NRF_SUCCESS:
|
||||
err = BLE_ERROR_NONE;
|
||||
break;
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
case NRF_ERROR_INVALID_ADDR:
|
||||
err = BLE_ERROR_INVALID_PARAM;
|
||||
break;
|
||||
case NRF_ERROR_BUSY:
|
||||
err = BLE_STACK_BUSY;
|
||||
break;
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
err = BLE_ERROR_INVALID_STATE;
|
||||
break;
|
||||
default:
|
||||
err = BLE_ERROR_UNSPECIFIED;
|
||||
break;
|
||||
}
|
||||
|
||||
if (err) {
|
||||
terminateCharacteristicDiscovery(err);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xServiceDiscovery::setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response)
|
||||
{
|
||||
serviceIndex = 0;
|
||||
numServices = response->count;
|
||||
|
||||
/* Account for the limitation on the number of discovered services we can handle at a time. */
|
||||
if (numServices > BLE_DB_DISCOVERY_MAX_SRV) {
|
||||
numServices = BLE_DB_DISCOVERY_MAX_SRV;
|
||||
}
|
||||
|
||||
serviceUUIDDiscoveryQueue.reset();
|
||||
for (unsigned i = 0; i < numServices; ++i) {
|
||||
if (response->services[i].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
|
||||
serviceUUIDDiscoveryQueue.enqueue(i);
|
||||
services[i].setup(response->services[i].handle_range.start_handle,
|
||||
response->services[i].handle_range.end_handle);
|
||||
} else {
|
||||
services[i].setup(response->services[i].uuid.uuid,
|
||||
response->services[i].handle_range.start_handle,
|
||||
response->services[i].handle_range.end_handle);
|
||||
}
|
||||
}
|
||||
|
||||
/* Trigger discovery of service UUID if necessary. */
|
||||
if (serviceUUIDDiscoveryQueue.getCount()) {
|
||||
serviceUUIDDiscoveryQueue.triggerFirst();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xServiceDiscovery::setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response)
|
||||
{
|
||||
numCharacteristics = response->count;
|
||||
|
||||
/* Account for the limitation on the number of discovered characteristics we can handle at a time. */
|
||||
if (numCharacteristics > BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV) {
|
||||
numCharacteristics = BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV;
|
||||
}
|
||||
|
||||
charUUIDDiscoveryQueue.reset();
|
||||
for (unsigned charIndex = 0; charIndex < numCharacteristics; charIndex++) {
|
||||
if (response->chars[charIndex].uuid.type == BLE_UUID_TYPE_UNKNOWN) {
|
||||
charUUIDDiscoveryQueue.enqueue(charIndex);
|
||||
characteristics[charIndex].setup(gattc,
|
||||
connHandle,
|
||||
response->chars[charIndex].char_props,
|
||||
response->chars[charIndex].handle_decl,
|
||||
response->chars[charIndex].handle_value);
|
||||
} else {
|
||||
characteristics[charIndex].setup(gattc,
|
||||
connHandle,
|
||||
response->chars[charIndex].uuid.uuid,
|
||||
response->chars[charIndex].char_props,
|
||||
response->chars[charIndex].handle_decl,
|
||||
response->chars[charIndex].handle_value);
|
||||
}
|
||||
}
|
||||
|
||||
/* Trigger discovery of char UUID if necessary. */
|
||||
if (charUUIDDiscoveryQueue.getCount()) {
|
||||
charUUIDDiscoveryQueue.triggerFirst();
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xServiceDiscovery::progressCharacteristicDiscovery(void)
|
||||
{
|
||||
if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if ((discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) && (numCharacteristics > 0)) {
|
||||
discoveredCharacteristic.setLastHandle(characteristics[0].getDeclHandle() - 1);
|
||||
|
||||
if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
||||
((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) &&
|
||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
||||
if (characteristicCallback) {
|
||||
characteristicCallback(&discoveredCharacteristic);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (uint8_t i = 0; i < numCharacteristics; ++i) {
|
||||
if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (i == (numCharacteristics - 1)) {
|
||||
discoveredCharacteristic = characteristics[i];
|
||||
break;
|
||||
} else {
|
||||
characteristics[i].setLastHandle(characteristics[i + 1].getDeclHandle() - 1);
|
||||
}
|
||||
|
||||
if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
||||
((matchingCharacteristicUUID == characteristics[i].getUUID()) &&
|
||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
||||
if (characteristicCallback) {
|
||||
characteristicCallback(&characteristics[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (state != CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
||||
return;
|
||||
}
|
||||
|
||||
Gap::Handle_t startHandle = (numCharacteristics > 0) ? characteristics[numCharacteristics - 1].getValueHandle() + 1 : SRV_DISC_END_HANDLE;
|
||||
Gap::Handle_t endHandle = services[serviceIndex].getEndHandle();
|
||||
resetDiscoveredCharacteristics(); /* Note: resetDiscoveredCharacteristics() must come after fetching start and end Handles. */
|
||||
|
||||
if (startHandle < endHandle) {
|
||||
ble_gattc_handle_range_t handleRange = {
|
||||
.start_handle = startHandle,
|
||||
.end_handle = endHandle
|
||||
};
|
||||
if (sd_ble_gattc_characteristics_discover(connHandle, &handleRange) != NRF_SUCCESS) {
|
||||
terminateCharacteristicDiscovery(BLE_ERROR_UNSPECIFIED);
|
||||
}
|
||||
} else {
|
||||
terminateCharacteristicDiscovery(BLE_ERROR_NONE);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xServiceDiscovery::progressServiceDiscovery(void)
|
||||
{
|
||||
/* Iterate through the previously discovered services cached in services[]. */
|
||||
while ((state == SERVICE_DISCOVERY_ACTIVE) && (serviceIndex < numServices)) {
|
||||
if ((matchingServiceUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
||||
(matchingServiceUUID == services[serviceIndex].getUUID())) {
|
||||
|
||||
if (serviceCallback && (matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN))) {
|
||||
serviceCallback(&services[serviceIndex]);
|
||||
}
|
||||
|
||||
if ((state == SERVICE_DISCOVERY_ACTIVE) && characteristicCallback) {
|
||||
launchCharacteristicDiscovery(connHandle, services[serviceIndex].getStartHandle(), services[serviceIndex].getEndHandle());
|
||||
} else {
|
||||
serviceIndex++;
|
||||
}
|
||||
} else {
|
||||
serviceIndex++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Relaunch discovery of new services beyond the last entry cached in services[]. */
|
||||
if ((state == SERVICE_DISCOVERY_ACTIVE) && (numServices > 0) && (serviceIndex > 0)) {
|
||||
/* Determine the ending handle of the last cached service. */
|
||||
Gap::Handle_t endHandle = services[serviceIndex - 1].getEndHandle();
|
||||
resetDiscoveredServices(); /* Note: resetDiscoveredServices() must come after fetching endHandle. */
|
||||
|
||||
if (endHandle == SRV_DISC_END_HANDLE) {
|
||||
terminateServiceDiscovery();
|
||||
} else {
|
||||
// the next service is located after the last handle discovered
|
||||
// Launch a new discovery from [endHandle + 1 : 0xFFFF]
|
||||
if (sd_ble_gattc_primary_services_discover(connHandle, endHandle + 1, NULL) != NRF_SUCCESS) {
|
||||
terminateServiceDiscovery();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xServiceDiscovery::ServiceUUIDDiscoveryQueue::triggerFirst(void)
|
||||
{
|
||||
while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
|
||||
parentDiscoveryObject->state = DISCOVER_SERVICE_UUIDS;
|
||||
|
||||
unsigned serviceIndex = getFirst();
|
||||
ble_uuid_t uuid = {
|
||||
.uuid = BLE_UUID_SERVICE_PRIMARY,
|
||||
.type = BLE_UUID_TYPE_BLE,
|
||||
};
|
||||
ble_gattc_handle_range_t handleRange = {
|
||||
.start_handle = parentDiscoveryObject->services[serviceIndex].getStartHandle(),
|
||||
.end_handle = parentDiscoveryObject->services[serviceIndex].getEndHandle(),
|
||||
};
|
||||
|
||||
if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip this service if we fail to launch a read for its service-declaration
|
||||
* attribute. Its UUID will remain INVALID, and it may not match any filters. */
|
||||
dequeue();
|
||||
}
|
||||
|
||||
/* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
|
||||
if (parentDiscoveryObject->state == DISCOVER_SERVICE_UUIDS) {
|
||||
parentDiscoveryObject->state = SERVICE_DISCOVERY_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xServiceDiscovery::CharUUIDDiscoveryQueue::triggerFirst(void)
|
||||
{
|
||||
while (numIndices) { /* loop until a call to char_value_by_uuid_read() succeeds or we run out of pending indices. */
|
||||
parentDiscoveryObject->state = DISCOVER_CHARACTERISTIC_UUIDS;
|
||||
|
||||
unsigned charIndex = getFirst();
|
||||
ble_uuid_t uuid = {
|
||||
.uuid = BLE_UUID_CHARACTERISTIC,
|
||||
.type = BLE_UUID_TYPE_BLE,
|
||||
};
|
||||
ble_gattc_handle_range_t handleRange = { };
|
||||
handleRange.start_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle();
|
||||
handleRange.end_handle = parentDiscoveryObject->characteristics[charIndex].getDeclHandle() + 1;
|
||||
if (sd_ble_gattc_char_value_by_uuid_read(parentDiscoveryObject->connHandle, &uuid, &handleRange) == NRF_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Skip this service if we fail to launch a read for its service-declaration
|
||||
* attribute. Its UUID will remain INVALID, and it may not match any filters. */
|
||||
dequeue();
|
||||
}
|
||||
|
||||
/* Switch back to service discovery upon exhausting the service-indices pending UUID discovery. */
|
||||
if (parentDiscoveryObject->state == DISCOVER_CHARACTERISTIC_UUIDS) {
|
||||
parentDiscoveryObject->state = CHARACTERISTIC_DISCOVERY_ACTIVE;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xServiceDiscovery::processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gattc_evt)
|
||||
{
|
||||
const ble_gattc_evt_char_val_by_uuid_read_rsp_t * response = &p_gattc_evt->params.char_val_by_uuid_read_rsp;
|
||||
|
||||
if (state == DISCOVER_SERVICE_UUIDS) {
|
||||
if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID)) {
|
||||
UUID::LongUUIDBytes_t uuid;
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
||||
/* SoftDevice API since 3.0.0 (e.g. sd 140 5.0.0-1.alpha) provide sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter() helper function,
|
||||
* but it's not reliable for c++ build.
|
||||
* Instead of it memcpy gets proper response's value field by offset from handle-value pair: [2 B handle|16 B value=uuid_128b] */
|
||||
|
||||
memcpy(uuid, (&response->handle_value + 2), UUID::LENGTH_OF_LONG_UUID);
|
||||
#else
|
||||
memcpy(uuid, &(response->handle_value[0].p_value[0]), UUID::LENGTH_OF_LONG_UUID);
|
||||
#endif
|
||||
|
||||
unsigned serviceIndex = serviceUUIDDiscoveryQueue.dequeue();
|
||||
services[serviceIndex].setupLongUUID(uuid, UUID::LSB);
|
||||
|
||||
serviceUUIDDiscoveryQueue.triggerFirst();
|
||||
} else {
|
||||
serviceUUIDDiscoveryQueue.dequeue();
|
||||
}
|
||||
} else if (state == DISCOVER_CHARACTERISTIC_UUIDS) {
|
||||
if ((response->count == 1) && (response->value_len == UUID::LENGTH_OF_LONG_UUID + 1 /* props */ + 2 /* value handle */)) {
|
||||
UUID::LongUUIDBytes_t uuid;
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
||||
/* SoftDevice API since 3.0.0 (e.g. sd 140 5.0.0-1.alpha) provide sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter() helper function,
|
||||
* but it's not reliable for c++ build.
|
||||
* Instead of it memcpy gets proper response's value by offset: [2 B type| 1B prop |2 B value handle| 16 B value=uuid_128b] */
|
||||
memcpy(uuid, (&response->handle_value + 5), UUID::LENGTH_OF_LONG_UUID);
|
||||
#else
|
||||
memcpy(uuid, &(response->handle_value[0].p_value[3]), UUID::LENGTH_OF_LONG_UUID);
|
||||
#endif
|
||||
|
||||
unsigned charIndex = charUUIDDiscoveryQueue.dequeue();
|
||||
characteristics[charIndex].setupLongUUID(uuid, UUID::LSB);
|
||||
|
||||
charUUIDDiscoveryQueue.triggerFirst();
|
||||
} else {
|
||||
charUUIDDiscoveryQueue.dequeue();
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,366 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF_SERVICE_DISCOVERY_H__
|
||||
#define __NRF_SERVICE_DISCOVERY_H__
|
||||
|
||||
#include "ble/ServiceDiscovery.h"
|
||||
#include "ble/DiscoveredService.h"
|
||||
#include "nRF5xDiscoveredCharacteristic.h"
|
||||
|
||||
#include "headers/ble.h"
|
||||
#include "ble_gattc.h"
|
||||
|
||||
class nRF5xGattClient; /* forward declaration */
|
||||
|
||||
class nRF5xServiceDiscovery : public ServiceDiscovery
|
||||
{
|
||||
public:
|
||||
static const uint16_t SRV_DISC_START_HANDLE = 0x0001; /**< The start handle value used during service discovery. */
|
||||
static const uint16_t SRV_DISC_END_HANDLE = 0xFFFF; /**< The end handle value used during service discovery. */
|
||||
|
||||
public:
|
||||
static const unsigned BLE_DB_DISCOVERY_MAX_SRV = 4; /**< Maximum number of services we can retain information for after a single discovery. */
|
||||
static const unsigned BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV = 4; /**< Maximum number of characteristics per service we can retain information for. */
|
||||
|
||||
public:
|
||||
nRF5xServiceDiscovery(nRF5xGattClient *gattcIn) :
|
||||
gattc(gattcIn),
|
||||
serviceIndex(0),
|
||||
numServices(0),
|
||||
numCharacteristics(0),
|
||||
state(INACTIVE),
|
||||
services(),
|
||||
characteristics(),
|
||||
serviceUUIDDiscoveryQueue(this),
|
||||
charUUIDDiscoveryQueue(this),
|
||||
onTerminationCallback(NULL) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
virtual ble_error_t launch(Gap::Handle_t connectionHandle,
|
||||
ServiceDiscovery::ServiceCallback_t sc,
|
||||
ServiceDiscovery::CharacteristicCallback_t cc,
|
||||
const UUID &matchingServiceUUIDIn,
|
||||
const UUID &matchingCharacteristicUUIDIn)
|
||||
{
|
||||
if (isActive()) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
serviceCallback = sc;
|
||||
characteristicCallback = cc;
|
||||
matchingServiceUUID = matchingServiceUUIDIn;
|
||||
matchingCharacteristicUUID = matchingCharacteristicUUIDIn;
|
||||
|
||||
serviceDiscoveryStarted(connectionHandle);
|
||||
|
||||
uint32_t rc;
|
||||
if ((rc = sd_ble_gattc_primary_services_discover(connectionHandle, SRV_DISC_START_HANDLE, NULL)) != NRF_SUCCESS) {
|
||||
terminate();
|
||||
switch (rc) {
|
||||
case NRF_ERROR_INVALID_PARAM:
|
||||
case BLE_ERROR_INVALID_CONN_HANDLE:
|
||||
return BLE_ERROR_INVALID_PARAM;
|
||||
case NRF_ERROR_BUSY:
|
||||
return BLE_STACK_BUSY;
|
||||
default:
|
||||
case NRF_ERROR_INVALID_STATE:
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
}
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
virtual bool isActive(void) const {
|
||||
return state != INACTIVE;
|
||||
}
|
||||
|
||||
virtual void terminate(void) {
|
||||
terminateServiceDiscovery();
|
||||
}
|
||||
|
||||
void terminate(Gap::Handle_t connectionHandle) {
|
||||
if(connHandle == connectionHandle) {
|
||||
terminate();
|
||||
}
|
||||
}
|
||||
|
||||
virtual void onTermination(ServiceDiscovery::TerminationCallback_t callback) {
|
||||
onTerminationCallback = callback;
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Clear nRF5xServiceDiscovery's state.
|
||||
*
|
||||
* @return
|
||||
* BLE_ERROR_NONE if successful.
|
||||
*/
|
||||
virtual ble_error_t reset(void) {
|
||||
/* Clear all state that is from the parent, including private members */
|
||||
if (ServiceDiscovery::reset() != BLE_ERROR_NONE) {
|
||||
return BLE_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
/* Clear derived class members */
|
||||
serviceIndex = 0;
|
||||
numServices = 0;
|
||||
numCharacteristics = 0;
|
||||
|
||||
state = INACTIVE;
|
||||
|
||||
serviceUUIDDiscoveryQueue.reset();
|
||||
charUUIDDiscoveryQueue.reset();
|
||||
|
||||
onTerminationCallback = NULL;
|
||||
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
private:
|
||||
ble_error_t launchCharacteristicDiscovery(Gap::Handle_t connectionHandle, Gap::Handle_t startHandle, Gap::Handle_t endHandle);
|
||||
|
||||
private:
|
||||
void setupDiscoveredServices(const ble_gattc_evt_prim_srvc_disc_rsp_t *response);
|
||||
void setupDiscoveredCharacteristics(const ble_gattc_evt_char_disc_rsp_t *response);
|
||||
|
||||
void triggerServiceUUIDDiscovery(void);
|
||||
void processDiscoverUUIDResponse(const ble_gattc_evt_t *p_gattc_evt);
|
||||
void removeFirstServiceNeedingUUIDDiscovery(void);
|
||||
|
||||
void terminateServiceDiscovery(void) {
|
||||
discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
|
||||
|
||||
bool wasActive = isActive();
|
||||
state = INACTIVE;
|
||||
|
||||
if (wasActive && onTerminationCallback) {
|
||||
onTerminationCallback(connHandle);
|
||||
}
|
||||
}
|
||||
|
||||
void terminateCharacteristicDiscovery(ble_error_t err) {
|
||||
if (state == CHARACTERISTIC_DISCOVERY_ACTIVE) {
|
||||
if(discoveredCharacteristic != nRF5xDiscoveredCharacteristic()) {
|
||||
if(err == BLE_ERROR_NONE) {
|
||||
// fullfill the last characteristic
|
||||
discoveredCharacteristic.setLastHandle(services[serviceIndex].getEndHandle());
|
||||
|
||||
if ((matchingCharacteristicUUID == UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)) ||
|
||||
((matchingCharacteristicUUID == discoveredCharacteristic.getUUID()) &&
|
||||
(matchingServiceUUID != UUID::ShortUUIDBytes_t(BLE_UUID_UNKNOWN)))) {
|
||||
if (characteristicCallback) {
|
||||
characteristicCallback(&discoveredCharacteristic);
|
||||
}
|
||||
}
|
||||
}
|
||||
discoveredCharacteristic = nRF5xDiscoveredCharacteristic();
|
||||
}
|
||||
|
||||
state = SERVICE_DISCOVERY_ACTIVE;
|
||||
}
|
||||
serviceIndex++; /* Progress service index to keep discovery alive. */
|
||||
}
|
||||
|
||||
private:
|
||||
void resetDiscoveredServices(void) {
|
||||
numServices = 0;
|
||||
serviceIndex = 0;
|
||||
}
|
||||
|
||||
void resetDiscoveredCharacteristics(void) {
|
||||
numCharacteristics = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
void serviceDiscoveryStarted(Gap::Handle_t connectionHandle) {
|
||||
connHandle = connectionHandle;
|
||||
resetDiscoveredServices();
|
||||
state = SERVICE_DISCOVERY_ACTIVE;
|
||||
}
|
||||
|
||||
private:
|
||||
void characteristicDiscoveryStarted(Gap::Handle_t connectionHandle) {
|
||||
connHandle = connectionHandle;
|
||||
resetDiscoveredCharacteristics();
|
||||
state = CHARACTERISTIC_DISCOVERY_ACTIVE;
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* A datatype to contain service-indices for which long UUIDs need to be
|
||||
* discovered using read_val_by_uuid().
|
||||
*/
|
||||
class ServiceUUIDDiscoveryQueue {
|
||||
public:
|
||||
ServiceUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
|
||||
numIndices(0),
|
||||
serviceIndices(),
|
||||
parentDiscoveryObject(parent) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
public:
|
||||
void reset(void) {
|
||||
numIndices = 0;
|
||||
for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
|
||||
serviceIndices[i] = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
void enqueue(int serviceIndex) {
|
||||
serviceIndices[numIndices++] = serviceIndex;
|
||||
}
|
||||
int dequeue(void) {
|
||||
if (numIndices == 0) {
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
unsigned valueToReturn = serviceIndices[0];
|
||||
numIndices--;
|
||||
for (unsigned i = 0; i < numIndices; i++) {
|
||||
serviceIndices[i] = serviceIndices[i + 1];
|
||||
}
|
||||
|
||||
return valueToReturn;
|
||||
}
|
||||
unsigned getFirst(void) const {
|
||||
return serviceIndices[0];
|
||||
}
|
||||
size_t getCount(void) const {
|
||||
return numIndices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger UUID discovery for the first of the enqueued ServiceIndices.
|
||||
*/
|
||||
void triggerFirst(void);
|
||||
|
||||
private:
|
||||
static const int INVALID_INDEX = -1;
|
||||
|
||||
private:
|
||||
size_t numIndices;
|
||||
int serviceIndices[BLE_DB_DISCOVERY_MAX_SRV];
|
||||
|
||||
nRF5xServiceDiscovery *parentDiscoveryObject;
|
||||
};
|
||||
friend class ServiceUUIDDiscoveryQueue;
|
||||
|
||||
/**
|
||||
* A datatype to contain characteristic-indices for which long UUIDs need to
|
||||
* be discovered using read_val_by_uuid().
|
||||
*/
|
||||
class CharUUIDDiscoveryQueue {
|
||||
public:
|
||||
CharUUIDDiscoveryQueue(nRF5xServiceDiscovery *parent) :
|
||||
numIndices(0),
|
||||
charIndices(),
|
||||
parentDiscoveryObject(parent) {
|
||||
/* empty */
|
||||
}
|
||||
|
||||
public:
|
||||
void reset(void) {
|
||||
numIndices = 0;
|
||||
for (unsigned i = 0; i < BLE_DB_DISCOVERY_MAX_SRV; i++) {
|
||||
charIndices[i] = INVALID_INDEX;
|
||||
}
|
||||
}
|
||||
void enqueue(int serviceIndex) {
|
||||
charIndices[numIndices++] = serviceIndex;
|
||||
}
|
||||
int dequeue(void) {
|
||||
if (numIndices == 0) {
|
||||
return INVALID_INDEX;
|
||||
}
|
||||
|
||||
unsigned valueToReturn = charIndices[0];
|
||||
numIndices--;
|
||||
for (unsigned i = 0; i < numIndices; i++) {
|
||||
charIndices[i] = charIndices[i + 1];
|
||||
}
|
||||
|
||||
return valueToReturn;
|
||||
}
|
||||
unsigned getFirst(void) const {
|
||||
return charIndices[0];
|
||||
}
|
||||
size_t getCount(void) const {
|
||||
return numIndices;
|
||||
}
|
||||
|
||||
/**
|
||||
* Trigger UUID discovery for the first of the enqueued charIndices.
|
||||
*/
|
||||
void triggerFirst(void);
|
||||
|
||||
private:
|
||||
static const int INVALID_INDEX = -1;
|
||||
|
||||
private:
|
||||
size_t numIndices;
|
||||
int charIndices[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
|
||||
|
||||
nRF5xServiceDiscovery *parentDiscoveryObject;
|
||||
};
|
||||
friend class CharUUIDDiscoveryQueue;
|
||||
|
||||
private:
|
||||
friend void bleGattcEventHandler(const ble_evt_t *p_ble_evt);
|
||||
void progressCharacteristicDiscovery(void);
|
||||
void progressServiceDiscovery(void);
|
||||
|
||||
private:
|
||||
nRF5xGattClient *gattc;
|
||||
|
||||
private:
|
||||
uint8_t serviceIndex; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
|
||||
uint8_t numServices; /**< Number of services at the peers GATT database.*/
|
||||
uint8_t numCharacteristics; /**< Number of characteristics within the service.*/
|
||||
|
||||
enum State_t {
|
||||
INACTIVE,
|
||||
SERVICE_DISCOVERY_ACTIVE,
|
||||
CHARACTERISTIC_DISCOVERY_ACTIVE,
|
||||
DISCOVER_SERVICE_UUIDS,
|
||||
DISCOVER_CHARACTERISTIC_UUIDS,
|
||||
} state;
|
||||
|
||||
DiscoveredService services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered.
|
||||
* This is intended for internal use during service discovery. */
|
||||
nRF5xDiscoveredCharacteristic characteristics[BLE_DB_DISCOVERY_MAX_CHAR_PER_SRV];
|
||||
|
||||
ServiceUUIDDiscoveryQueue serviceUUIDDiscoveryQueue;
|
||||
CharUUIDDiscoveryQueue charUUIDDiscoveryQueue;
|
||||
|
||||
TerminationCallback_t onTerminationCallback;
|
||||
|
||||
/*
|
||||
* The currently discovered characteristic. Discovery of a characteristic
|
||||
* is a two phase process.
|
||||
* First, declaration handle is fetched, it provide the UUID, the value handle and
|
||||
* the properties of a characteristic.
|
||||
* Second, the next declaration handle is fetched, with its declaration handle, it is
|
||||
* possible to compute the last handle of the discovered characteristic and fill the
|
||||
* missing part of the object.
|
||||
* If there is no remaining characteristic to discover, the last handle of the
|
||||
* discovered characteristic will be set to the last handle of its enclosing service.
|
||||
*/
|
||||
nRF5xDiscoveredCharacteristic discoveredCharacteristic;
|
||||
};
|
||||
|
||||
#endif /*__NRF_SERVICE_DISCOVERY_H__*/
|
|
@ -0,0 +1,224 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifdef YOTTA_CFG_MBED_OS
|
||||
#include "mbed-drivers/mbed.h"
|
||||
#else
|
||||
#include "mbed.h"
|
||||
#endif
|
||||
#include "nRF5xn.h"
|
||||
#include "ble/blecommon.h"
|
||||
#include "nrf_soc.h"
|
||||
|
||||
#include "btle/btle.h"
|
||||
#include "btle/custom/custom_helper.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
extern "C" {
|
||||
#include "softdevice_handler.h"
|
||||
}
|
||||
|
||||
/**
|
||||
* The singleton which represents the nRF51822 transport for the BLE.
|
||||
*/
|
||||
static nRF5xn& getDeviceInstance() {
|
||||
static nRF5xn deviceInstance;
|
||||
return deviceInstance;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* BLE-API requires an implementation of the following function in order to
|
||||
* obtain its transport handle.
|
||||
*/
|
||||
BLEInstanceBase *
|
||||
createBLEInstance(void)
|
||||
{
|
||||
return &nRF5xn::Instance(BLE::DEFAULT_INSTANCE);
|
||||
}
|
||||
|
||||
nRF5xn& nRF5xn::Instance(BLE::InstanceID_t instanceId)
|
||||
{
|
||||
return getDeviceInstance();
|
||||
}
|
||||
|
||||
nRF5xn::nRF5xn(void) :
|
||||
initialized(false),
|
||||
instanceID(BLE::DEFAULT_INSTANCE),
|
||||
gapInstance(),
|
||||
gattServerInstance(NULL),
|
||||
gattClientInstance(NULL),
|
||||
securityManagerInstance(NULL)
|
||||
{
|
||||
}
|
||||
|
||||
nRF5xn::~nRF5xn(void)
|
||||
{
|
||||
}
|
||||
|
||||
const char *nRF5xn::getVersion(void)
|
||||
{
|
||||
if (!initialized) {
|
||||
return "INITIALIZATION_INCOMPLETE";
|
||||
}
|
||||
|
||||
static char versionString[32];
|
||||
static bool versionFetched = false;
|
||||
|
||||
if (!versionFetched) {
|
||||
ble_version_t version;
|
||||
if ((sd_ble_version_get(&version) == NRF_SUCCESS) && (version.company_id == 0x0059)) {
|
||||
switch (version.version_number) {
|
||||
case 0x07:
|
||||
case 0x08:
|
||||
snprintf(versionString, sizeof(versionString), "Nordic BLE4.1 ver:%u fw:%04x", version.version_number, version.subversion_number);
|
||||
break;
|
||||
default:
|
||||
snprintf(versionString, sizeof(versionString), "Nordic (spec unknown) ver:%u fw:%04x", version.version_number, version.subversion_number);
|
||||
break;
|
||||
}
|
||||
versionFetched = true;
|
||||
} else {
|
||||
strncpy(versionString, "unknown", sizeof(versionString));
|
||||
}
|
||||
}
|
||||
|
||||
return versionString;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Initialize the BLE stack.
|
||||
|
||||
@returns ble_error_t
|
||||
|
||||
@retval BLE_ERROR_NONE if everything executed properly and
|
||||
BLE_ERROR_ALREADY_INITIALIZED if the stack has already
|
||||
been initialized (possibly through a call to nRF5xn::init()).
|
||||
BLE_ERROR_INTERNAL_STACK_FAILURE is returned if initialization
|
||||
of the internal stack (SoftDevice) failed.
|
||||
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ble_error_t nRF5xn::init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback)
|
||||
{
|
||||
if (initialized) {
|
||||
BLE::InitializationCompleteCallbackContext context = {
|
||||
BLE::Instance(instanceID),
|
||||
BLE_ERROR_ALREADY_INITIALIZED
|
||||
};
|
||||
callback.call(&context);
|
||||
return BLE_ERROR_ALREADY_INITIALIZED;
|
||||
}
|
||||
|
||||
instanceID = instanceID;
|
||||
|
||||
/* ToDo: Clear memory contents, reset the SD, etc. */
|
||||
if (btle_init() != ERROR_NONE) {
|
||||
return BLE_ERROR_INTERNAL_STACK_FAILURE;
|
||||
}
|
||||
|
||||
initialized = true;
|
||||
BLE::InitializationCompleteCallbackContext context = {
|
||||
BLE::Instance(instanceID),
|
||||
BLE_ERROR_NONE
|
||||
};
|
||||
callback.call(&context);
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
/**************************************************************************/
|
||||
/*!
|
||||
@brief Purge the BLE stack of GATT and GAP state.
|
||||
|
||||
@returns ble_error_t
|
||||
|
||||
@retval BLE_ERROR_NONE
|
||||
Everything executed properly
|
||||
|
||||
@note When using S110, GattClient::shutdown() will not be called
|
||||
since Gatt client features are not supported.
|
||||
*/
|
||||
/**************************************************************************/
|
||||
ble_error_t nRF5xn::shutdown(void)
|
||||
{
|
||||
if (!initialized) {
|
||||
return BLE_ERROR_INITIALIZATION_INCOMPLETE;
|
||||
}
|
||||
|
||||
/*
|
||||
* Shutdown the SoftDevice first. This is because we need to disable all
|
||||
* interrupts. Otherwise if we clear the BLE API and glue code first there
|
||||
* will be many NULL references and no config information which could lead
|
||||
* to errors if the shutdown process is interrupted.
|
||||
*/
|
||||
if (softdevice_handler_sd_disable() != NRF_SUCCESS) {
|
||||
return BLE_STACK_BUSY;
|
||||
}
|
||||
|
||||
|
||||
/* Shutdown the BLE API and nRF51 glue code */
|
||||
ble_error_t error;
|
||||
|
||||
if (gattServerInstance != NULL) {
|
||||
error = gattServerInstance->reset();
|
||||
if (error != BLE_ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
if (securityManagerInstance != NULL) {
|
||||
error = securityManagerInstance->reset();
|
||||
if (error != BLE_ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
|
||||
/* S110 does not support BLE client features, nothing to reset. */
|
||||
#if !defined(TARGET_MCU_NRF51_16K_S110) && !defined(TARGET_MCU_NRF51_32K_S110)
|
||||
if (gattClientInstance != NULL) {
|
||||
error = gattClientInstance->reset();
|
||||
if (error != BLE_ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Gap instance is always present */
|
||||
error = gapInstance.reset();
|
||||
if (error != BLE_ERROR_NONE) {
|
||||
return error;
|
||||
}
|
||||
|
||||
custom_reset_128bits_uuid_table();
|
||||
|
||||
initialized = false;
|
||||
return BLE_ERROR_NONE;
|
||||
}
|
||||
|
||||
void
|
||||
nRF5xn::waitForEvent(void)
|
||||
{
|
||||
processEvents();
|
||||
sd_app_evt_wait();
|
||||
}
|
||||
|
||||
void nRF5xn::processEvents() {
|
||||
if (isEventsSignaled) {
|
||||
isEventsSignaled = false;
|
||||
intern_softdevice_events_execute();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,184 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef __NRF51822_H__
|
||||
#define __NRF51822_H__
|
||||
|
||||
#include "ble/BLE.h"
|
||||
#include "ble/blecommon.h"
|
||||
#include "ble/BLEInstanceBase.h"
|
||||
|
||||
#include "nRF5xGap.h"
|
||||
#include "nRF5xGattServer.h"
|
||||
#include "nRF5xGattClient.h"
|
||||
#include "nRF5xSecurityManager.h"
|
||||
|
||||
#include "btle.h"
|
||||
|
||||
class nRF5xn : public BLEInstanceBase
|
||||
{
|
||||
public:
|
||||
nRF5xn(void);
|
||||
virtual ~nRF5xn(void);
|
||||
|
||||
virtual ble_error_t init(BLE::InstanceID_t instanceID, FunctionPointerWithContext<BLE::InitializationCompleteCallbackContext *> callback);
|
||||
virtual bool hasInitialized(void) const {
|
||||
return initialized;
|
||||
}
|
||||
virtual ble_error_t shutdown(void);
|
||||
virtual const char *getVersion(void);
|
||||
|
||||
/**
|
||||
* Accessors to GAP. This function checks whether gapInstance points to an
|
||||
* object. If if does not, then the gapInstance is updated to
|
||||
* &_getInstance before returning.
|
||||
*
|
||||
* @return A reference to GattServer.
|
||||
*
|
||||
* @note Unlike the GattClient, GattServer and SecurityManager, Gap is
|
||||
* always needed in a BLE application. Therefore it is allocated
|
||||
* statically.
|
||||
*/
|
||||
virtual Gap &getGap() {
|
||||
return gapInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accessors to GATT Server. This function checks whether a GattServer
|
||||
* object was previously instantiated. If such object does not exist, then
|
||||
* it is created before returning.
|
||||
*
|
||||
* @return A reference to GattServer.
|
||||
*/
|
||||
virtual GattServer &getGattServer() {
|
||||
if (gattServerInstance == NULL) {
|
||||
gattServerInstance = new nRF5xGattServer();
|
||||
}
|
||||
return *gattServerInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accessors to GATT Client. This function checks whether a GattClient
|
||||
* object was previously instantiated. If such object does not exist, then
|
||||
* it is created before returning.
|
||||
*
|
||||
* @return A reference to GattClient.
|
||||
*/
|
||||
virtual nRF5xGattClient &getGattClient() {
|
||||
if (gattClientInstance == NULL) {
|
||||
gattClientInstance = new nRF5xGattClient();
|
||||
}
|
||||
return *gattClientInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessors to Security Manager. This function checks whether a SecurityManager
|
||||
* object was previously instantiated. If such object does not exist, then
|
||||
* it is created before returning.
|
||||
*
|
||||
* @return A reference to GattServer.
|
||||
*/
|
||||
virtual nRF5xSecurityManager &getSecurityManager() {
|
||||
if (securityManagerInstance == NULL) {
|
||||
securityManagerInstance = new nRF5xSecurityManager();
|
||||
}
|
||||
return *securityManagerInstance;
|
||||
}
|
||||
|
||||
/**
|
||||
* Accessors to GAP. This function checks whether gapInstance points to an
|
||||
* object. If if does not, then the gapInstance is updated to
|
||||
* &_getInstance before returning.
|
||||
*
|
||||
* @return A const reference to GattServer.
|
||||
*
|
||||
* @note Unlike the GattClient, GattServer and SecurityManager, Gap is
|
||||
* always needed in a BLE application. Therefore it is allocated
|
||||
* statically.
|
||||
*
|
||||
* @note The accessor is able to modify the object's state because the
|
||||
* internal pointer has been declared mutable.
|
||||
*/
|
||||
virtual const nRF5xGap &getGap() const {
|
||||
return gapInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accessors to GATT Server. This function checks whether a GattServer
|
||||
* object was previously instantiated. If such object does not exist, then
|
||||
* it is created before returning.
|
||||
*
|
||||
* @return A const reference to GattServer.
|
||||
*
|
||||
* @note The accessor is able to modify the object's state because the
|
||||
* internal pointer has been declared mutable.
|
||||
*/
|
||||
virtual const nRF5xGattServer &getGattServer() const {
|
||||
if (gattServerInstance == NULL) {
|
||||
gattServerInstance = new nRF5xGattServer();
|
||||
}
|
||||
return *gattServerInstance;
|
||||
};
|
||||
|
||||
/**
|
||||
* Accessors to Security Manager. This function checks whether a SecurityManager
|
||||
* object was previously instantiated. If such object does not exist, then
|
||||
* it is created before returning.
|
||||
*
|
||||
* @return A const reference to GattServer.
|
||||
*
|
||||
* @note The accessor is able to modify the object's state because the
|
||||
* internal pointer has been declared mutable.
|
||||
*/
|
||||
virtual const nRF5xSecurityManager &getSecurityManager() const {
|
||||
if (securityManagerInstance == NULL) {
|
||||
securityManagerInstance = new nRF5xSecurityManager();
|
||||
}
|
||||
return *securityManagerInstance;
|
||||
}
|
||||
|
||||
virtual void waitForEvent(void);
|
||||
|
||||
virtual void processEvents();
|
||||
|
||||
public:
|
||||
static nRF5xn& Instance(BLE::InstanceID_t instanceId);
|
||||
|
||||
private:
|
||||
bool initialized;
|
||||
BLE::InstanceID_t instanceID;
|
||||
|
||||
private:
|
||||
mutable nRF5xGap gapInstance; /**< Gap instance whose reference is returned from a call to
|
||||
* getGap(). Unlike the GattClient, GattServer and
|
||||
* SecurityManager, Gap is always needed in a BLE application. */
|
||||
|
||||
private:
|
||||
mutable nRF5xGattServer *gattServerInstance; /**< Pointer to the GattServer object instance.
|
||||
* If NULL, then GattServer has not been initialized.
|
||||
* The pointer has been declared as 'mutable' so that
|
||||
* it can be assigned inside a 'const' function. */
|
||||
mutable nRF5xGattClient *gattClientInstance; /**< Pointer to the GattClient object instance.
|
||||
* If NULL, then GattClient has not been initialized.
|
||||
* The pointer has been declared as 'mutable' so that
|
||||
* it can be assigned inside a 'const' function. */
|
||||
mutable nRF5xSecurityManager *securityManagerInstance; /**< Pointer to the SecurityManager object instance.
|
||||
* If NULL, then SecurityManager has not been initialized.
|
||||
* The pointer has been declared as 'mutable' so that
|
||||
* it can be assigned inside a 'const' function. */
|
||||
};
|
||||
|
||||
#endif
|
|
@ -0,0 +1,136 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef _PROJECTCONFIG_H_
|
||||
#define _PROJECTCONFIG_H_
|
||||
|
||||
#include "ble/GapAdvertisingData.h"
|
||||
|
||||
/*=========================================================================
|
||||
MCU & BOARD SELCTION
|
||||
|
||||
CFG_BOARD is one of the value defined in board.h
|
||||
-----------------------------------------------------------------------*/
|
||||
#define CFG_BOARD BOARD_PCA10001
|
||||
#define CFG_MCU_STRING "nRF51822"
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
CODE BASE VERSION SETTINGS
|
||||
|
||||
Please do not modify this version number. To set a version number
|
||||
for your project or firmware, change the values in your 'boards/'
|
||||
config file.
|
||||
-----------------------------------------------------------------------*/
|
||||
#define CFG_CODEBASE_VERSION_MAJOR 0
|
||||
#define CFG_CODEBASE_VERSION_MINOR 1
|
||||
#define CFG_CODEBASE_VERSION_REVISION 0
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
FIRMWARE VERSION SETTINGS
|
||||
-----------------------------------------------------------------------*/
|
||||
#define CFG_FIRMWARE_VERSION_MAJOR 0
|
||||
#define CFG_FIRMWARE_VERSION_MINOR 0
|
||||
#define CFG_FIRMWARE_VERSION_REVISION 0
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
DEBUG LEVEL
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CFG_DEBUG Level 3: Full debug output, any failed assert
|
||||
will produce a breakpoint for the
|
||||
debugger
|
||||
Level 2: ATTR_ALWAYS_INLINE is null, ASSERT
|
||||
has text
|
||||
Level 1: ATTR_ALWAYS_INLINE is an attribute,
|
||||
ASSERT has no text
|
||||
Level 0: No debug information generated
|
||||
|
||||
-----------------------------------------------------------------------*/
|
||||
#define CFG_DEBUG (1)
|
||||
|
||||
#if (CFG_DEBUG > 3) || (CFG_DEBUG < 0)
|
||||
#error "CFG_DEBUG must be a value between 0 (no debug) and 3"
|
||||
#endif
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
GENERAL NRF51 PERIPHERAL SETTINGS
|
||||
-----------------------------------------------------------------------
|
||||
|
||||
CFG_SCHEDULER_ENABLE Set this to 'true' or 'false' depending on
|
||||
if you use the event scheduler or not
|
||||
|
||||
-----------------------------------------------------------------------*/
|
||||
#define CFG_SCHEDULER_ENABLE false
|
||||
|
||||
/*------------------------------- GPIOTE ------------------------------*/
|
||||
#define CFG_GPIOTE_MAX_USERS 1 /**< Maximum number of users of the GPIOTE handler. */
|
||||
|
||||
/*-------------------------------- TIMER ------------------------------*/
|
||||
#define CFG_TIMER_PRESCALER 0 /**< Value of the RTC1 PRESCALER register. freq = (32768/(PRESCALER+1)) */
|
||||
#define CFG_TIMER_MAX_INSTANCE 1 /**< Maximum number of simultaneously created timers. */
|
||||
#define CFG_TIMER_OPERATION_QUEUE_SIZE 2 /**< Size of timer operation queues. */
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
BTLE SETTINGS
|
||||
-----------------------------------------------------------------------*/
|
||||
|
||||
#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.*/
|
||||
#define CFG_BLE_BOND_FLASH_PAGE_SYS_ATTR (BLE_FLASH_PAGE_END-3) /**< Flash page used for bond manager system attribute information. TODO check if we can use BLE_FLASH_PAGE_END-2*/
|
||||
#define CFG_BLE_BOND_DELETE_BUTTON_NUM 0 /**< Button to press to delete bond details during init */
|
||||
|
||||
/*------------------------------ SECURITY -----------------------------*/
|
||||
#define CFG_BLE_SEC_PARAM_MITM 0 /**< Man In The Middle protection not required. */
|
||||
#define CFG_BLE_SEC_PARAM_IO_CAPABILITIES BLE_GAP_IO_CAPS_NONE /**< No I/O capabilities. */
|
||||
#define CFG_BLE_SEC_PARAM_OOB 0 /**< Out Of Band data not available. */
|
||||
#define CFG_BLE_SEC_PARAM_MIN_KEY_SIZE 7 /**< Minimum encryption key size. */
|
||||
#define CFG_BLE_SEC_PARAM_MAX_KEY_SIZE 16
|
||||
|
||||
/*--------------------------------- GAP -------------------------------*/
|
||||
#define CFG_GAP_APPEARANCE GapAdvertisingData::GENERIC_TAG
|
||||
#define CFG_GAP_LOCAL_NAME "nRF5x"
|
||||
|
||||
#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. */
|
||||
|
||||
#define CFG_GAP_ADV_INTERVAL_MS 25 /**< The advertising interval in miliseconds, should be multiply of 0.625 */
|
||||
#define CFG_GAP_ADV_TIMEOUT_S 180 /**< The advertising timeout in units of seconds. */
|
||||
/*=========================================================================*/
|
||||
|
||||
|
||||
/*=========================================================================
|
||||
VALIDATION
|
||||
-----------------------------------------------------------------------*/
|
||||
#if CFG_BLE_TX_POWER_LEVEL != -40 && CFG_BLE_TX_POWER_LEVEL != -20 && CFG_BLE_TX_POWER_LEVEL != -16 && CFG_BLE_TX_POWER_LEVEL != -12 && CFG_BLE_TX_POWER_LEVEL != -8 && CFG_BLE_TX_POWER_LEVEL != -4 && CFG_BLE_TX_POWER_LEVEL != 0 && CFG_BLE_TX_POWER_LEVEL != 4
|
||||
#error "CFG_BLE_TX_POWER_LEVEL must be -40, -20, -16, -12, -8, -4, 0 or 4"
|
||||
#endif
|
||||
/*=========================================================================*/
|
||||
|
||||
#endif /* _PROJECTCONFIG_H_ */
|
|
@ -0,0 +1,97 @@
|
|||
|
||||
# LF Clock configuration using mbed configuration system
|
||||
|
||||
In order to provide the configuration for a low frequency (LF) clock, add a description of the LF clock inside a mbed configuration JSON file.
|
||||
For example at application level the description might be added in a mbed_app.json file and on target level the description might be added in the hal/target.json file.
|
||||
LF clock source configuration is used for MCU startup initialization and the BLE SoftDevice LF clock configuration (if BLE libraries is used). Advanced configurations are used only for the BLE SoftDevice LF clock configuration.
|
||||
|
||||
|
||||
## Usage:
|
||||
|
||||
1. Clock source
|
||||
|
||||
Default clock source is XTAL oscillator. It is defined at the target level configuration as the target.lf_clock_src key.
|
||||
There are three options that can be configured as the clock source:
|
||||
- NRF_LF_SRC_XTAL
|
||||
- NRF_LF_SRC_RC
|
||||
- NRF_LF_SRC_SYNTH
|
||||
|
||||
In order to override this configuration use targed_override section in configuration file (e.g mbed_app.json)
|
||||
|
||||
```json
|
||||
{
|
||||
"target_overrides": {
|
||||
"*": {
|
||||
"target.lf_clock_src": "NRF_LF_SRC_XTAL"
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
2a. Advanced configuration of the LFCLK RC oscillator:
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"lf_clock_rc_calib_timer_interval": {
|
||||
"value": 16,
|
||||
"macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL"
|
||||
},
|
||||
"lf_clock_rc_calib_mode_config": {
|
||||
"value": 1,
|
||||
"macro_name": "MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
"lf_clock_rc_calib_timer_interval" - Calibration timer interval in 250 ms. It is equivalent to nrf_clock_lf_cfg_t::rc_ctiv.
|
||||
This item generates macro MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_TIMER_INTERVAL.
|
||||
By default, such configuration is set to 16.
|
||||
|
||||
"lf_clock_rc_calib_mode_config" - This value configures how often the RC oscillator will be calibrated, in number of calibration intervals.
|
||||
It is equivalent to nrf_clock_lf_cfg_t::rc_temp_ctiv.
|
||||
For further information, see the documentation for the [API of a SoftDevice 13x version 2.0.0](http://infocenter.nordicsemi.com/topic/com.nordic.infocenter.s132.api.v2.0.0/structnrf__clock__lf__cfg__t.html)
|
||||
This item generates macro MBED_CONF_NORDIC_NRF_LF_CLOCK_CALIB_MODE_CONFIG.
|
||||
By default, such configuration is set to 1.
|
||||
|
||||
2b. Advanced configuration of the LFCLK XTAL oscillator:
|
||||
|
||||
Accuracy of the clock source can be set. In order to do so macro MBED_CONF_NORDIC_LF_CLOCK_XTAL_ACCURACY should been provided (e.g. in mbed_app.json).
|
||||
By default such configuration is set to NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM.
|
||||
For further information, see the documentation for the [API of a SoftDevice 13x version 2.0.0](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s132.api.v2.0.0%2Fgroup___n_r_f___s_d_m___d_e_f_i_n_e_s.html)
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"lf_clock_xtal_accuracy": {
|
||||
"value": "NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM",
|
||||
"macro_name": "MBED_CONF_NORDIC_LF_CLOCK_XTAL_ACCURACY"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
||||
|
||||
2c. Advance configuration of the LFCLK Synthesized from HFCLK:
|
||||
|
||||
Accuracy of the clock source can be set. In order to do so macro MBED_CONF_NORDIC_LF_CLOCK_SYNTH_ACCURACY should been provided (e.g. in mbed_app.json).
|
||||
By default, such configuration is set to NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM.
|
||||
For further information, see the documentation for the [API of a SoftDevice 13x version 2.0.0](https://infocenter.nordicsemi.com/index.jsp?topic=%2Fcom.nordic.infocenter.s132.api.v2.0.0%2Fgroup___n_r_f___s_d_m___d_e_f_i_n_e_s.html)
|
||||
|
||||
```json
|
||||
{
|
||||
"config": {
|
||||
"lf_clock_synth_accuracy": {
|
||||
"value": "NRF_CLOCK_LF_SYNTH_ACCURACY_250_PPM",
|
||||
"macro_name": "MBED_CONF_NORDIC_LF_CLOCK_XTAL_ACCURACY"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_PERIPHERALNAMES_H
|
||||
#define MBED_PERIPHERALNAMES_H
|
||||
|
||||
#include "cmsis.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define STDIO_UART_TX TX_PIN_NUMBER
|
||||
#define STDIO_UART_RX RX_PIN_NUMBER
|
||||
#define STDIO_UART UART_0
|
||||
|
||||
typedef enum
|
||||
{
|
||||
UART_0 = (int)NRF_UART0_BASE
|
||||
} UARTName;
|
||||
|
||||
|
||||
typedef enum
|
||||
{
|
||||
SPI_0 = (int)NRF_SPI0_BASE,
|
||||
SPI_1 = (int)NRF_SPI1_BASE,
|
||||
SPIS = (int)NRF_SPIS1_BASE
|
||||
} SPIName;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
PWM_1 = 0,
|
||||
PWM_2
|
||||
} PWMName;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
I2C_0 = (int)NRF_TWI0_BASE,
|
||||
I2C_1 = (int)NRF_TWI1_BASE
|
||||
} I2CName;
|
||||
|
||||
typedef enum
|
||||
{
|
||||
ADC0_0 = (int)0
|
||||
} ADCName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_PORTNAMES_H
|
||||
#define MBED_PORTNAMES_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum
|
||||
{
|
||||
Port0 = 0, //GPIO pins 0-31 -> 0.0-0.31
|
||||
Port1 = 1 //GPIO pins 32-47 -> 1.0-1.15
|
||||
} PortName;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
|
@ -0,0 +1,241 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_PINNAMES_H
|
||||
#define MBED_PINNAMES_H
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef enum {
|
||||
PIN_INPUT,
|
||||
PIN_OUTPUT
|
||||
} PinDirection;
|
||||
|
||||
#define PORT_SHIFT 3
|
||||
|
||||
///> define macro producing for example Px_y = NRF_GPIO_PIN_MAP(x, y)
|
||||
#define PinDef(port_num, pin_num) P##port_num##_##pin_num = NRF_GPIO_PIN_MAP(port_num, pin_num)
|
||||
|
||||
|
||||
typedef enum {
|
||||
PinDef(0 , 0), // P0_0 = 0...
|
||||
PinDef(0 , 1),
|
||||
PinDef(0 , 2),
|
||||
PinDef(0 , 3),
|
||||
PinDef(0 , 4),
|
||||
PinDef(0 , 5),
|
||||
PinDef(0 , 6),
|
||||
PinDef(0 , 7),
|
||||
PinDef(0 , 8),
|
||||
PinDef(0 , 9),
|
||||
PinDef(0 , 10),
|
||||
PinDef(0 , 11),
|
||||
PinDef(0 , 12),
|
||||
PinDef(0 , 13),
|
||||
PinDef(0 , 14),
|
||||
PinDef(0 , 15),
|
||||
PinDef(0 , 16),
|
||||
PinDef(0 , 17),
|
||||
PinDef(0 , 18),
|
||||
PinDef(0 , 19),
|
||||
PinDef(0 , 20),
|
||||
PinDef(0 , 21),
|
||||
PinDef(0 , 22),
|
||||
PinDef(0 , 23),
|
||||
PinDef(0 , 24),
|
||||
PinDef(0 , 25),
|
||||
PinDef(0 , 26),
|
||||
PinDef(0 , 27),
|
||||
PinDef(0 , 28),
|
||||
PinDef(0 , 29),
|
||||
PinDef(0 , 30),
|
||||
PinDef(0 , 31),
|
||||
|
||||
PinDef(1 , 0), //P1_1 = 32...
|
||||
PinDef(1 , 1),
|
||||
PinDef(1 , 2),
|
||||
PinDef(1 , 3),
|
||||
PinDef(1 , 4),
|
||||
PinDef(1 , 5),
|
||||
PinDef(1 , 6),
|
||||
PinDef(1 , 7),
|
||||
PinDef(1 , 8),
|
||||
PinDef(1 , 9),
|
||||
PinDef(1 , 10),
|
||||
PinDef(1 , 11),
|
||||
PinDef(1 , 12),
|
||||
PinDef(1 , 13),
|
||||
PinDef(1 , 14),
|
||||
PinDef(1 , 15),
|
||||
|
||||
// Port0
|
||||
p0 = P0_0,
|
||||
p1 = P0_1,
|
||||
p2 = P0_2,
|
||||
p3 = P0_3,
|
||||
p4 = P0_4,
|
||||
p5 = P0_5,
|
||||
p6 = P0_6,
|
||||
p7 = P0_7,
|
||||
p8 = P0_8,
|
||||
p9 = P0_9,
|
||||
p10 = P0_10,
|
||||
p11 = P0_11,
|
||||
p12 = P0_12,
|
||||
p13 = P0_13,
|
||||
p14 = P0_14,
|
||||
p15 = P0_15,
|
||||
p16 = P0_16,
|
||||
p17 = P0_17,
|
||||
p18 = P0_18,
|
||||
p19 = P0_19,
|
||||
p20 = P0_20,
|
||||
p21 = P0_21,
|
||||
p22 = P0_22,
|
||||
p23 = P0_23,
|
||||
p24 = P0_24,
|
||||
p25 = P0_25,
|
||||
p26 = P0_26,
|
||||
p27 = P0_27,
|
||||
p28 = P0_28,
|
||||
p29 = P0_29,
|
||||
p30 = P0_30,
|
||||
p31 = P0_31,
|
||||
|
||||
// Port1
|
||||
p32 = P1_0,
|
||||
p33 = P1_1,
|
||||
p34 = P1_2,
|
||||
p35 = P1_3,
|
||||
p36 = P1_4,
|
||||
p37 = P1_5,
|
||||
p38 = P1_6,
|
||||
p39 = P1_7,
|
||||
p40 = P1_8,
|
||||
p41 = P1_9,
|
||||
p42 = P1_10,
|
||||
p43 = P1_11,
|
||||
p44 = P1_12,
|
||||
p45 = P1_13,
|
||||
p46 = P1_14,
|
||||
p47 = P1_15,
|
||||
|
||||
LED1 = p13,
|
||||
LED2 = p14,
|
||||
LED3 = p15,
|
||||
LED4 = p16,
|
||||
|
||||
BUTTON1 = p11,
|
||||
BUTTON2 = p12,
|
||||
BUTTON3 = p24,
|
||||
BUTTON4 = p25,
|
||||
|
||||
RX_PIN_NUMBER = p8,
|
||||
TX_PIN_NUMBER = p6,
|
||||
CTS_PIN_NUMBER = p7,
|
||||
RTS_PIN_NUMBER = p5,
|
||||
|
||||
// mBed interface Pins
|
||||
USBTX = TX_PIN_NUMBER,
|
||||
USBRX = RX_PIN_NUMBER,
|
||||
|
||||
SPI_PSELMOSI0 = P1_13,
|
||||
SPI_PSELMISO0 = P1_14,
|
||||
SPI_PSELSS0 = P1_12,
|
||||
SPI_PSELSCK0 = P1_15,
|
||||
|
||||
SPI_PSELMOSI1 = P1_2,
|
||||
SPI_PSELMISO1 = P1_3,
|
||||
SPI_PSELSS1 = P1_1,
|
||||
SPI_PSELSCK1 = P1_4,
|
||||
|
||||
SPIS_PSELMOSI = P1_2,
|
||||
SPIS_PSELMISO = P1_3,
|
||||
SPIS_PSELSS = P1_1,
|
||||
SPIS_PSELSCK = P1_4,
|
||||
|
||||
I2C_SDA0 = p26,
|
||||
I2C_SCL0 = p27,
|
||||
|
||||
D0 = P1_1,
|
||||
D1 = P1_2,
|
||||
D2 = P1_3,
|
||||
D3 = P1_4,
|
||||
D4 = P1_5,
|
||||
D5 = P1_6,
|
||||
D6 = P1_7,
|
||||
D7 = P1_8,
|
||||
|
||||
D8 = P1_10,
|
||||
D9 = P1_11,
|
||||
D10 = P1_12,
|
||||
D11 = P1_13,
|
||||
D12 = P1_14,
|
||||
D13 = P1_15,
|
||||
|
||||
D14 = p26,
|
||||
D15 = p27,
|
||||
|
||||
A0 = p3,
|
||||
A1 = p4,
|
||||
A2 = p28,
|
||||
A3 = p29,
|
||||
A4 = p30,
|
||||
A5 = p31,
|
||||
|
||||
// Not connected
|
||||
NC = (int)0xFFFFFFFF
|
||||
} PinName;
|
||||
|
||||
typedef enum {
|
||||
PullNone = 0,
|
||||
PullDown = 1,
|
||||
PullUp = 3,
|
||||
PullDefault = PullUp
|
||||
} PinMode;
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,38 @@
|
|||
// The 'features' section in 'target.json' is now used to create the device's hardware preprocessor switches.
|
||||
// Check the 'features' section of the target description in 'targets.json' for more details.
|
||||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_DEVICE_H
|
||||
#define MBED_DEVICE_H
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
#include "objects.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,13 @@
|
|||
LR_IROM1 0x21000 0x00DF000 {
|
||||
ER_IROM1 0x21000 0x00DF000 {
|
||||
*.o (RESET, +First)
|
||||
*(InRoot$$Sections)
|
||||
.ANY (+RO)
|
||||
}
|
||||
RW_IRAM0 0x20003288 UNINIT 0x000000F8 { ;no init section
|
||||
*(noinit)
|
||||
}
|
||||
RW_IRAM1 0x20003380 0x0003cc80 {
|
||||
.ANY (+RW +ZI)
|
||||
}
|
||||
}
|
|
@ -0,0 +1,269 @@
|
|||
;/* Copyright (c) 2012 ARM LIMITED
|
||||
;
|
||||
; All rights reserved.
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
; - Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; - Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
; - Neither the name of ARM nor the names of its contributors may be used
|
||||
; to endorse or promote products derived from this software without
|
||||
; specific prior written permission.
|
||||
; *
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
; POSSIBILITY OF SUCH DAMAGE.
|
||||
; ---------------------------------------------------------------------------*/
|
||||
|
||||
__initial_sp EQU 0x20040000
|
||||
|
||||
PRESERVE8
|
||||
THUMB
|
||||
|
||||
; Vector Table Mapped to Address 0 at Reset
|
||||
|
||||
AREA RESET, DATA, READONLY
|
||||
EXPORT __Vectors
|
||||
EXPORT __Vectors_End
|
||||
EXPORT __Vectors_Size
|
||||
|
||||
__Vectors DCD __initial_sp ; Top of Stack
|
||||
DCD Reset_Handler
|
||||
DCD NMI_Handler
|
||||
DCD HardFault_Handler
|
||||
DCD MemoryManagement_Handler
|
||||
DCD BusFault_Handler
|
||||
DCD UsageFault_Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD SVC_Handler
|
||||
DCD DebugMonitor_Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD PendSV_Handler
|
||||
DCD SysTick_Handler
|
||||
|
||||
; External Interrupts
|
||||
DCD POWER_CLOCK_IRQHandler
|
||||
DCD RADIO_IRQHandler
|
||||
DCD UARTE0_UART0_IRQHandler_v
|
||||
DCD SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v
|
||||
DCD SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v
|
||||
DCD NFCT_IRQHandler_v
|
||||
DCD GPIOTE_IRQHandler_v
|
||||
DCD SAADC_IRQHandler_v
|
||||
DCD TIMER0_IRQHandler_v
|
||||
DCD TIMER1_IRQHandler_v
|
||||
DCD TIMER2_IRQHandler_v
|
||||
DCD RTC0_IRQHandler
|
||||
DCD TEMP_IRQHandler_v
|
||||
DCD RNG_IRQHandler
|
||||
DCD ECB_IRQHandler
|
||||
DCD CCM_AAR_IRQHandler
|
||||
DCD WDT_IRQHandler_v
|
||||
DCD RTC1_IRQHandler_v
|
||||
DCD QDEC_IRQHandler_v
|
||||
DCD COMP_LPCOMP_IRQHandler_v
|
||||
DCD SWI0_EGU0_IRQHandler_v
|
||||
DCD SWI1_EGU1_IRQHandler_v
|
||||
DCD SWI2_EGU2_IRQHandler_v
|
||||
DCD SWI3_EGU3_IRQHandler_v
|
||||
DCD SWI4_EGU4_IRQHandler
|
||||
DCD SWI5_EGU5_IRQHandler
|
||||
DCD TIMER3_IRQHandler_v
|
||||
DCD TIMER4_IRQHandler_v
|
||||
DCD PWM0_IRQHandler_v
|
||||
DCD PDM_IRQHandler_v
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD MWU_IRQHandler
|
||||
DCD PWM1_IRQHandler_v
|
||||
DCD PWM2_IRQHandler_v
|
||||
DCD SPIM2_SPIS2_SPI2_IRQHandler_v
|
||||
DCD RTC2_IRQHandler_v
|
||||
DCD I2S_IRQHandler_v
|
||||
DCD FPU_IRQHandler_v
|
||||
DCD USBD_IRQHandler_v
|
||||
DCD UARTE1_IRQHandler_v
|
||||
DCD QSPI_IRQHandler_v
|
||||
DCD CRYPTOCELL_IRQHandler_v
|
||||
DCD SPIM3_IRQHandler_v
|
||||
DCD 0 ; Reserved
|
||||
DCD PWM3_IRQHandler_v
|
||||
|
||||
__Vectors_End
|
||||
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
AREA |.text|, CODE, READONLY
|
||||
|
||||
; Reset Handler
|
||||
|
||||
|
||||
Reset_Handler PROC
|
||||
EXPORT Reset_Handler [WEAK]
|
||||
IMPORT SystemInit
|
||||
IMPORT __main
|
||||
IMPORT nrf_reloc_vector_table
|
||||
|
||||
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =nrf_reloc_vector_table
|
||||
BLX R0
|
||||
LDR R0, =__main
|
||||
BX R0
|
||||
ENDP
|
||||
|
||||
; Dummy Exception Handlers (infinite loops which can be modified)
|
||||
|
||||
NMI_Handler PROC
|
||||
EXPORT NMI_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
HardFault_Handler\
|
||||
PROC
|
||||
EXPORT HardFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
MemoryManagement_Handler\
|
||||
PROC
|
||||
EXPORT MemoryManagement_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
BusFault_Handler\
|
||||
PROC
|
||||
EXPORT BusFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
UsageFault_Handler\
|
||||
PROC
|
||||
EXPORT UsageFault_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SVC_Handler PROC
|
||||
EXPORT SVC_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
DebugMonitor_Handler\
|
||||
PROC
|
||||
EXPORT DebugMonitor_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
PendSV_Handler PROC
|
||||
EXPORT PendSV_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
SysTick_Handler PROC
|
||||
EXPORT SysTick_Handler [WEAK]
|
||||
B .
|
||||
ENDP
|
||||
|
||||
Default_Handler PROC
|
||||
|
||||
EXPORT POWER_CLOCK_IRQHandler [WEAK]
|
||||
EXPORT RADIO_IRQHandler [WEAK]
|
||||
EXPORT UARTE0_UART0_IRQHandler_v [WEAK]
|
||||
EXPORT SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v [WEAK]
|
||||
EXPORT SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v [WEAK]
|
||||
EXPORT NFCT_IRQHandler_v [WEAK]
|
||||
EXPORT GPIOTE_IRQHandler_v [WEAK]
|
||||
EXPORT SAADC_IRQHandler_v [WEAK]
|
||||
EXPORT TIMER0_IRQHandler_v [WEAK]
|
||||
EXPORT TIMER1_IRQHandler_v [WEAK]
|
||||
EXPORT TIMER2_IRQHandler_v [WEAK]
|
||||
EXPORT RTC0_IRQHandler [WEAK]
|
||||
EXPORT TEMP_IRQHandler_v [WEAK]
|
||||
EXPORT RNG_IRQHandler [WEAK]
|
||||
EXPORT ECB_IRQHandler [WEAK]
|
||||
EXPORT CCM_AAR_IRQHandler [WEAK]
|
||||
EXPORT WDT_IRQHandler_v [WEAK]
|
||||
EXPORT RTC1_IRQHandler_v [WEAK]
|
||||
EXPORT QDEC_IRQHandler_v [WEAK]
|
||||
EXPORT COMP_LPCOMP_IRQHandler_v [WEAK]
|
||||
EXPORT SWI0_EGU0_IRQHandler_v [WEAK]
|
||||
EXPORT SWI1_EGU1_IRQHandler_v [WEAK]
|
||||
EXPORT SWI2_EGU2_IRQHandler_v [WEAK]
|
||||
EXPORT SWI3_EGU3_IRQHandler_v [WEAK]
|
||||
EXPORT SWI4_EGU4_IRQHandler [WEAK]
|
||||
EXPORT SWI5_EGU5_IRQHandler [WEAK]
|
||||
EXPORT TIMER3_IRQHandler_v [WEAK]
|
||||
EXPORT TIMER4_IRQHandler_v [WEAK]
|
||||
EXPORT PWM0_IRQHandler_v [WEAK]
|
||||
EXPORT PDM_IRQHandler_v [WEAK]
|
||||
EXPORT MWU_IRQHandler [WEAK]
|
||||
EXPORT PWM1_IRQHandler_v [WEAK]
|
||||
EXPORT PWM2_IRQHandler_v [WEAK]
|
||||
EXPORT SPIM2_SPIS2_SPI2_IRQHandler_v [WEAK]
|
||||
EXPORT RTC2_IRQHandler_v [WEAK]
|
||||
EXPORT I2S_IRQHandler_v [WEAK]
|
||||
EXPORT FPU_IRQHandler_v [WEAK]
|
||||
EXPORT USBD_IRQHandler_v [WEAK]
|
||||
EXPORT UARTE1_IRQHandler_v [WEAK]
|
||||
EXPORT QSPI_IRQHandler_v [WEAK]
|
||||
EXPORT CRYPTOCELL_IRQHandler_v [WEAK]
|
||||
EXPORT SPIM3_IRQHandler_v [WEAK]
|
||||
EXPORT PWM3_IRQHandler_v [WEAK]
|
||||
|
||||
|
||||
|
||||
|
||||
POWER_CLOCK_IRQHandler
|
||||
RADIO_IRQHandler
|
||||
UARTE0_UART0_IRQHandler_v
|
||||
SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v
|
||||
SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v
|
||||
NFCT_IRQHandler_v
|
||||
GPIOTE_IRQHandler_v
|
||||
SAADC_IRQHandler_v
|
||||
TIMER0_IRQHandler_v
|
||||
TIMER1_IRQHandler_v
|
||||
TIMER2_IRQHandler_v
|
||||
RTC0_IRQHandler
|
||||
TEMP_IRQHandler_v
|
||||
RNG_IRQHandler
|
||||
ECB_IRQHandler
|
||||
CCM_AAR_IRQHandler
|
||||
WDT_IRQHandler_v
|
||||
RTC1_IRQHandler_v
|
||||
QDEC_IRQHandler_v
|
||||
COMP_LPCOMP_IRQHandler_v
|
||||
SWI0_EGU0_IRQHandler_v
|
||||
SWI1_EGU1_IRQHandler_v
|
||||
SWI2_EGU2_IRQHandler_v
|
||||
SWI3_EGU3_IRQHandler_v
|
||||
SWI4_EGU4_IRQHandler
|
||||
SWI5_EGU5_IRQHandler
|
||||
TIMER3_IRQHandler_v
|
||||
TIMER4_IRQHandler_v
|
||||
PWM0_IRQHandler_v
|
||||
PDM_IRQHandler_v
|
||||
MWU_IRQHandler
|
||||
PWM1_IRQHandler_v
|
||||
PWM2_IRQHandler_v
|
||||
SPIM2_SPIS2_SPI2_IRQHandler_v
|
||||
RTC2_IRQHandler_v
|
||||
I2S_IRQHandler_v
|
||||
FPU_IRQHandler_v
|
||||
USBD_IRQHandler_v
|
||||
UARTE1_IRQHandler_v
|
||||
QSPI_IRQHandler_v
|
||||
CRYPTOCELL_IRQHandler_v
|
||||
SPIM3_IRQHandler_v
|
||||
PWM3_IRQHandler_v
|
||||
|
||||
B .
|
||||
ENDP
|
||||
ALIGN
|
||||
END
|
|
@ -0,0 +1,31 @@
|
|||
/* mbed Microcontroller Library - stackheap
|
||||
* Copyright (C) 2009-2011 ARM Limited. All rights reserved.
|
||||
*
|
||||
* Setup a fixed single stack/heap memory model,
|
||||
* between the top of the RW/ZI region and the stackpointer
|
||||
*/
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <rt_misc.h>
|
||||
#include <stdint.h>
|
||||
|
||||
extern char Image$$RW_IRAM1$$ZI$$Limit[];
|
||||
|
||||
extern __value_in_regs struct __initial_stackheap __user_setup_stackheap(uint32_t R0, uint32_t R1, uint32_t R2, uint32_t R3) {
|
||||
uint32_t zi_limit = (uint32_t)Image$$RW_IRAM1$$ZI$$Limit;
|
||||
uint32_t sp_limit = __current_sp();
|
||||
|
||||
zi_limit = (zi_limit + 7) & ~0x7; // ensure zi_limit is 8-byte aligned
|
||||
|
||||
struct __initial_stackheap r;
|
||||
r.heap_base = zi_limit;
|
||||
r.heap_limit = sp_limit;
|
||||
return r;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
|
@ -0,0 +1,190 @@
|
|||
/*
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
/* Linker script to configure memory regions. */
|
||||
|
||||
MEMORY
|
||||
{
|
||||
FLASH (rx) : ORIGIN = 0x21000, LENGTH = 0xDF000
|
||||
RAM (rwx) : ORIGIN = 0x20003288, LENGTH = 0x3cd78
|
||||
}
|
||||
|
||||
|
||||
OUTPUT_FORMAT ("elf32-littlearm", "elf32-bigarm", "elf32-littlearm")
|
||||
|
||||
/* Linker script to place sections and symbol values. Should be used together
|
||||
* with the other linker script that defines memory regions FLASH and RAM.
|
||||
* It references the following symbols that must be defined in code:
|
||||
* Reset_Handler : Entry of reset handler
|
||||
*
|
||||
* It defines the following symbols that the code can use without definition:
|
||||
* __exidx_start
|
||||
* __exidx_end
|
||||
* __etext
|
||||
* __data_start__
|
||||
* __preinit_array_start
|
||||
* __preinit_array_end
|
||||
* __init_array_start
|
||||
* __init_array_end
|
||||
* __fini_array_start
|
||||
* __fini_array_end
|
||||
* __data_end__
|
||||
* __bss_start__
|
||||
* __bss_end__
|
||||
* __end__
|
||||
* end
|
||||
* __HeapLimit
|
||||
* __StackLimit
|
||||
* __StackTop
|
||||
* __stack
|
||||
*/
|
||||
ENTRY(Reset_Handler)
|
||||
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
.text :
|
||||
{
|
||||
KEEP(*(.Vectors))
|
||||
*(.text*)
|
||||
|
||||
KEEP(*(.init))
|
||||
KEEP(*(.fini))
|
||||
|
||||
/* .ctors */
|
||||
*crtbegin.o(.ctors)
|
||||
*crtbegin?.o(.ctors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .ctors)
|
||||
*(SORT(.ctors.*))
|
||||
*(.ctors)
|
||||
|
||||
/* .dtors */
|
||||
*crtbegin.o(.dtors)
|
||||
*crtbegin?.o(.dtors)
|
||||
*(EXCLUDE_FILE(*crtend?.o *crtend.o) .dtors)
|
||||
*(SORT(.dtors.*))
|
||||
*(.dtors)
|
||||
|
||||
*(.rodata*)
|
||||
|
||||
KEEP(*(.eh_frame*))
|
||||
} > FLASH
|
||||
|
||||
.ARM.extab :
|
||||
{
|
||||
*(.ARM.extab* .gnu.linkonce.armextab.*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
|
||||
__exidx_start = .;
|
||||
.ARM.exidx :
|
||||
{
|
||||
*(.ARM.exidx* .gnu.linkonce.armexidx.*)
|
||||
. = ALIGN(4);
|
||||
} > FLASH
|
||||
__exidx_end = .;
|
||||
|
||||
__etext = .;
|
||||
|
||||
.data : AT (__etext)
|
||||
{
|
||||
__data_start__ = .;
|
||||
*(vtable)
|
||||
*(.data*)
|
||||
|
||||
. = ALIGN(4);
|
||||
/* preinit data */
|
||||
PROVIDE_HIDDEN (__preinit_array_start = .);
|
||||
KEEP(*(.preinit_array))
|
||||
PROVIDE_HIDDEN (__preinit_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
/* init data */
|
||||
PROVIDE_HIDDEN (__init_array_start = .);
|
||||
KEEP(*(SORT(.init_array.*)))
|
||||
KEEP(*(.init_array))
|
||||
PROVIDE_HIDDEN (__init_array_end = .);
|
||||
|
||||
|
||||
. = ALIGN(4);
|
||||
/* finit data */
|
||||
PROVIDE_HIDDEN (__fini_array_start = .);
|
||||
KEEP(*(SORT(.fini_array.*)))
|
||||
KEEP(*(.fini_array))
|
||||
PROVIDE_HIDDEN (__fini_array_end = .);
|
||||
|
||||
. = ALIGN(4);
|
||||
PROVIDE(__start_fs_data = .);
|
||||
KEEP(*(.fs_data))
|
||||
PROVIDE(__stop_fs_data = .);
|
||||
|
||||
*(.jcr)
|
||||
. = ALIGN(4);
|
||||
/* All data end */
|
||||
__data_end__ = .;
|
||||
|
||||
} > RAM
|
||||
|
||||
__edata = .;
|
||||
|
||||
.noinit :
|
||||
{
|
||||
PROVIDE(__start_noinit = .);
|
||||
KEEP(*(.noinit))
|
||||
PROVIDE(__stop_noinit = .);
|
||||
} > RAM
|
||||
|
||||
.bss :
|
||||
{
|
||||
. = ALIGN(4);
|
||||
__bss_start__ = .;
|
||||
*(.bss*)
|
||||
*(COMMON)
|
||||
. = ALIGN(4);
|
||||
__bss_end__ = .;
|
||||
} > RAM
|
||||
|
||||
.heap (NOLOAD):
|
||||
{
|
||||
__end__ = .;
|
||||
end = __end__;
|
||||
*(.heap*);
|
||||
|
||||
/* Expand the heap to reach the stack boundary. */
|
||||
ASSERT(. <= (ORIGIN(RAM) + LENGTH(RAM) - 0x800), "heap region overflowed into stack");
|
||||
. += (ORIGIN(RAM) + LENGTH(RAM) - 0x800) - .;
|
||||
} > RAM
|
||||
PROVIDE(__heap_start = ADDR(.heap));
|
||||
PROVIDE(__heap_size = SIZEOF(.heap));
|
||||
PROVIDE(__mbed_sbrk_start = ADDR(.heap));
|
||||
PROVIDE(__mbed_krbs_start = ADDR(.heap) + SIZEOF(.heap));
|
||||
|
||||
/* .stack_dummy section does not contain any symbols. It is only
|
||||
* used for the linker script to calculate the size of stack sections
|
||||
* and assign values to stack symbols later. */
|
||||
.stack (NOLOAD):
|
||||
{
|
||||
__StackLimit = .;
|
||||
*(.stack*)
|
||||
. += (ORIGIN(RAM) + LENGTH(RAM) - .);
|
||||
} > RAM
|
||||
|
||||
/* Set the stack top to the end of RAM and move down the stack limit by
|
||||
* the size of the stack_dummy section. */
|
||||
__StackTop = ORIGIN(RAM) + LENGTH(RAM);
|
||||
__StackLimit = __StackTop - SIZEOF(.stack);
|
||||
PROVIDE(__stack = __StackTop);
|
||||
}
|
|
@ -0,0 +1,283 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
NOTE: Template files (including this one) are application specific and therefore
|
||||
expected to be copied into the application project folder prior to its use!
|
||||
*/
|
||||
|
||||
.syntax unified
|
||||
.arch armv7e-m
|
||||
|
||||
.section .Vectors
|
||||
.align 2
|
||||
.globl __Vectors
|
||||
__Vectors:
|
||||
.long __StackTop /* Top of Stack */
|
||||
.long Reset_Handler
|
||||
.long NMI_Handler
|
||||
.long HardFault_Handler
|
||||
.long MemoryManagement_Handler
|
||||
.long BusFault_Handler
|
||||
.long UsageFault_Handler
|
||||
.long 0 /*Reserved */
|
||||
.long 0 /*Reserved */
|
||||
.long 0 /*Reserved */
|
||||
.long 0 /*Reserved */
|
||||
.long SVC_Handler
|
||||
.long 0 /*Reserved */
|
||||
.long 0 /*Reserved */
|
||||
.long PendSV_Handler
|
||||
.long SysTick_Handler
|
||||
|
||||
/* External Interrupts */
|
||||
.long POWER_CLOCK_IRQHandler
|
||||
.long RADIO_IRQHandler
|
||||
.long UARTE0_UART0_IRQHandler_v
|
||||
.long SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v
|
||||
.long SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v
|
||||
.long NFCT_IRQHandler_v
|
||||
.long GPIOTE_IRQHandler_v
|
||||
.long SAADC_IRQHandler_v
|
||||
.long TIMER0_IRQHandler_v
|
||||
.long TIMER1_IRQHandler_v
|
||||
.long TIMER2_IRQHandler_v
|
||||
.long RTC0_IRQHandler
|
||||
.long TEMP_IRQHandler_v
|
||||
.long RNG_IRQHandler
|
||||
.long ECB_IRQHandler
|
||||
.long CCM_AAR_IRQHandler
|
||||
.long WDT_IRQHandler_v
|
||||
.long RTC1_IRQHandler_v
|
||||
.long QDEC_IRQHandler_v
|
||||
.long COMP_LPCOMP_IRQHandler_v
|
||||
.long SWI0_EGU0_IRQHandler_v
|
||||
.long SWI1_EGU1_IRQHandler_v
|
||||
.long SWI2_EGU2_IRQHandler_v
|
||||
.long SWI3_EGU3_IRQHandler_v
|
||||
.long SWI4_EGU4_IRQHandler
|
||||
.long SWI5_EGU5_IRQHandler
|
||||
.long TIMER3_IRQHandler_v
|
||||
.long TIMER4_IRQHandler_v
|
||||
.long PWM0_IRQHandler_v
|
||||
.long PDM_IRQHandler_v
|
||||
.long 0 /*Reserved */
|
||||
.long 0 /*Reserved */
|
||||
.long MWU_IRQHandler
|
||||
.long PWM1_IRQHandler_v
|
||||
.long PWM2_IRQHandler_v
|
||||
.long SPIM2_SPIS2_SPI2_IRQHandler_v
|
||||
.long RTC2_IRQHandler_v
|
||||
.long I2S_IRQHandler_v
|
||||
.long FPU_IRQHandler_v
|
||||
.long USBD_IRQHandler_v
|
||||
.long UARTE1_IRQHandler_v
|
||||
.long QSPI_IRQHandler_v
|
||||
.long CRYPTOCELL_IRQHandler_v
|
||||
.long SPIM3_IRQHandler_v
|
||||
.long 0 /*Reserved */
|
||||
.long PWM3_IRQHandler_v
|
||||
|
||||
|
||||
.size __Vectors, . - __Vectors
|
||||
|
||||
/* Reset Handler */
|
||||
|
||||
.text
|
||||
.thumb
|
||||
.thumb_func
|
||||
.align 1
|
||||
.globl Reset_Handler
|
||||
.type Reset_Handler, %function
|
||||
Reset_Handler:
|
||||
.fnstart
|
||||
|
||||
|
||||
/* Loop to copy data from read only memory to RAM. The ranges
|
||||
* of copy from/to are specified by following symbols evaluated in
|
||||
* linker script.
|
||||
* __etext: End of code section, i.e., begin of data sections to copy from.
|
||||
* __data_start__/__data_end__: RAM address range that data should be
|
||||
* copied to. Both must be aligned to 4 bytes boundary. */
|
||||
|
||||
ldr r1, =__etext
|
||||
ldr r2, =__data_start__
|
||||
ldr r3, =__data_end__
|
||||
|
||||
subs r3, r2
|
||||
ble .LC0
|
||||
|
||||
.LC1:
|
||||
subs r3, 4
|
||||
ldr r0, [r1,r3]
|
||||
str r0, [r2,r3]
|
||||
bgt .LC1
|
||||
.LC0:
|
||||
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =nrf_reloc_vector_table
|
||||
BLX R0
|
||||
LDR R0, =_start
|
||||
BX R0
|
||||
|
||||
.pool
|
||||
.cantunwind
|
||||
.fnend
|
||||
.size Reset_Handler,.-Reset_Handler
|
||||
|
||||
.section ".text"
|
||||
|
||||
|
||||
/* Dummy Exception Handlers (infinite loops which can be modified) */
|
||||
|
||||
.weak NMI_Handler
|
||||
.type NMI_Handler, %function
|
||||
NMI_Handler:
|
||||
B .
|
||||
.size NMI_Handler, . - NMI_Handler
|
||||
|
||||
|
||||
.weak HardFault_Handler
|
||||
.type HardFault_Handler, %function
|
||||
HardFault_Handler:
|
||||
B .
|
||||
.size HardFault_Handler, . - HardFault_Handler
|
||||
|
||||
|
||||
.weak MemoryManagement_Handler
|
||||
.type MemoryManagement_Handler, %function
|
||||
MemoryManagement_Handler:
|
||||
B .
|
||||
.size MemoryManagement_Handler, . - MemoryManagement_Handler
|
||||
|
||||
|
||||
.weak BusFault_Handler
|
||||
.type BusFault_Handler, %function
|
||||
BusFault_Handler:
|
||||
B .
|
||||
.size BusFault_Handler, . - BusFault_Handler
|
||||
|
||||
|
||||
.weak UsageFault_Handler
|
||||
.type UsageFault_Handler, %function
|
||||
UsageFault_Handler:
|
||||
B .
|
||||
.size UsageFault_Handler, . - UsageFault_Handler
|
||||
|
||||
|
||||
.weak SVC_Handler
|
||||
.type SVC_Handler, %function
|
||||
SVC_Handler:
|
||||
B .
|
||||
.size SVC_Handler, . - SVC_Handler
|
||||
|
||||
|
||||
.weak PendSV_Handler
|
||||
.type PendSV_Handler, %function
|
||||
PendSV_Handler:
|
||||
B .
|
||||
.size PendSV_Handler, . - PendSV_Handler
|
||||
|
||||
|
||||
.weak SysTick_Handler
|
||||
.type SysTick_Handler, %function
|
||||
SysTick_Handler:
|
||||
B .
|
||||
.size SysTick_Handler, . - SysTick_Handler
|
||||
|
||||
|
||||
/* IRQ Handlers */
|
||||
|
||||
.globl Default_Handler
|
||||
.type Default_Handler, %function
|
||||
Default_Handler:
|
||||
B .
|
||||
.size Default_Handler, . - Default_Handler
|
||||
|
||||
.macro IRQ handler
|
||||
.weak \handler
|
||||
.set \handler, Default_Handler
|
||||
.endm
|
||||
|
||||
IRQ POWER_CLOCK_IRQHandler /* restricted */
|
||||
IRQ RADIO_IRQHandler /* blocked */
|
||||
IRQ UARTE0_UART0_IRQHandler_v
|
||||
IRQ SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v
|
||||
IRQ SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v
|
||||
IRQ NFCT_IRQHandler_v
|
||||
IRQ GPIOTE_IRQHandler_v
|
||||
IRQ SAADC_IRQHandler_v
|
||||
IRQ TIMER0_IRQHandler_v
|
||||
IRQ TIMER1_IRQHandler_v
|
||||
IRQ TIMER2_IRQHandler_v
|
||||
IRQ RTC0_IRQHandler /* blocked */
|
||||
IRQ TEMP_IRQHandler_v
|
||||
IRQ RNG_IRQHandler /* restricted */
|
||||
IRQ ECB_IRQHandler /* restricted */
|
||||
IRQ CCM_AAR_IRQHandler /* blocked */
|
||||
IRQ WDT_IRQHandler_v
|
||||
IRQ RTC1_IRQHandler_v
|
||||
IRQ QDEC_IRQHandler_v
|
||||
IRQ COMP_LPCOMP_IRQHandler_v
|
||||
IRQ SWI0_EGU0_IRQHandler_v
|
||||
IRQ SWI1_EGU1_IRQHandler_v /* restricted for Radio Notification */
|
||||
IRQ SWI2_EGU2_IRQHandler_v /* blocked for SoftDevice Event */
|
||||
IRQ SWI3_EGU3_IRQHandler_v
|
||||
IRQ SWI4_EGU4_IRQHandler /* blocked */
|
||||
IRQ SWI5_EGU5_IRQHandler /* blocked */
|
||||
IRQ TIMER3_IRQHandler_v
|
||||
IRQ TIMER4_IRQHandler_v
|
||||
IRQ PWM0_IRQHandler_v
|
||||
IRQ PDM_IRQHandler_v
|
||||
IRQ MWU_IRQHandler /* restricted */
|
||||
IRQ PWM1_IRQHandler_v
|
||||
IRQ PWM2_IRQHandler_v
|
||||
IRQ SPIM2_SPIS2_SPI2_IRQHandler_v
|
||||
IRQ RTC2_IRQHandler_v
|
||||
IRQ I2S_IRQHandler_v
|
||||
IRQ FPU_IRQHandler_v
|
||||
IRQ USBD_IRQHandler_v
|
||||
IRQ UARTE1_IRQHandler_v
|
||||
IRQ QSPI_IRQHandler_v
|
||||
IRQ CRYPTOCELL_IRQHandler_v
|
||||
IRQ SPIM3_IRQHandler_v
|
||||
IRQ PWM3_IRQHandler_v
|
||||
|
||||
.end
|
|
@ -0,0 +1,46 @@
|
|||
/*###ICF### Section handled by ICF editor, don't touch! ****/
|
||||
/*-Editor annotation file-*/
|
||||
/* IcfEditorFile="$TOOLKIT_DIR$\config\ide\IcfEditor\cortex_v1_0.xml" */
|
||||
/*-Specials-*/
|
||||
define symbol __ICFEDIT_intvec_start__ = 0x21000;
|
||||
/*-Memory Regions-*/
|
||||
define symbol __ICFEDIT_region_ROM_start__ = 0x21000;
|
||||
define symbol __ICFEDIT_region_ROM_end__ = 0xfffff;
|
||||
define symbol __ICFEDIT_region_RAM_start__ = 0x20003288;
|
||||
define symbol __ICFEDIT_region_RAM_end__ = 0x2003ffff;
|
||||
export symbol __ICFEDIT_region_RAM_start__;
|
||||
export symbol __ICFEDIT_region_RAM_end__;
|
||||
/*-Sizes-*/
|
||||
/*Heap 1/4 of ram and stack 1/8*/
|
||||
define symbol __ICFEDIT_size_cstack__ = 0x800;
|
||||
define symbol __ICFEDIT_size_heap__ = 0x3000;
|
||||
/**** End of ICF editor section. ###ICF###*/
|
||||
|
||||
define symbol __code_start_soft_device__ = 0x0;
|
||||
|
||||
define memory mem with size = 4G;
|
||||
define region ROM_region = mem:[from __ICFEDIT_region_ROM_start__ to __ICFEDIT_region_ROM_end__];
|
||||
define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFEDIT_region_RAM_end__];
|
||||
|
||||
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
||||
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
|
||||
|
||||
initialize by copy { readwrite };
|
||||
do not initialize { section .noinit };
|
||||
|
||||
keep { section .intvec };
|
||||
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
||||
place in ROM_region { readonly };
|
||||
place in RAM_region { readwrite,
|
||||
block HEAP,
|
||||
block CSTACK };
|
||||
|
||||
/*This is used for mbed applications build inside the Embedded workbench
|
||||
Applications build with the python scritps use a hex merge so need to merge it
|
||||
inside the linker. The linker can only use binary files so the hex merge is not possible
|
||||
through the linker. That is why a binary is used instead of a hex image for the embedded project.
|
||||
*/
|
||||
if(isdefinedsymbol(SOFT_DEVICE_BIN))
|
||||
{
|
||||
place at address mem:__code_start_soft_device__ { section .noinit_softdevice };
|
||||
}
|
|
@ -0,0 +1,417 @@
|
|||
;/* Copyright (c) 2012 ARM LIMITED
|
||||
;
|
||||
; All rights reserved.
|
||||
; Redistribution and use in source and binary forms, with or without
|
||||
; modification, are permitted provided that the following conditions are met:
|
||||
; - Redistributions of source code must retain the above copyright
|
||||
; notice, this list of conditions and the following disclaimer.
|
||||
; - Redistributions in binary form must reproduce the above copyright
|
||||
; notice, this list of conditions and the following disclaimer in the
|
||||
; documentation and/or other materials provided with the distribution.
|
||||
; - Neither the name of ARM nor the names of its contributors may be used
|
||||
; to endorse or promote products derived from this software without
|
||||
; specific prior written permission.
|
||||
; *
|
||||
; THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
; AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
; IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
; ARE DISCLAIMED. IN NO EVENT SHALL COPYRIGHT HOLDERS AND CONTRIBUTORS BE
|
||||
; LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
||||
; CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
; SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
; INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
; CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
; ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
; POSSIBILITY OF SUCH DAMAGE.
|
||||
; ---------------------------------------------------------------------------*/
|
||||
|
||||
|
||||
; The modules in this file are included in the libraries, and may be replaced
|
||||
; by any user-defined modules that define the PUBLIC symbol _program_start or
|
||||
; a user defined start symbol.
|
||||
; To override the cstartup defined in the library, simply add your modified
|
||||
; version to the workbench project.
|
||||
;
|
||||
; The vector table is normally located at address 0.
|
||||
; When debugging in RAM, it can be located in RAM, aligned to at least 2^6.
|
||||
; The name "__vector_table" has special meaning for C-SPY:
|
||||
; it is where the SP start value is found, and the NVIC vector
|
||||
; table register (VTOR) is initialized to this address if != 0.
|
||||
|
||||
|
||||
|
||||
MODULE ?cstartup
|
||||
|
||||
;; Stack size default : Defined in *.icf (linker file). Can be modified inside EW.
|
||||
;; Heap size default : Defined in *.icf (linker file). Can be modified inside EW.
|
||||
|
||||
;; Forward declaration of sections.
|
||||
SECTION CSTACK:DATA:NOROOT(3)
|
||||
|
||||
SECTION .intvec:CODE:NOROOT(2)
|
||||
|
||||
EXTERN __iar_program_start
|
||||
EXTERN SystemInit
|
||||
EXTERN nrf_reloc_vector_table
|
||||
PUBLIC __vector_table
|
||||
PUBLIC __Vectors
|
||||
PUBLIC __Vectors_End
|
||||
PUBLIC __Vectors_Size
|
||||
|
||||
DATA
|
||||
|
||||
__vector_table
|
||||
DCD sfe(CSTACK)
|
||||
DCD Reset_Handler
|
||||
DCD NMI_Handler
|
||||
DCD HardFault_Handler
|
||||
DCD MemoryManagement_Handler
|
||||
DCD BusFault_Handler
|
||||
DCD UsageFault_Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD SVC_Handler
|
||||
DCD DebugMonitor_Handler
|
||||
DCD 0 ; Reserved
|
||||
DCD PendSV_Handler
|
||||
DCD SysTick_Handler
|
||||
|
||||
; External Interrupts
|
||||
DCD POWER_CLOCK_IRQHandler
|
||||
DCD RADIO_IRQHandler
|
||||
DCD UARTE0_UART0_IRQHandler_v
|
||||
DCD SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v
|
||||
DCD SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v
|
||||
DCD NFCT_IRQHandler_v
|
||||
DCD GPIOTE_IRQHandler_v
|
||||
DCD SAADC_IRQHandler_v
|
||||
DCD TIMER0_IRQHandler_v
|
||||
DCD TIMER1_IRQHandler_v
|
||||
DCD TIMER2_IRQHandler_v
|
||||
DCD RTC0_IRQHandler
|
||||
DCD TEMP_IRQHandler_v
|
||||
DCD RNG_IRQHandler
|
||||
DCD ECB_IRQHandler
|
||||
DCD CCM_AAR_IRQHandler
|
||||
DCD WDT_IRQHandler_v
|
||||
DCD RTC1_IRQHandler_v
|
||||
DCD QDEC_IRQHandler_v
|
||||
DCD COMP_LPCOMP_IRQHandler_v
|
||||
DCD SWI0_EGU0_IRQHandler_v
|
||||
DCD SWI1_EGU1_IRQHandler_v
|
||||
DCD SWI2_EGU2_IRQHandler_v
|
||||
DCD SWI3_EGU3_IRQHandler_v
|
||||
DCD SWI4_EGU4_IRQHandler
|
||||
DCD SWI5_EGU5_IRQHandler
|
||||
DCD TIMER3_IRQHandler_v
|
||||
DCD TIMER4_IRQHandler_v
|
||||
DCD PWM0_IRQHandler_v
|
||||
DCD PDM_IRQHandler_v
|
||||
DCD 0 ; Reserved
|
||||
DCD 0 ; Reserved
|
||||
DCD MWU_IRQHandler
|
||||
DCD PWM1_IRQHandler_v
|
||||
DCD PWM2_IRQHandler_v
|
||||
DCD SPIM2_SPIS2_SPI2_IRQHandler_v
|
||||
DCD RTC2_IRQHandler_v
|
||||
DCD I2S_IRQHandler_v
|
||||
DCD FPU_IRQHandler_v
|
||||
DCD USBD_IRQHandler_v
|
||||
DCD UARTE1_IRQHandler_v
|
||||
DCD QSPI_IRQHandler_v
|
||||
DCD CRYPTOCELL_IRQHandler_v
|
||||
DCD SPIM3_IRQHandler_v
|
||||
DCD 0 /*Reserved */
|
||||
DCD PWM3_IRQHandler_v
|
||||
|
||||
__Vectors_End
|
||||
__Vectors EQU __vector_table
|
||||
__Vectors_Size EQU __Vectors_End - __Vectors
|
||||
|
||||
|
||||
; Default handlers.
|
||||
THUMB
|
||||
|
||||
PUBWEAK Reset_Handler
|
||||
SECTION .text:CODE:NOROOT(2)
|
||||
Reset_Handler
|
||||
|
||||
LDR R0, =SystemInit
|
||||
BLX R0
|
||||
LDR R0, =nrf_reloc_vector_table
|
||||
BLX R0
|
||||
LDR R0, =__iar_program_start
|
||||
BX R0
|
||||
|
||||
; Dummy exception handlers
|
||||
|
||||
|
||||
PUBWEAK NMI_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
NMI_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK HardFault_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
HardFault_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK MemoryManagement_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
MemoryManagement_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK BusFault_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
BusFault_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK UsageFault_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
UsageFault_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK SVC_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SVC_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK DebugMonitor_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
DebugMonitor_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK PendSV_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
PendSV_Handler
|
||||
B .
|
||||
|
||||
PUBWEAK SysTick_Handler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SysTick_Handler
|
||||
B .
|
||||
|
||||
|
||||
; Dummy interrupt handlers
|
||||
|
||||
PUBWEAK POWER_CLOCK_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
POWER_CLOCK_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK RADIO_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
RADIO_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK UARTE0_UART0_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
UARTE0_UART0_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SPIM0_SPIS0_TWIM0_TWIS0_SPI0_TWI0_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SPIM1_SPIS1_TWIM1_TWIS1_SPI1_TWI1_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK NFCT_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
NFCT_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK GPIOTE_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
GPIOTE_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SAADC_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SAADC_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK TIMER0_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
TIMER0_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK TIMER1_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
TIMER1_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK TIMER2_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
TIMER2_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK RTC0_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
RTC0_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK TEMP_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
TEMP_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK RNG_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
RNG_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK ECB_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
ECB_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK CCM_AAR_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
CCM_AAR_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK WDT_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
WDT_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK RTC1_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
RTC1_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK QDEC_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
QDEC_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK COMP_LPCOMP_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
COMP_LPCOMP_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SWI0_EGU0_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SWI0_EGU0_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SWI1_EGU1_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SWI1_EGU1_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SWI2_EGU2_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SWI2_EGU2_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SWI3_EGU3_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SWI3_EGU3_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SWI4_EGU4_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SWI4_EGU4_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK SWI5_EGU5_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SWI5_EGU5_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK TIMER3_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
TIMER3_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK TIMER4_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
TIMER4_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK PWM0_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
PWM0_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK PDM_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
PDM_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK MWU_IRQHandler
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
MWU_IRQHandler
|
||||
B .
|
||||
|
||||
PUBWEAK PWM1_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
PWM1_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK PWM2_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
PWM2_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SPIM2_SPIS2_SPI2_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SPIM2_SPIS2_SPI2_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK RTC2_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
RTC2_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK I2S_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
I2S_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK FPU_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
FPU_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK USBD_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
USBD_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK UARTE1_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
UARTE1_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK QSPI_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
QSPI_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK CRYPTOCELL_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
CRYPTOCELL_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK SPIM3_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
SPIM3_IRQHandler_v
|
||||
B .
|
||||
|
||||
PUBWEAK PWM3_IRQHandler_v
|
||||
SECTION .text:CODE:NOROOT(1)
|
||||
PWM3_IRQHandler_v
|
||||
B .
|
||||
|
||||
|
||||
END
|
||||
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
/*
|
||||
* PackageLicenseDeclared: Apache-2.0
|
||||
* Copyright (c) 2016 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef MBED_CMSIS_H
|
||||
#define MBED_CMSIS_H
|
||||
|
||||
#include "nrf.h"
|
||||
#include "cmsis_nvic.h"
|
||||
|
||||
#endif
|
|
@ -0,0 +1,43 @@
|
|||
/* mbed Microcontroller Library
|
||||
* CMSIS-style functionality to support dynamic vectors
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2016 ARM Limited. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of ARM Limited nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************
|
||||
*/
|
||||
#include "cmsis_nvic.h"
|
||||
|
||||
extern uint32_t nrf_dispatch_vector[NVIC_NUM_VECTORS];
|
||||
|
||||
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector)
|
||||
{
|
||||
nrf_dispatch_vector[IRQn + NVIC_USER_IRQ_OFFSET] = vector;
|
||||
}
|
||||
|
||||
uint32_t NVIC_GetVector(IRQn_Type IRQn)
|
||||
{
|
||||
return nrf_dispatch_vector[IRQn + NVIC_USER_IRQ_OFFSET];
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/* mbed Microcontroller Library
|
||||
* CMSIS-style functionality to support dynamic vectors
|
||||
*******************************************************************************
|
||||
* Copyright (c) 2016 ARM Limited. All rights reserved.
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of ARM Limited nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef MBED_CMSIS_NVIC_H
|
||||
#define MBED_CMSIS_NVIC_H
|
||||
|
||||
#define NVIC_NUM_VECTORS (16 + 46) // CORE + MCU Peripherals
|
||||
#define NVIC_USER_IRQ_OFFSET 16
|
||||
|
||||
#include "nrf.h"
|
||||
#include "cmsis.h"
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
void NVIC_SetVector(IRQn_Type IRQn, uint32_t vector);
|
||||
uint32_t NVIC_GetVector(IRQn_Type IRQn);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,209 @@
|
|||
/* Copyright (c) 2012 ARM LIMITED
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of ARM nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "nrf.h"
|
||||
#include "system_nrf52840.h"
|
||||
|
||||
/*lint ++flb "Enter library region" */
|
||||
|
||||
#define __SYSTEM_CLOCK_64M (64000000UL)
|
||||
|
||||
static bool errata_36(void);
|
||||
static bool errata_98(void);
|
||||
static bool errata_103(void);
|
||||
static bool errata_115(void);
|
||||
static bool errata_120(void);
|
||||
|
||||
|
||||
#if defined ( __CC_ARM )
|
||||
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M;
|
||||
#elif defined ( __ICCARM__ )
|
||||
__root uint32_t SystemCoreClock = __SYSTEM_CLOCK_64M;
|
||||
#elif defined ( __GNUC__ )
|
||||
uint32_t SystemCoreClock __attribute__((used)) = __SYSTEM_CLOCK_64M;
|
||||
#endif
|
||||
|
||||
void SystemCoreClockUpdate(void)
|
||||
{
|
||||
SystemCoreClock = __SYSTEM_CLOCK_64M;
|
||||
}
|
||||
|
||||
void SystemInit(void)
|
||||
{
|
||||
/* Workaround for Errata 36 "CLOCK: Some registers are not reset when expected" found at the Errata document
|
||||
for your device located at https://infocenter.nordicsemi.com/ */
|
||||
if (errata_36()){
|
||||
NRF_CLOCK->EVENTS_DONE = 0;
|
||||
NRF_CLOCK->EVENTS_CTTO = 0;
|
||||
NRF_CLOCK->CTIV = 0;
|
||||
}
|
||||
|
||||
/* Workaround for Errata 98 "NFCT: Not able to communicate with the peer" found at the Errata document
|
||||
for your device located at https://infocenter.nordicsemi.com/ */
|
||||
if (errata_98()){
|
||||
*(volatile uint32_t *)0x4000568Cul = 0x00038148ul;
|
||||
}
|
||||
|
||||
/* Workaround for Errata 103 "CCM: Wrong reset value of CCM MAXPACKETSIZE" found at the Errata document
|
||||
for your device located at https://infocenter.nordicsemi.com/ */
|
||||
if (errata_103()){
|
||||
NRF_CCM->MAXPACKETSIZE = 0xFBul;
|
||||
}
|
||||
|
||||
/* Workaround for Errata 115 "RAM: RAM content cannot be trusted upon waking up from System ON Idle or System OFF mode" found at the Errata document
|
||||
for your device located at https://infocenter.nordicsemi.com/ */
|
||||
if (errata_115()){
|
||||
*(volatile uint32_t *)0x40000EE4 = (*(volatile uint32_t *)0x40000EE4 & 0xFFFFFFF0) | (*(uint32_t *)0x10000258 & 0x0000000F);
|
||||
}
|
||||
|
||||
/* Workaround for Errata 120 "QSPI: Data read or written is corrupted" found at the Errata document
|
||||
for your device located at https://infocenter.nordicsemi.com/ */
|
||||
if (errata_120()){
|
||||
*(volatile uint32_t *)0x40029640ul = 0x200ul;
|
||||
}
|
||||
|
||||
/* Enable the FPU if the compiler used floating point unit instructions. __FPU_USED is a MACRO defined by the
|
||||
* compiler. Since the FPU consumes energy, remember to disable FPU use in the compiler if floating point unit
|
||||
* operations are not used in your code. */
|
||||
#if (__FPU_USED == 1)
|
||||
SCB->CPACR |= (3UL << 20) | (3UL << 22);
|
||||
__DSB();
|
||||
__ISB();
|
||||
#endif
|
||||
|
||||
/* Configure NFCT pins as GPIOs if NFCT is not to be used in your code. If CONFIG_NFCT_PINS_AS_GPIOS is not defined,
|
||||
two GPIOs (see Product Specification to see which ones) will be reserved for NFC and will not be available as
|
||||
normal GPIOs. */
|
||||
#if defined (CONFIG_NFCT_PINS_AS_GPIOS)
|
||||
if ((NRF_UICR->NFCPINS & UICR_NFCPINS_PROTECT_Msk) == (UICR_NFCPINS_PROTECT_NFC << UICR_NFCPINS_PROTECT_Pos)){
|
||||
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
|
||||
NRF_UICR->NFCPINS &= ~UICR_NFCPINS_PROTECT_Msk;
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
|
||||
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Configure GPIO pads as pPin Reset pin if Pin Reset capabilities desired. If CONFIG_GPIO_AS_PINRESET is not
|
||||
defined, pin reset will not be available. One GPIO (see Product Specification to see which one) will then be
|
||||
reserved for PinReset and not available as normal GPIO. */
|
||||
#if defined (CONFIG_GPIO_AS_PINRESET)
|
||||
if (((NRF_UICR->PSELRESET[0] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos)) ||
|
||||
((NRF_UICR->PSELRESET[1] & UICR_PSELRESET_CONNECT_Msk) != (UICR_PSELRESET_CONNECT_Connected << UICR_PSELRESET_CONNECT_Pos))){
|
||||
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Wen << NVMC_CONFIG_WEN_Pos;
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
|
||||
NRF_UICR->PSELRESET[0] = 18;
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
|
||||
NRF_UICR->PSELRESET[1] = 18;
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
|
||||
NRF_NVMC->CONFIG = NVMC_CONFIG_WEN_Ren << NVMC_CONFIG_WEN_Pos;
|
||||
while (NRF_NVMC->READY == NVMC_READY_READY_Busy){}
|
||||
NVIC_SystemReset();
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Enable SWO trace functionality. If ENABLE_SWO is not defined, SWO pin will be used as GPIO (see Product
|
||||
Specification to see which one). */
|
||||
#if defined (ENABLE_SWO)
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Serial << CLOCK_TRACECONFIG_TRACEMUX_Pos;
|
||||
NRF_P1->PIN_CNF[0] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
#endif
|
||||
|
||||
/* Enable Trace functionality. If ENABLE_TRACE is not defined, TRACE pins will be used as GPIOs (see Product
|
||||
Specification to see which ones). */
|
||||
#if defined (ENABLE_TRACE)
|
||||
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
|
||||
NRF_CLOCK->TRACECONFIG |= CLOCK_TRACECONFIG_TRACEMUX_Parallel << CLOCK_TRACECONFIG_TRACEMUX_Pos;
|
||||
NRF_P0->PIN_CNF[7] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
NRF_P1->PIN_CNF[0] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
NRF_P0->PIN_CNF[12] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
NRF_P0->PIN_CNF[11] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
NRF_P1->PIN_CNF[9] = (GPIO_PIN_CNF_DRIVE_H0H1 << GPIO_PIN_CNF_DRIVE_Pos) | (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos) | (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
#endif
|
||||
|
||||
SystemCoreClockUpdate();
|
||||
}
|
||||
|
||||
|
||||
static bool errata_36(void)
|
||||
{
|
||||
if ((*(uint32_t *)0x10000130ul == 0x8ul) && (*(uint32_t *)0x10000134ul == 0x0ul)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool errata_98(void)
|
||||
{
|
||||
if ((*(uint32_t *)0x10000130ul == 0x8ul) && (*(uint32_t *)0x10000134ul == 0x0ul)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool errata_103(void)
|
||||
{
|
||||
if ((*(uint32_t *)0x10000130ul == 0x8ul) && (*(uint32_t *)0x10000134ul == 0x0ul)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool errata_115(void)
|
||||
{
|
||||
if ((*(uint32_t *)0x10000130ul == 0x8ul) && (*(uint32_t *)0x10000134ul == 0x0ul)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static bool errata_120(void)
|
||||
{
|
||||
if ((*(uint32_t *)0x10000130ul == 0x8ul) && (*(uint32_t *)0x10000134ul == 0x0ul)){
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/*lint --flb "Leave library region" */
|
|
@ -0,0 +1,69 @@
|
|||
/* Copyright (c) 2012 ARM LIMITED
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* * Redistributions of source code must retain the above copyright notice, this
|
||||
* list of conditions and the following disclaimer.
|
||||
*
|
||||
* * Redistributions in binary form must reproduce the above copyright notice,
|
||||
* this list of conditions and the following disclaimer in the documentation
|
||||
* and/or other materials provided with the distribution.
|
||||
*
|
||||
* * Neither the name of ARM nor the names of its contributors may be used to
|
||||
* endorse or promote products derived from this software without specific
|
||||
* prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
|
||||
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
|
||||
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
|
||||
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
|
||||
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
|
||||
* OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SYSTEM_NRF52840_H
|
||||
#define SYSTEM_NRF52840_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
|
||||
extern uint32_t SystemCoreClock; /*!< System Clock Frequency (Core Clock) */
|
||||
|
||||
/**
|
||||
* Initialize the system
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Setup the microcontroller system.
|
||||
* Initialize the System and update the SystemCoreClock variable.
|
||||
*/
|
||||
extern void SystemInit (void);
|
||||
|
||||
/**
|
||||
* Update SystemCoreClock variable
|
||||
*
|
||||
* @param none
|
||||
* @return none
|
||||
*
|
||||
* @brief Updates the SystemCoreClock with current core Clock
|
||||
* retrieved from cpu registers.
|
||||
*/
|
||||
extern void SystemCoreClockUpdate (void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* SYSTEM_NRF52840_H */
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,689 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_COMMON BLE SoftDevice Common
|
||||
@{
|
||||
@defgroup ble_api Events, type definitions and API calls
|
||||
@{
|
||||
|
||||
@brief Module independent events, type definitions and API calls for the BLE SoftDevice.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef BLE_H__
|
||||
#define BLE_H__
|
||||
|
||||
#include "ble_ranges.h"
|
||||
#include "ble_types.h"
|
||||
#include "ble_gap.h"
|
||||
#include "ble_l2cap.h"
|
||||
#include "ble_gatt.h"
|
||||
#include "ble_gattc.h"
|
||||
#include "ble_gatts.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup BLE_COMMON_ENUMERATIONS Enumerations
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief Common API SVC numbers.
|
||||
*/
|
||||
enum BLE_COMMON_SVCS
|
||||
{
|
||||
SD_BLE_ENABLE = BLE_SVC_BASE, /**< Enable and initialize the BLE stack */
|
||||
SD_BLE_EVT_GET, /**< Get an event from the pending events queue. */
|
||||
SD_BLE_TX_PACKET_COUNT_GET, /**< Get the total number of available application transmission packets for a particular connection. */
|
||||
SD_BLE_UUID_VS_ADD, /**< Add a Vendor Specific UUID. */
|
||||
SD_BLE_UUID_DECODE, /**< Decode UUID bytes. */
|
||||
SD_BLE_UUID_ENCODE, /**< Encode UUID bytes. */
|
||||
SD_BLE_VERSION_GET, /**< Get the local version information (company id, Link Layer Version, Link Layer Subversion). */
|
||||
SD_BLE_USER_MEM_REPLY, /**< User Memory Reply. */
|
||||
SD_BLE_OPT_SET, /**< Set a BLE option. */
|
||||
SD_BLE_OPT_GET, /**< Get a BLE option. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief BLE Module Independent Event IDs.
|
||||
*/
|
||||
enum BLE_COMMON_EVTS
|
||||
{
|
||||
BLE_EVT_TX_COMPLETE = BLE_EVT_BASE, /**< Transmission Complete. @ref ble_evt_tx_complete_t */
|
||||
BLE_EVT_USER_MEM_REQUEST, /**< User Memory request. @ref ble_evt_user_mem_request_t */
|
||||
BLE_EVT_USER_MEM_RELEASE, /**< User Memory release. @ref ble_evt_user_mem_release_t */
|
||||
BLE_EVT_DATA_LENGTH_CHANGED /**< Link layer PDU length changed. @ref ble_evt_data_length_changed_t. */
|
||||
};
|
||||
|
||||
/**@brief BLE connection bandwidth types.
|
||||
* Bandwidth types supported by the SoftDevice. The bandwidth type dictates the maximum number of full length packets per connection interval.
|
||||
*/
|
||||
enum BLE_CONN_BWS
|
||||
{
|
||||
BLE_CONN_BW_INVALID = 0, /**< Invalid connection bandwidth. */
|
||||
BLE_CONN_BW_LOW, /**< Low connection bandwidth. */
|
||||
BLE_CONN_BW_MID, /**< Medium connection bandwidth. */
|
||||
BLE_CONN_BW_HIGH /**< High connection bandwidth. */
|
||||
};
|
||||
|
||||
/**@brief Common Option IDs.
|
||||
* IDs that uniquely identify a common option.
|
||||
*/
|
||||
enum BLE_COMMON_OPTS
|
||||
{
|
||||
BLE_COMMON_OPT_CONN_BW = BLE_OPT_BASE, /**< Bandwidth configuration @ref ble_common_opt_conn_bw_t */
|
||||
BLE_COMMON_OPT_PA_LNA, /**< PA and LNA options */
|
||||
BLE_COMMON_OPT_CONN_EVT_EXT, /**< Extended connection events option */
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_COMMON_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/** @brief Required pointer alignment for BLE Events.
|
||||
*/
|
||||
#define BLE_EVT_PTR_ALIGNMENT 4
|
||||
|
||||
/** @brief Leaves the maximum of the two arguments.
|
||||
*/
|
||||
#define BLE_MAX(a, b) ((a) < (b) ? (b) : (a))
|
||||
|
||||
/** @brief Maximum possible length for BLE Events.
|
||||
* @note Value of @ref ble_gatt_enable_params_t::att_mtu shall be used as a parameter.
|
||||
* If that value is set to 0 then @ref BLE_GATT_MTU_SIZE_DEFAULT must be used instead.
|
||||
*/
|
||||
#define BLE_EVT_LEN_MAX(ATT_MTU) (BLE_MAX( \
|
||||
sizeof(ble_evt_t), \
|
||||
BLE_MAX( \
|
||||
offsetof(ble_evt_t, evt.gattc_evt.params.rel_disc_rsp.includes) + ((ATT_MTU) - 2) / 6 * sizeof(ble_gattc_include_t), \
|
||||
offsetof(ble_evt_t, evt.gattc_evt.params.attr_info_disc_rsp.info.attr_info16) + ((ATT_MTU) - 2) / 4 * sizeof(ble_gattc_attr_info16_t) \
|
||||
) \
|
||||
))
|
||||
|
||||
/** @defgroup BLE_USER_MEM_TYPES User Memory Types
|
||||
* @{ */
|
||||
#define BLE_USER_MEM_TYPE_INVALID 0x00 /**< Invalid User Memory Types. */
|
||||
#define BLE_USER_MEM_TYPE_GATTS_QUEUED_WRITES 0x01 /**< User Memory for GATTS queued writes. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_UUID_VS_COUNTS Vendor Specific UUID counts
|
||||
* @{
|
||||
*/
|
||||
#define BLE_UUID_VS_COUNT_MIN 1 /**< Minimum VS UUID count. */
|
||||
#define BLE_UUID_VS_COUNT_DEFAULT 0 /**< Use the default VS UUID count (10 for this version of the SoftDevice). */
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_COMMON_STRUCTURES Structures
|
||||
* @{ */
|
||||
|
||||
/**@brief User Memory Block. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t *p_mem; /**< Pointer to the start of the user memory block. */
|
||||
uint16_t len; /**< Length in bytes of the user memory block. */
|
||||
} ble_user_mem_block_t;
|
||||
|
||||
/**
|
||||
* @brief Event structure for @ref BLE_EVT_TX_COMPLETE.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t count; /**< Number of packets transmitted. */
|
||||
} ble_evt_tx_complete_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_EVT_USER_MEM_REQUEST. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< User memory type, see @ref BLE_USER_MEM_TYPES. */
|
||||
} ble_evt_user_mem_request_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_EVT_USER_MEM_RELEASE. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< User memory type, see @ref BLE_USER_MEM_TYPES. */
|
||||
ble_user_mem_block_t mem_block; /**< User memory block */
|
||||
} ble_evt_user_mem_release_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_EVT_DATA_LENGTH_CHANGED. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t max_tx_octets; /**< The maximum number of payload octets in a Link Layer Data Channel PDU that the local Controller will send. Range: 27-251 */
|
||||
uint16_t max_tx_time; /**< The maximum time (in microseconds) that the local Controller will take to send a Link Layer Data Channel PDU. Range: 328-2120 */
|
||||
uint16_t max_rx_octets; /**< The maximum number of payload octets in a Link Layer Data Channel PDU that the local controller expects to receive. Range: 27-251 */
|
||||
uint16_t max_rx_time; /**< The maximum time (in microseconds) that the local Controller expects to take to receive a Link Layer Data Channel PDU. Range: 328-2120 */
|
||||
} ble_evt_data_length_changed_t;
|
||||
|
||||
/**@brief Event structure for events not associated with a specific function module. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t conn_handle; /**< Connection Handle on which this event occurred. */
|
||||
union
|
||||
{
|
||||
ble_evt_tx_complete_t tx_complete; /**< Transmission Complete. */
|
||||
ble_evt_user_mem_request_t user_mem_request; /**< User Memory Request Event Parameters. */
|
||||
ble_evt_user_mem_release_t user_mem_release; /**< User Memory Release Event Parameters. */
|
||||
ble_evt_data_length_changed_t data_length_changed; /**< Data Length Changed Event Parameters. */
|
||||
} params; /**< Event parameter union. */
|
||||
} ble_common_evt_t;
|
||||
|
||||
/**@brief BLE Event header. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t evt_id; /**< Value from a BLE_<module>_EVT series. */
|
||||
uint16_t evt_len; /**< Length in octets including this header. */
|
||||
} ble_evt_hdr_t;
|
||||
|
||||
/**@brief Common BLE Event type, wrapping the module specific event reports. */
|
||||
typedef struct
|
||||
{
|
||||
ble_evt_hdr_t header; /**< Event header. */
|
||||
union
|
||||
{
|
||||
ble_common_evt_t common_evt; /**< Common Event, evt_id in BLE_EVT_* series. */
|
||||
ble_gap_evt_t gap_evt; /**< GAP originated event, evt_id in BLE_GAP_EVT_* series. */
|
||||
ble_l2cap_evt_t l2cap_evt; /**< L2CAP originated event, evt_id in BLE_L2CAP_EVT* series. */
|
||||
ble_gattc_evt_t gattc_evt; /**< GATT client originated event, evt_id in BLE_GATTC_EVT* series. */
|
||||
ble_gatts_evt_t gatts_evt; /**< GATT server originated event, evt_id in BLE_GATTS_EVT* series. */
|
||||
} evt; /**< Event union. */
|
||||
} ble_evt_t;
|
||||
|
||||
|
||||
/**
|
||||
* @brief Version Information.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t version_number; /**< Link Layer Version number for BT 4.1 spec is 7 (https://www.bluetooth.org/en-us/specification/assigned-numbers/link-layer). */
|
||||
uint16_t company_id; /**< Company ID, Nordic Semiconductor's company ID is 89 (0x0059) (https://www.bluetooth.org/apps/content/Default.aspx?doc_id=49708). */
|
||||
uint16_t subversion_number; /**< Link Layer Sub Version number, corresponds to the SoftDevice Config ID or Firmware ID (FWID). */
|
||||
} ble_version_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration parameters for the PA and LNA.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t enable :1; /**< Enable toggling for this amplifier */
|
||||
uint8_t active_high :1; /**< Set the pin to be active high */
|
||||
uint8_t gpio_pin :6; /**< The GPIO pin to toggle for this amplifier */
|
||||
} ble_pa_lna_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief PA & LNA GPIO toggle configuration
|
||||
*
|
||||
* This option configures the SoftDevice to toggle pins when the radio is active for use with a power amplifier and/or
|
||||
* a low noise amplifier.
|
||||
*
|
||||
* Toggling the pins is achieved by using two PPI channels and a GPIOTE channel. The hardware channel IDs are provided
|
||||
* by the application and should be regarded as reserved as long as any PA/LNA toggling is enabled.
|
||||
*
|
||||
* @note @ref sd_ble_opt_get is not supported for this option.
|
||||
* @note This feature is only supported for nRF52, on nRF51 @ref NRF_ERROR_NOT_SUPPORTED will always be returned.
|
||||
* @note Setting this option while the radio is in use (i.e. any of the roles are active) may have undefined consequences
|
||||
* and must be avoided by the application.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ble_pa_lna_cfg_t pa_cfg; /**< Power Amplifier configuration */
|
||||
ble_pa_lna_cfg_t lna_cfg; /**< Low Noise Amplifier configuration */
|
||||
|
||||
uint8_t ppi_ch_id_set; /**< PPI channel used for radio pin setting */
|
||||
uint8_t ppi_ch_id_clr; /**< PPI channel used for radio pin clearing */
|
||||
uint8_t gpiote_ch_id; /**< GPIOTE channel used for radio pin toggling */
|
||||
} ble_common_opt_pa_lna_t;
|
||||
|
||||
/**
|
||||
* @brief BLE connection bandwidth configuration parameters
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t conn_bw_tx; /**< Connection bandwidth configuration for transmission, see @ref BLE_CONN_BWS.*/
|
||||
uint8_t conn_bw_rx; /**< Connection bandwidth configuration for reception, see @ref BLE_CONN_BWS.*/
|
||||
} ble_conn_bw_t;
|
||||
|
||||
/**@brief BLE connection specific bandwidth configuration parameters.
|
||||
*
|
||||
* This can be used with @ref sd_ble_opt_set to set the bandwidth configuration to be used when creating connections.
|
||||
*
|
||||
* Call @ref sd_ble_opt_set with this option prior to calling @ref sd_ble_gap_adv_start or @ref sd_ble_gap_connect.
|
||||
*
|
||||
* The bandwidth configurations set via @ref sd_ble_opt_set are maintained separately for central and peripheral
|
||||
* connections. The given configurations are used for all future connections of the role indicated in this structure
|
||||
* unless they are changed by subsequent @ref sd_ble_opt_set calls.
|
||||
*
|
||||
* @note When this option is not used, the SoftDevice will use the default options:
|
||||
* - @ref BLE_CONN_BW_HIGH for @ref BLE_GAP_ROLE_PERIPH connections (both transmission and reception).
|
||||
* - @ref BLE_CONN_BW_MID for @ref BLE_GAP_ROLE_CENTRAL connections (both transmisison and reception).
|
||||
* This option allows the application to selectively override these defaults for each role.
|
||||
*
|
||||
* @note The global memory pool configuration can be set with the @ref ble_conn_bw_counts_t configuration parameter, which
|
||||
* is provided to @ref sd_ble_enable.
|
||||
*
|
||||
* @note @ref sd_ble_opt_get is not supported for this option.
|
||||
* @note Please refer to SoftDevice Specification for more information on bandwidth configuration.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_COMMON_CONF_BW}
|
||||
* @endmscs
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Set successfully.
|
||||
* @retval ::BLE_ERROR_INVALID_ROLE The role is invalid.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid bandwidth configuration parameters.
|
||||
* @retval ::NRF_ERROR_NOT_SUPPORTED If the combination of role and bandwidth configuration is not supported.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t role; /**< BLE role of the connection, see @ref BLE_GAP_ROLES. */
|
||||
ble_conn_bw_t conn_bw; /**< Bandwidth configuration parameters. */
|
||||
} ble_common_opt_conn_bw_t;
|
||||
|
||||
/**
|
||||
* @brief Configuration of extended BLE connection events.
|
||||
*
|
||||
* When enabled the SoftDevice will dynamically extend the connection event when possible.
|
||||
*
|
||||
* The connection event length is controlled by the bandwidth configuration as set by @ref ble_common_opt_conn_bw_t.
|
||||
* The connection event can be extended if there is time to send another packet pair before the start of the next connection interval,
|
||||
* and if there are no conflicts with other BLE roles requesting radio time.
|
||||
*
|
||||
* @note @ref sd_ble_opt_get is not supported for this option.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t enable : 1; /**< Enable extended BLE connection events, disabled by default. */
|
||||
} ble_common_opt_conn_evt_ext_t;
|
||||
|
||||
/**@brief Option structure for common options. */
|
||||
typedef union
|
||||
{
|
||||
ble_common_opt_conn_bw_t conn_bw; /**< Parameters for the connection bandwidth option. */
|
||||
ble_common_opt_pa_lna_t pa_lna; /**< Parameters for controlling PA and LNA pin toggling. */
|
||||
ble_common_opt_conn_evt_ext_t conn_evt_ext; /**< Parameters for enabling extended connection events. */
|
||||
} ble_common_opt_t;
|
||||
|
||||
/**@brief Common BLE Option type, wrapping the module specific options. */
|
||||
typedef union
|
||||
{
|
||||
ble_common_opt_t common_opt; /**< COMMON options, opt_id in @ref BLE_COMMON_OPTS series. */
|
||||
ble_gap_opt_t gap_opt; /**< GAP option, opt_id in @ref BLE_GAP_OPTS series. */
|
||||
} ble_opt_t;
|
||||
|
||||
/**
|
||||
* @brief BLE bandwidth count parameters
|
||||
*
|
||||
* These parameters are used to configure the memory pools allocated within the SoftDevice for application packets
|
||||
* (both transmission and reception) for all connections.
|
||||
*
|
||||
* @note The sum of all three counts must add up to the sum of @ref ble_gap_enable_params_t::central_conn_count and
|
||||
* @ref ble_gap_enable_params_t::periph_conn_count in @ref ble_gap_enable_params_t.
|
||||
*/
|
||||
typedef struct {
|
||||
uint8_t high_count; /**< Total number of high bandwidth TX or RX memory pools available to the application at runtime for all active connections. */
|
||||
uint8_t mid_count; /**< Total number of medium bandwidth TX or RX memory pools available to the application at runtime for all active connections. */
|
||||
uint8_t low_count; /**< Total number of low bandwidth TX or RX memory pools available to the application at runtime for all active connections. */
|
||||
} ble_conn_bw_count_t;
|
||||
|
||||
/**
|
||||
* @brief BLE bandwidth global memory pool configuration parameters
|
||||
*
|
||||
* These configuration parameters are used to set the amount of memory dedicated to application packets for
|
||||
* all connections. The application should specify the most demanding configuration for the intended use.
|
||||
*
|
||||
* Please refer to the SoftDevice Specification for more information on bandwidth configuration.
|
||||
*
|
||||
* @note Each connection created at runtime requires both a TX and an RX memory pool. By the use of these configuration
|
||||
* parameters, the application can decide the size and total number of the global memory pools that will be later
|
||||
* available for connection creation.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_COMMON_CONF_BW}
|
||||
* @endmscs
|
||||
*
|
||||
*/
|
||||
typedef struct {
|
||||
ble_conn_bw_count_t tx_counts; /**< Global memory pool configuration for transmission.*/
|
||||
ble_conn_bw_count_t rx_counts; /**< Global memory pool configuration for reception.*/
|
||||
} ble_conn_bw_counts_t;
|
||||
|
||||
/**
|
||||
* @brief BLE Common Initialization parameters.
|
||||
*
|
||||
* @note If @ref p_conn_bw_counts is NULL the SoftDevice will assume default bandwidth configuration for all connections.
|
||||
* To fit a custom bandwidth configuration requirement, the application developer may have to specify a custom memory
|
||||
* pool configuration here. See @ref ble_common_opt_conn_bw_t for bandwidth configuration of individual connections.
|
||||
* Please refer to the SoftDevice Specification for more information on bandwidth configuration.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t vs_uuid_count; /**< Maximum number of 128-bit, Vendor Specific UUID bases to allocate. */
|
||||
ble_conn_bw_counts_t *p_conn_bw_counts; /**< Bandwidth configuration parameters or NULL for defaults. */
|
||||
} ble_common_enable_params_t;
|
||||
|
||||
/**
|
||||
* @brief BLE Initialization parameters.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ble_common_enable_params_t common_enable_params; /**< Common init parameters @ref ble_common_enable_params_t. */
|
||||
ble_gap_enable_params_t gap_enable_params; /**< GAP init parameters @ref ble_gap_enable_params_t. */
|
||||
ble_gatt_enable_params_t gatt_enable_params; /**< GATT init parameters @ref ble_gatt_enable_params_t. */
|
||||
ble_gatts_enable_params_t gatts_enable_params; /**< GATTS init parameters @ref ble_gatts_enable_params_t. */
|
||||
} ble_enable_params_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_COMMON_FUNCTIONS Functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Enable the BLE stack
|
||||
*
|
||||
* @param[in, out] p_ble_enable_params Pointer to ble_enable_params_t
|
||||
* @param[in, out] p_app_ram_base Pointer to a variable containing the start address of the application RAM region
|
||||
* (APP_RAM_BASE). On return, this will contain the minimum start address of the application RAM region required by the
|
||||
* SoftDevice for this configuration. Calling @ref sd_ble_enable() with *p_app_ram_base set to 0 can be used during
|
||||
* development to find out how much memory a specific configuration will need.
|
||||
*
|
||||
* @note The memory requirement for a specific configuration will not increase between SoftDevices with the same major
|
||||
* version number.
|
||||
*
|
||||
* @note At runtime the IC's RAM is split into 2 regions: The SoftDevice RAM region is located between 0x20000000 and
|
||||
* APP_RAM_BASE-1 and the application's RAM region is located between APP_RAM_BASE and the start of the call stack.
|
||||
*
|
||||
* @details This call initializes the BLE stack, no other BLE related function can be called before this one.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_COMMON_ENABLE}
|
||||
* @endmscs
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The BLE stack has been initialized successfully.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE The BLE stack had already been initialized and cannot be reinitialized.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_LENGTH One or more of the following is true:
|
||||
* - The specified Attribute Table size is too small.
|
||||
* The minimum acceptable size is defined by @ref BLE_GATTS_ATTR_TAB_SIZE_MIN.
|
||||
* - The specified Attribute Table size is not a multiple of 4.
|
||||
* - The device name length is invalid (must be between 0 and @ref BLE_GAP_DEVNAME_MAX_LEN).
|
||||
* - The device name length is too long for the given Attribute Table.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM One or more of the following is true:
|
||||
* - Incorrectly configured VS UUID count.
|
||||
* - Invalid connection count parameters.
|
||||
* - Invalid device name location (vloc).
|
||||
* - Invalid device name security mode.
|
||||
* - Invalid maximum ATT_MTU size, see @ref ble_gatt_enable_params_t::att_mtu.
|
||||
* @retval ::NRF_ERROR_NOT_SUPPORTED Device name security mode is not supported.
|
||||
* @retval ::NRF_ERROR_NO_MEM The amount of memory assigned to the SoftDevice by *p_app_ram_base is not
|
||||
* large enough to fit this configuration's memory requirement. Check *p_app_ram_base
|
||||
* and set the start address of the application RAM region accordingly.
|
||||
* @retval ::NRF_ERROR_CONN_COUNT The requested number of connections exceeds the maximum supported by the SoftDevice.
|
||||
* Please refer to the SoftDevice Specification for more information on role configuration.
|
||||
*/
|
||||
SVCALL(SD_BLE_ENABLE, uint32_t, sd_ble_enable(ble_enable_params_t * p_ble_enable_params, uint32_t * p_app_ram_base));
|
||||
|
||||
/**@brief Get an event from the pending events queue.
|
||||
*
|
||||
* @param[out] p_dest Pointer to buffer to be filled in with an event, or NULL to retrieve the event length.
|
||||
* This buffer <b>must be aligned to the extend defined by @ref BLE_EVT_PTR_ALIGNMENT</b>.
|
||||
* The buffer should be interpreted as a @ref ble_evt_t struct.
|
||||
* @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 signaled that
|
||||
* an event is available from the BLE stack by the triggering of the SD_EVT_IRQn interrupt.
|
||||
* 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 BLE 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.
|
||||
* The maximum possible event length is defined by @ref BLE_EVT_LEN_MAX. The application may also "peek" the event length
|
||||
* by providing p_dest as a NULL pointer and inspecting the value of *p_len upon return:
|
||||
*
|
||||
* \code
|
||||
* uint16_t len;
|
||||
* errcode = sd_ble_evt_get(NULL, &len);
|
||||
* \endcode
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_COMMON_IRQ_EVT_MSC}
|
||||
* @mmsc{@ref BLE_COMMON_THREAD_EVT_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Event pulled and stored into the supplied buffer.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid or not sufficiently aligned pointer supplied.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND No events ready to be pulled.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE Event ready but could not fit into the supplied buffer.
|
||||
*/
|
||||
SVCALL(SD_BLE_EVT_GET, uint32_t, sd_ble_evt_get(uint8_t *p_dest, uint16_t *p_len));
|
||||
|
||||
|
||||
/**@brief Get the total number of available guaranteed application transmission packets for a particular connection.
|
||||
*
|
||||
* @details This call allows the application to obtain the total number of guaranteed application transmission packets
|
||||
* available for a connection. Please note that this does not return the number of free packets, but rather the total
|
||||
* amount of them for that particular connection. The application has two options to handle transmitting application packets:
|
||||
* - Use a simple arithmetic calculation: after connection creation time the application should use this function to
|
||||
* find out the total amount of guaranteed packets available to it and store it in a variable.
|
||||
* Every time a packet is successfully queued for a transmission on this connection 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
|
||||
* with the conn_handle matching the particular connection is received by the application, it should retrieve the count
|
||||
* field in such event and add that number to the same variable storing the number of available guaranteed packets. This
|
||||
* mechanism allows the application to be aware at any time of the number of guaranteed application packets available for
|
||||
* each of the active connections, 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.
|
||||
* The application can still pursue transmissions when the number of guaranteed application packets available is smaller
|
||||
* than or equal to zero, but successful queuing of the tranmsission is not guaranteed.
|
||||
* - Choose to simply not keep track of available packets at all, and instead handle the @ref BLE_ERROR_NO_TX_PACKETS 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 packet depending on the parameters supplied to them can be found below:
|
||||
* - @ref sd_ble_gattc_write (write without response only)
|
||||
* - @ref sd_ble_gatts_hvx (notifications only)
|
||||
* - @ref sd_ble_l2cap_tx (all packets)
|
||||
*
|
||||
* @param[in] conn_handle Connection handle.
|
||||
* @param[out] p_count Pointer to a uint8_t which will contain the number of application transmission packets upon
|
||||
* successful return.
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_COMMON_APP_BUFF_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Number of application transmission packets retrieved successfully.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
*/
|
||||
SVCALL(SD_BLE_TX_PACKET_COUNT_GET, uint32_t, sd_ble_tx_packet_count_get(uint16_t conn_handle, uint8_t *p_count));
|
||||
|
||||
|
||||
/**@brief Add a Vendor Specific base UUID.
|
||||
*
|
||||
* @details This call enables the application to add a vendor specific base UUID to the BLE stack's table, for later
|
||||
* use with 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. This is accomplished 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
|
||||
* the 16-bit uuid field in @ref ble_uuid_t.
|
||||
*
|
||||
* @note If a UUID is already present in the BLE stack's internal table, the corresponding index will be returned in
|
||||
* p_uuid_type along with an NRF_SUCCESS error code.
|
||||
*
|
||||
* @param[in] p_vs_uuid Pointer to a 16-octet (128-bit) little endian Vendor Specific UUID disregarding
|
||||
* bytes 12 and 13.
|
||||
* @param[out] p_uuid_type Pointer to a uint8_t where the type field in @ref ble_uuid_t corresponding to this UUID will be stored.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully added the Vendor Specific UUID.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR If p_vs_uuid or p_uuid_type is NULL or invalid.
|
||||
* @retval ::NRF_ERROR_NO_MEM If there are no more free slots for VS UUIDs.
|
||||
*/
|
||||
SVCALL(SD_BLE_UUID_VS_ADD, uint32_t, sd_ble_uuid_vs_add(ble_uuid128_t const *p_vs_uuid, uint8_t *p_uuid_type));
|
||||
|
||||
|
||||
/** @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 populated 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.
|
||||
*
|
||||
* @param[in] uuid_le_len Length in bytes of the buffer pointed to by p_uuid_le (must be 2 or 16 bytes).
|
||||
* @param[in] p_uuid_le Pointer pointing to little endian raw UUID bytes.
|
||||
* @param[out] p_uuid Pointer to a @ref ble_uuid_t structure to be filled in.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully decoded into the @ref ble_uuid_t structure.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_LENGTH Invalid UUID length.
|
||||
* @retval ::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 *p_uuid_le, ble_uuid_t *p_uuid));
|
||||
|
||||
|
||||
/** @brief Encode a @ref ble_uuid_t structure into little endian raw UUID bytes (16-bit or 128-bit).
|
||||
*
|
||||
* @note The pointer to the destination buffer p_uuid_le may be NULL, in which case only the validity and size of p_uuid is computed.
|
||||
*
|
||||
* @param[in] p_uuid Pointer to a @ref ble_uuid_t structure that will be encoded into bytes.
|
||||
* @param[out] p_uuid_le_len Pointer to a uint8_t that will be filled with the encoded length (2 or 16 bytes).
|
||||
* @param[out] p_uuid_le Pointer to a buffer where the little endian raw UUID bytes (2 or 16) will be stored.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully encoded into the buffer.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid UUID type.
|
||||
*/
|
||||
SVCALL(SD_BLE_UUID_ENCODE, uint32_t, sd_ble_uuid_encode(ble_uuid_t const *p_uuid, uint8_t *p_uuid_le_len, uint8_t *p_uuid_le));
|
||||
|
||||
|
||||
/**@brief Get Version Information.
|
||||
*
|
||||
* @details This call allows the application to get the BLE stack version information.
|
||||
*
|
||||
* @param[out] p_version Pointer to a ble_version_t structure to be filled in.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Version information stored successfully.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_BUSY The BLE stack is busy (typically doing a locally-initiated disconnection procedure).
|
||||
*/
|
||||
SVCALL(SD_BLE_VERSION_GET, uint32_t, sd_ble_version_get(ble_version_t *p_version));
|
||||
|
||||
|
||||
/**@brief Provide a user memory block.
|
||||
*
|
||||
* @note This call can only be used as a response to a @ref BLE_EVT_USER_MEM_REQUEST event issued to the application.
|
||||
*
|
||||
* @param[in] conn_handle Connection handle.
|
||||
* @param[in,out] p_block Pointer to a user memory block structure.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_PEER_CANCEL_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_AUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_AUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_NOAUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully queued a response to the peer.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection state or no execute write request pending.
|
||||
* @retval ::NRF_ERROR_BUSY The BLE stack is busy. Retry at later time.
|
||||
*/
|
||||
SVCALL(SD_BLE_USER_MEM_REPLY, uint32_t, sd_ble_user_mem_reply(uint16_t conn_handle, ble_user_mem_block_t const *p_block));
|
||||
|
||||
/**@brief Set a BLE option.
|
||||
*
|
||||
* @details This call allows the application to set the value of an option.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GAP_PERIPH_BONDING_STATIC_PK_MSC}
|
||||
* @mmsc{@ref BLE_COMMON_CONF_BW}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] opt_id Option ID, see @ref BLE_COMMON_OPTS and @ref BLE_GAP_OPTS.
|
||||
* @param[in] p_opt Pointer to a ble_opt_t structure containing the option value.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Option set successfully.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Unable to set the parameter at this time.
|
||||
* @retval ::NRF_ERROR_BUSY The BLE stack is busy or the previous procedure has not completed.
|
||||
*/
|
||||
SVCALL(SD_BLE_OPT_SET, uint32_t, sd_ble_opt_set(uint32_t opt_id, ble_opt_t const *p_opt));
|
||||
|
||||
|
||||
/**@brief Get a BLE option.
|
||||
*
|
||||
* @details This call allows the application to retrieve the value of an option.
|
||||
*
|
||||
* @param[in] opt_id Option ID, see @ref BLE_COMMON_OPTS and @ref BLE_GAP_OPTS.
|
||||
* @param[out] p_opt Pointer to a ble_opt_t structure to be filled in.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Option retrieved successfully.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, check parameter limits and constraints.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Unable to retrieve the parameter at this time.
|
||||
* @retval ::NRF_ERROR_BUSY The BLE stack is busy or the previous procedure has not completed.
|
||||
* @retval ::NRF_ERROR_NOT_SUPPORTED This option is not supported.
|
||||
*
|
||||
*/
|
||||
SVCALL(SD_BLE_OPT_GET, uint32_t, sd_ble_opt_get(uint32_t opt_id, ble_opt_t *p_opt));
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* BLE_H__ */
|
||||
|
||||
/**
|
||||
@}
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,93 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_COMMON
|
||||
@{
|
||||
@addtogroup nrf_error
|
||||
@{
|
||||
@ingroup BLE_COMMON
|
||||
@}
|
||||
|
||||
@defgroup ble_err General error codes
|
||||
@{
|
||||
|
||||
@brief General error code definitions for the BLE API.
|
||||
|
||||
@ingroup BLE_COMMON
|
||||
*/
|
||||
#ifndef NRF_BLE_ERR_H__
|
||||
#define NRF_BLE_ERR_H__
|
||||
|
||||
#include "nrf_error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* @defgroup BLE_ERRORS Error Codes
|
||||
* @{ */
|
||||
#define BLE_ERROR_NOT_ENABLED (NRF_ERROR_STK_BASE_NUM+0x001) /**< @ref sd_ble_enable has not been called. */
|
||||
#define BLE_ERROR_INVALID_CONN_HANDLE (NRF_ERROR_STK_BASE_NUM+0x002) /**< Invalid connection handle. */
|
||||
#define BLE_ERROR_INVALID_ATTR_HANDLE (NRF_ERROR_STK_BASE_NUM+0x003) /**< Invalid attribute handle. */
|
||||
#define BLE_ERROR_NO_TX_PACKETS (NRF_ERROR_STK_BASE_NUM+0x004) /**< Not enough application packets available on this connection. */
|
||||
#define BLE_ERROR_INVALID_ROLE (NRF_ERROR_STK_BASE_NUM+0x005) /**< Invalid role. */
|
||||
#define BLE_ERROR_BLOCKED_BY_OTHER_LINKS (NRF_ERROR_STK_BASE_NUM+0x006) /**< The attempt to change link settings failed due to the scheduling of other links. */
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @defgroup BLE_ERROR_SUBRANGES Module specific error code subranges
|
||||
* @brief Assignment of subranges for module specific error codes.
|
||||
* @note For specific error codes, see ble_<module>.h or ble_error_<module>.h.
|
||||
* @{ */
|
||||
#define NRF_L2CAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x100) /**< L2CAP specific errors. */
|
||||
#define NRF_GAP_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x200) /**< GAP specific errors. */
|
||||
#define NRF_GATTC_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x300) /**< GATT client specific errors. */
|
||||
#define NRF_GATTS_ERR_BASE (NRF_ERROR_STK_BASE_NUM+0x400) /**< GATT server specific errors. */
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
/**
|
||||
@}
|
||||
@}
|
||||
*/
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,222 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_GATT Generic Attribute Profile (GATT) Common
|
||||
@{
|
||||
@brief Common definitions and prototypes for the GATT interfaces.
|
||||
*/
|
||||
|
||||
#ifndef BLE_GATT_H__
|
||||
#define BLE_GATT_H__
|
||||
|
||||
#include "ble_types.h"
|
||||
#include "ble_ranges.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup BLE_GATT_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/** @brief Default MTU size, in bytes. */
|
||||
#define BLE_GATT_MTU_SIZE_DEFAULT 23
|
||||
|
||||
/**@brief Invalid Attribute Handle. */
|
||||
#define BLE_GATT_HANDLE_INVALID 0x0000
|
||||
|
||||
/**@brief First Attribute Handle. */
|
||||
#define BLE_GATT_HANDLE_START 0x0001
|
||||
|
||||
/**@brief Last Attribute Handle. */
|
||||
#define BLE_GATT_HANDLE_END 0xFFFF
|
||||
|
||||
/** @defgroup BLE_GATT_TIMEOUT_SOURCES GATT Timeout sources
|
||||
* @{ */
|
||||
#define BLE_GATT_TIMEOUT_SRC_PROTOCOL 0x00 /**< ATT Protocol timeout. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATT_WRITE_OPS GATT Write operations
|
||||
* @{ */
|
||||
#define BLE_GATT_OP_INVALID 0x00 /**< Invalid Operation. */
|
||||
#define BLE_GATT_OP_WRITE_REQ 0x01 /**< Write Request. */
|
||||
#define BLE_GATT_OP_WRITE_CMD 0x02 /**< Write Command. */
|
||||
#define BLE_GATT_OP_SIGN_WRITE_CMD 0x03 /**< Signed Write Command. */
|
||||
#define BLE_GATT_OP_PREP_WRITE_REQ 0x04 /**< Prepare Write Request. */
|
||||
#define BLE_GATT_OP_EXEC_WRITE_REQ 0x05 /**< Execute Write Request. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATT_EXEC_WRITE_FLAGS GATT Execute Write flags
|
||||
* @{ */
|
||||
#define BLE_GATT_EXEC_WRITE_FLAG_PREPARED_CANCEL 0x00 /**< Cancel prepared write. */
|
||||
#define BLE_GATT_EXEC_WRITE_FLAG_PREPARED_WRITE 0x01 /**< Execute prepared write. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATT_HVX_TYPES GATT Handle Value operations
|
||||
* @{ */
|
||||
#define BLE_GATT_HVX_INVALID 0x00 /**< Invalid Operation. */
|
||||
#define BLE_GATT_HVX_NOTIFICATION 0x01 /**< Handle Value Notification. */
|
||||
#define BLE_GATT_HVX_INDICATION 0x02 /**< Handle Value Indication. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATT_STATUS_CODES GATT Status Codes
|
||||
* @{ */
|
||||
#define BLE_GATT_STATUS_SUCCESS 0x0000 /**< Success. */
|
||||
#define BLE_GATT_STATUS_UNKNOWN 0x0001 /**< Unknown or not applicable status. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INVALID 0x0100 /**< ATT Error: Invalid Error Code. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INVALID_HANDLE 0x0101 /**< ATT Error: Invalid Attribute Handle. */
|
||||
#define BLE_GATT_STATUS_ATTERR_READ_NOT_PERMITTED 0x0102 /**< ATT Error: Read not permitted. */
|
||||
#define BLE_GATT_STATUS_ATTERR_WRITE_NOT_PERMITTED 0x0103 /**< ATT Error: Write not permitted. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INVALID_PDU 0x0104 /**< ATT Error: Used in ATT as Invalid PDU. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHENTICATION 0x0105 /**< ATT Error: Authenticated link required. */
|
||||
#define BLE_GATT_STATUS_ATTERR_REQUEST_NOT_SUPPORTED 0x0106 /**< ATT Error: Used in ATT as Request Not Supported. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INVALID_OFFSET 0x0107 /**< ATT Error: Offset specified was past the end of the attribute. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INSUF_AUTHORIZATION 0x0108 /**< ATT Error: Used in ATT as Insufficient Authorisation. */
|
||||
#define BLE_GATT_STATUS_ATTERR_PREPARE_QUEUE_FULL 0x0109 /**< ATT Error: Used in ATT as Prepare Queue Full. */
|
||||
#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_FOUND 0x010A /**< ATT Error: Used in ATT as Attribute not found. */
|
||||
#define BLE_GATT_STATUS_ATTERR_ATTRIBUTE_NOT_LONG 0x010B /**< ATT Error: Attribute cannot be read or written using read/write blob requests. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INSUF_ENC_KEY_SIZE 0x010C /**< ATT Error: Encryption key size used is insufficient. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INVALID_ATT_VAL_LENGTH 0x010D /**< ATT Error: Invalid value size. */
|
||||
#define BLE_GATT_STATUS_ATTERR_UNLIKELY_ERROR 0x010E /**< ATT Error: Very unlikely error. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INSUF_ENCRYPTION 0x010F /**< ATT Error: Encrypted link required. */
|
||||
#define BLE_GATT_STATUS_ATTERR_UNSUPPORTED_GROUP_TYPE 0x0110 /**< ATT Error: Attribute type is not a supported grouping attribute. */
|
||||
#define BLE_GATT_STATUS_ATTERR_INSUF_RESOURCES 0x0111 /**< ATT Error: Encrypted link required. */
|
||||
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_BEGIN 0x0112 /**< ATT Error: Reserved for Future Use range #1 begin. */
|
||||
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE1_END 0x017F /**< ATT Error: Reserved for Future Use range #1 end. */
|
||||
#define BLE_GATT_STATUS_ATTERR_APP_BEGIN 0x0180 /**< ATT Error: Application range begin. */
|
||||
#define BLE_GATT_STATUS_ATTERR_APP_END 0x019F /**< ATT Error: Application range end. */
|
||||
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_BEGIN 0x01A0 /**< ATT Error: Reserved for Future Use range #2 begin. */
|
||||
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE2_END 0x01DF /**< ATT Error: Reserved for Future Use range #2 end. */
|
||||
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_BEGIN 0x01E0 /**< ATT Error: Reserved for Future Use range #3 begin. */
|
||||
#define BLE_GATT_STATUS_ATTERR_RFU_RANGE3_END 0x01FC /**< ATT Error: Reserved for Future Use range #3 end. */
|
||||
#define BLE_GATT_STATUS_ATTERR_CPS_CCCD_CONFIG_ERROR 0x01FD /**< ATT Common Profile and Service Error: Client Characteristic Configuration Descriptor improperly configured. */
|
||||
#define BLE_GATT_STATUS_ATTERR_CPS_PROC_ALR_IN_PROG 0x01FE /**< ATT Common Profile and Service Error: Procedure Already in Progress. */
|
||||
#define BLE_GATT_STATUS_ATTERR_CPS_OUT_OF_RANGE 0x01FF /**< ATT Common Profile and Service Error: Out Of Range. */
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @defgroup BLE_GATT_CPF_FORMATS Characteristic Presentation Formats
|
||||
* @note Found at http://developer.bluetooth.org/gatt/descriptors/Pages/DescriptorViewer.aspx?u=org.bluetooth.descriptor.gatt.characteristic_presentation_format.xml
|
||||
* @{ */
|
||||
#define BLE_GATT_CPF_FORMAT_RFU 0x00 /**< Reserved For Future Use. */
|
||||
#define BLE_GATT_CPF_FORMAT_BOOLEAN 0x01 /**< Boolean. */
|
||||
#define BLE_GATT_CPF_FORMAT_2BIT 0x02 /**< Unsigned 2-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_NIBBLE 0x03 /**< Unsigned 4-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT8 0x04 /**< Unsigned 8-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT12 0x05 /**< Unsigned 12-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT16 0x06 /**< Unsigned 16-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT24 0x07 /**< Unsigned 24-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT32 0x08 /**< Unsigned 32-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT48 0x09 /**< Unsigned 48-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT64 0x0A /**< Unsigned 64-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_UINT128 0x0B /**< Unsigned 128-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT8 0x0C /**< Signed 2-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT12 0x0D /**< Signed 12-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT16 0x0E /**< Signed 16-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT24 0x0F /**< Signed 24-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT32 0x10 /**< Signed 32-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT48 0x11 /**< Signed 48-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT64 0x12 /**< Signed 64-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_SINT128 0x13 /**< Signed 128-bit integer. */
|
||||
#define BLE_GATT_CPF_FORMAT_FLOAT32 0x14 /**< IEEE-754 32-bit floating point. */
|
||||
#define BLE_GATT_CPF_FORMAT_FLOAT64 0x15 /**< IEEE-754 64-bit floating point. */
|
||||
#define BLE_GATT_CPF_FORMAT_SFLOAT 0x16 /**< IEEE-11073 16-bit SFLOAT. */
|
||||
#define BLE_GATT_CPF_FORMAT_FLOAT 0x17 /**< IEEE-11073 32-bit FLOAT. */
|
||||
#define BLE_GATT_CPF_FORMAT_DUINT16 0x18 /**< IEEE-20601 format. */
|
||||
#define BLE_GATT_CPF_FORMAT_UTF8S 0x19 /**< UTF-8 string. */
|
||||
#define BLE_GATT_CPF_FORMAT_UTF16S 0x1A /**< UTF-16 string. */
|
||||
#define BLE_GATT_CPF_FORMAT_STRUCT 0x1B /**< Opaque Structure. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATT_CPF_NAMESPACES GATT Bluetooth Namespaces
|
||||
* @{
|
||||
*/
|
||||
#define BLE_GATT_CPF_NAMESPACE_BTSIG 0x01 /**< Bluetooth SIG defined Namespace. */
|
||||
#define BLE_GATT_CPF_NAMESPACE_DESCRIPTION_UNKNOWN 0x0000 /**< Namespace Description Unknown. */
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_GATT_STRUCTURES Structures
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief BLE GATT initialization parameters.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint16_t att_mtu; /**< Maximum size of ATT packet the SoftDevice can send or receive.
|
||||
If it is 0 then @ref BLE_GATT_MTU_SIZE_DEFAULT will be used.
|
||||
Otherwise @ref BLE_GATT_MTU_SIZE_DEFAULT is the minimum value.
|
||||
@mscs
|
||||
@mmsc{@ref BLE_GATTC_MTU_EXCHANGE}
|
||||
@mmsc{@ref BLE_GATTS_MTU_EXCHANGE}
|
||||
@endmscs
|
||||
*/
|
||||
} ble_gatt_enable_params_t;
|
||||
|
||||
/**@brief GATT Characteristic Properties. */
|
||||
typedef struct
|
||||
{
|
||||
/* Standard properties */
|
||||
uint8_t broadcast :1; /**< Broadcasting of the value permitted. */
|
||||
uint8_t read :1; /**< Reading the value permitted. */
|
||||
uint8_t write_wo_resp :1; /**< Writing the value with Write Command permitted. */
|
||||
uint8_t write :1; /**< Writing the value with Write Request permitted. */
|
||||
uint8_t notify :1; /**< Notications of the value permitted. */
|
||||
uint8_t indicate :1; /**< Indications of the value permitted. */
|
||||
uint8_t auth_signed_wr :1; /**< Writing the value with Signed Write Command permitted. */
|
||||
} ble_gatt_char_props_t;
|
||||
|
||||
/**@brief GATT Characteristic Extended Properties. */
|
||||
typedef struct
|
||||
{
|
||||
/* Extended properties */
|
||||
uint8_t reliable_wr :1; /**< Writing the value with Queued Write operations permitted. */
|
||||
uint8_t wr_aux :1; /**< Writing the Characteristic User Description descriptor permitted. */
|
||||
} ble_gatt_char_ext_props_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BLE_GATT_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,669 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_GATTC Generic Attribute Profile (GATT) Client
|
||||
@{
|
||||
@brief Definitions and prototypes for the GATT Client interface.
|
||||
*/
|
||||
|
||||
#ifndef BLE_GATTC_H__
|
||||
#define BLE_GATTC_H__
|
||||
|
||||
#include "ble_gatt.h"
|
||||
#include "ble_types.h"
|
||||
#include "ble_ranges.h"
|
||||
#include "nrf_svc.h"
|
||||
#include "nrf_error.h"
|
||||
#include "nrf.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup BLE_GATTC_ENUMERATIONS Enumerations
|
||||
* @{ */
|
||||
|
||||
/**@brief GATTC API SVC numbers. */
|
||||
enum BLE_GATTC_SVCS
|
||||
{
|
||||
SD_BLE_GATTC_PRIMARY_SERVICES_DISCOVER = BLE_GATTC_SVC_BASE, /**< Primary Service Discovery. */
|
||||
SD_BLE_GATTC_RELATIONSHIPS_DISCOVER, /**< Relationship Discovery. */
|
||||
SD_BLE_GATTC_CHARACTERISTICS_DISCOVER, /**< Characteristic Discovery. */
|
||||
SD_BLE_GATTC_DESCRIPTORS_DISCOVER, /**< Characteristic Descriptor Discovery. */
|
||||
SD_BLE_GATTC_ATTR_INFO_DISCOVER, /**< Attribute Information Discovery. */
|
||||
SD_BLE_GATTC_CHAR_VALUE_BY_UUID_READ, /**< Read Characteristic Value by UUID. */
|
||||
SD_BLE_GATTC_READ, /**< Generic read. */
|
||||
SD_BLE_GATTC_CHAR_VALUES_READ, /**< Read multiple Characteristic Values. */
|
||||
SD_BLE_GATTC_WRITE, /**< Generic write. */
|
||||
SD_BLE_GATTC_HV_CONFIRM, /**< Handle Value Confirmation. */
|
||||
SD_BLE_GATTC_EXCHANGE_MTU_REQUEST, /**< Exchange MTU Request. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GATT Client Event IDs.
|
||||
*/
|
||||
enum BLE_GATTC_EVTS
|
||||
{
|
||||
BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP = BLE_GATTC_EVT_BASE, /**< Primary Service Discovery Response event. \n See @ref ble_gattc_evt_prim_srvc_disc_rsp_t. */
|
||||
BLE_GATTC_EVT_REL_DISC_RSP, /**< Relationship Discovery Response event. \n See @ref ble_gattc_evt_rel_disc_rsp_t. */
|
||||
BLE_GATTC_EVT_CHAR_DISC_RSP, /**< Characteristic Discovery Response event. \n See @ref ble_gattc_evt_char_disc_rsp_t. */
|
||||
BLE_GATTC_EVT_DESC_DISC_RSP, /**< Descriptor Discovery Response event. \n See @ref ble_gattc_evt_desc_disc_rsp_t. */
|
||||
BLE_GATTC_EVT_ATTR_INFO_DISC_RSP, /**< Attribute Information Response event. \n See @ref ble_gattc_evt_attr_info_disc_rsp_t. */
|
||||
BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP, /**< Read By UUID Response event. \n See @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t. */
|
||||
BLE_GATTC_EVT_READ_RSP, /**< Read Response event. \n See @ref ble_gattc_evt_read_rsp_t. */
|
||||
BLE_GATTC_EVT_CHAR_VALS_READ_RSP, /**< Read multiple Response event. \n See @ref ble_gattc_evt_char_vals_read_rsp_t. */
|
||||
BLE_GATTC_EVT_WRITE_RSP, /**< Write Response event. \n See @ref ble_gattc_evt_write_rsp_t. */
|
||||
BLE_GATTC_EVT_HVX, /**< Handle Value Notification or Indication event. \n Confirm indication with @ref sd_ble_gattc_hv_confirm. \n See @ref ble_gattc_evt_hvx_t. */
|
||||
BLE_GATTC_EVT_EXCHANGE_MTU_RSP, /**< Exchange MTU Response event. \n See @ref ble_gattc_evt_exchange_mtu_rsp_t. */
|
||||
BLE_GATTC_EVT_TIMEOUT /**< Timeout event. \n See @ref ble_gattc_evt_timeout_t. */
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_GATTC_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/** @defgroup BLE_ERRORS_GATTC SVC return values specific to GATTC
|
||||
* @{ */
|
||||
#define BLE_ERROR_GATTC_PROC_NOT_PERMITTED (NRF_GATTC_ERR_BASE + 0x000) /**< Procedure not Permitted. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATTC_ATTR_INFO_FORMAT Attribute Information Formats
|
||||
* @{ */
|
||||
#define BLE_GATTC_ATTR_INFO_FORMAT_16BIT 1 /**< 16-bit Attribute Information Format. */
|
||||
#define BLE_GATTC_ATTR_INFO_FORMAT_128BIT 2 /**< 128-bit Attribute Information Format. */
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_GATTC_STRUCTURES Structures
|
||||
* @{ */
|
||||
|
||||
/**@brief Operation Handle Range. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t start_handle; /**< Start Handle. */
|
||||
uint16_t end_handle; /**< End Handle. */
|
||||
} ble_gattc_handle_range_t;
|
||||
|
||||
|
||||
/**@brief GATT service. */
|
||||
typedef struct
|
||||
{
|
||||
ble_uuid_t uuid; /**< Service UUID. */
|
||||
ble_gattc_handle_range_t handle_range; /**< Service Handle Range. */
|
||||
} ble_gattc_service_t;
|
||||
|
||||
|
||||
/**@brief GATT include. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Include Handle. */
|
||||
ble_gattc_service_t included_srvc; /**< Handle of the included service. */
|
||||
} ble_gattc_include_t;
|
||||
|
||||
|
||||
/**@brief GATT characteristic. */
|
||||
typedef struct
|
||||
{
|
||||
ble_uuid_t uuid; /**< Characteristic UUID. */
|
||||
ble_gatt_char_props_t char_props; /**< Characteristic Properties. */
|
||||
uint8_t char_ext_props : 1; /**< Extended properties present. */
|
||||
uint16_t handle_decl; /**< Handle of the Characteristic Declaration. */
|
||||
uint16_t handle_value; /**< Handle of the Characteristic Value. */
|
||||
} ble_gattc_char_t;
|
||||
|
||||
|
||||
/**@brief GATT descriptor. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Descriptor Handle. */
|
||||
ble_uuid_t uuid; /**< Descriptor UUID. */
|
||||
} ble_gattc_desc_t;
|
||||
|
||||
|
||||
/**@brief Write Parameters. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t write_op; /**< Write Operation to be performed, see @ref BLE_GATT_WRITE_OPS. */
|
||||
uint8_t flags; /**< Flags, see @ref BLE_GATT_EXEC_WRITE_FLAGS. */
|
||||
uint16_t handle; /**< Handle to the attribute to be written. */
|
||||
uint16_t offset; /**< Offset in bytes. @note For WRITE_CMD and WRITE_REQ, offset must be 0. */
|
||||
uint16_t len; /**< Length of data in bytes. */
|
||||
uint8_t const *p_value; /**< Pointer to the value data. */
|
||||
} ble_gattc_write_params_t;
|
||||
|
||||
/**@brief Attribute Information for 16-bit Attribute UUID. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute handle. */
|
||||
ble_uuid_t uuid; /**< 16-bit Attribute UUID. */
|
||||
} ble_gattc_attr_info16_t;
|
||||
|
||||
/**@brief Attribute Information for 128-bit Attribute UUID. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute handle. */
|
||||
ble_uuid128_t uuid; /**< 128-bit Attribute UUID. */
|
||||
} ble_gattc_attr_info128_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count; /**< Service count. */
|
||||
ble_gattc_service_t services[1]; /**< Service data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_prim_srvc_disc_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_REL_DISC_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count; /**< Include count. */
|
||||
ble_gattc_include_t includes[1]; /**< Include data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_rel_disc_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_DISC_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count; /**< Characteristic count. */
|
||||
ble_gattc_char_t chars[1]; /**< Characteristic data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_char_disc_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_DESC_DISC_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count; /**< Descriptor count. */
|
||||
ble_gattc_desc_t descs[1]; /**< Descriptor data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_desc_disc_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_ATTR_INFO_DISC_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count; /**< Attribute count. */
|
||||
uint8_t format; /**< Attribute information format, see @ref BLE_GATTC_ATTR_INFO_FORMAT. */
|
||||
union {
|
||||
ble_gattc_attr_info16_t attr_info16[1]; /**< Attribute information for 16-bit Attribute UUID.
|
||||
@note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
ble_gattc_attr_info128_t attr_info128[1]; /**< Attribute information for 128-bit Attribute UUID.
|
||||
@note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} info; /**< Attribute information union. */
|
||||
} ble_gattc_evt_attr_info_disc_rsp_t;
|
||||
|
||||
/**@brief GATT read by UUID handle value pair. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute Handle. */
|
||||
uint8_t *p_value; /**< Pointer to the Attribute Value, length is available in @ref ble_gattc_evt_char_val_by_uuid_read_rsp_t::value_len. */
|
||||
} ble_gattc_handle_value_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t count; /**< Handle-Value Pair Count. */
|
||||
uint16_t value_len; /**< Length of the value in Handle-Value(s) list. */
|
||||
uint8_t handle_value[1]; /**< Handle-Value(s) list. To iterate through the list use @ref sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter.
|
||||
@note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_char_val_by_uuid_read_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_READ_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute Handle. */
|
||||
uint16_t offset; /**< Offset of the attribute data. */
|
||||
uint16_t len; /**< Attribute data length. */
|
||||
uint8_t data[1]; /**< Attribute data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_read_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_CHAR_VALS_READ_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t len; /**< Concatenated Attribute values length. */
|
||||
uint8_t values[1]; /**< Attribute values. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_char_vals_read_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_WRITE_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute Handle. */
|
||||
uint8_t write_op; /**< Type of write operation, see @ref BLE_GATT_WRITE_OPS. */
|
||||
uint16_t offset; /**< Data offset. */
|
||||
uint16_t len; /**< Data length. */
|
||||
uint8_t data[1]; /**< Data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_write_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_HVX. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Handle to which the HVx operation applies. */
|
||||
uint8_t type; /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */
|
||||
uint16_t len; /**< Attribute data length. */
|
||||
uint8_t data[1]; /**< Attribute data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gattc_evt_hvx_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t server_rx_mtu; /**< Server RX MTU size. */
|
||||
} ble_gattc_evt_exchange_mtu_rsp_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTC_EVT_TIMEOUT. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */
|
||||
} ble_gattc_evt_timeout_t;
|
||||
|
||||
/**@brief GATTC event structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t conn_handle; /**< Connection Handle on which event occured. */
|
||||
uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */
|
||||
uint16_t error_handle; /**< In case of error: The handle causing the error. In all other cases @ref BLE_GATT_HANDLE_INVALID. */
|
||||
union
|
||||
{
|
||||
ble_gattc_evt_prim_srvc_disc_rsp_t prim_srvc_disc_rsp; /**< Primary Service Discovery Response Event Parameters. */
|
||||
ble_gattc_evt_rel_disc_rsp_t rel_disc_rsp; /**< Relationship Discovery Response Event Parameters. */
|
||||
ble_gattc_evt_char_disc_rsp_t char_disc_rsp; /**< Characteristic Discovery Response Event Parameters. */
|
||||
ble_gattc_evt_desc_disc_rsp_t desc_disc_rsp; /**< Descriptor Discovery Response Event Parameters. */
|
||||
ble_gattc_evt_char_val_by_uuid_read_rsp_t char_val_by_uuid_read_rsp; /**< Characteristic Value Read by UUID Response Event Parameters. */
|
||||
ble_gattc_evt_read_rsp_t read_rsp; /**< Read Response Event Parameters. */
|
||||
ble_gattc_evt_char_vals_read_rsp_t char_vals_read_rsp; /**< Characteristic Values Read Response Event Parameters. */
|
||||
ble_gattc_evt_write_rsp_t write_rsp; /**< Write Response Event Parameters. */
|
||||
ble_gattc_evt_hvx_t hvx; /**< Handle Value Notification/Indication Event Parameters. */
|
||||
ble_gattc_evt_exchange_mtu_rsp_t exchange_mtu_rsp; /**< Exchange MTU Response Event Parameters. */
|
||||
ble_gattc_evt_timeout_t timeout; /**< Timeout Event Parameters. */
|
||||
ble_gattc_evt_attr_info_disc_rsp_t attr_info_disc_rsp; /**< Attribute Information Discovery Event Parameters. */
|
||||
} params; /**< Event Parameters. @note Only valid if @ref gatt_status == @ref BLE_GATT_STATUS_SUCCESS. */
|
||||
} ble_gattc_evt_t;
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_GATTC_FUNCTIONS Functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Initiate or continue a GATT Primary Service Discovery procedure.
|
||||
*
|
||||
* @details This function initiates or resumes a Primary Service discovery procedure, starting from the supplied handle.
|
||||
* If the last service has not been reached, this function must be called again with an updated start handle value to continue the search.
|
||||
*
|
||||
* @note If any of the discovered services have 128-bit UUIDs which are not present in the table provided to ble_vs_uuids_assign, a UUID structure with
|
||||
* type @ref BLE_UUID_TYPE_UNKNOWN will be received in the corresponding event.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_PRIM_SRVC_DISC_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] start_handle Handle to start searching from.
|
||||
* @param[in] p_srvc_uuid Pointer to the service UUID to be found. If it is NULL, all primary services will be returned.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started or resumed the Primary Service Discovery procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_PRIMARY_SERVICES_DISCOVER, uint32_t, sd_ble_gattc_primary_services_discover(uint16_t conn_handle, uint16_t start_handle, ble_uuid_t const *p_srvc_uuid));
|
||||
|
||||
|
||||
/**@brief Initiate or continue a GATT Relationship Discovery procedure.
|
||||
*
|
||||
* @details This function initiates or resumes the Find Included Services sub-procedure. If the last included service has not been reached,
|
||||
* this must be called again with an updated handle range to continue the search.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_REL_DISC_RSP}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_REL_DISC_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] p_handle_range A pointer to the range of handles of the Service to perform this procedure on.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started or resumed the Relationship Discovery procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_RELATIONSHIPS_DISCOVER, uint32_t, sd_ble_gattc_relationships_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range));
|
||||
|
||||
|
||||
/**@brief Initiate or continue a GATT Characteristic Discovery procedure.
|
||||
*
|
||||
* @details This function initiates or resumes a Characteristic discovery procedure. If the last Characteristic has not been reached,
|
||||
* this must be called again with an updated handle range to continue the discovery.
|
||||
*
|
||||
* @note If any of the discovered characteristics have 128-bit UUIDs which are not present in the table provided to ble_vs_uuids_assign, a UUID structure with
|
||||
* type @ref BLE_UUID_TYPE_UNKNOWN will be received in the corresponding event.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_CHAR_DISC_RSP}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_CHAR_DISC_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] p_handle_range A pointer to the range of handles of the Service to perform this procedure on.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started or resumed the Characteristic Discovery procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_CHARACTERISTICS_DISCOVER, uint32_t, sd_ble_gattc_characteristics_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range));
|
||||
|
||||
|
||||
/**@brief Initiate or continue a GATT Characteristic Descriptor Discovery procedure.
|
||||
*
|
||||
* @details This function initiates or resumes a Characteristic Descriptor discovery procedure. If the last Descriptor has not been reached,
|
||||
* this must be called again with an updated handle range to continue the discovery.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_DESC_DISC_RSP}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_DESC_DISC_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] p_handle_range A pointer to the range of handles of the Characteristic to perform this procedure on.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started or resumed the Descriptor Discovery procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_DESCRIPTORS_DISCOVER, uint32_t, sd_ble_gattc_descriptors_discover(uint16_t conn_handle, ble_gattc_handle_range_t const *p_handle_range));
|
||||
|
||||
|
||||
/**@brief Initiate or continue a GATT Read using Characteristic UUID procedure.
|
||||
*
|
||||
* @details This function initiates or resumes a Read using Characteristic UUID procedure. If the last Characteristic has not been reached,
|
||||
* this must be called again with an updated handle range to continue the discovery.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_READ_UUID_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] p_uuid Pointer to a Characteristic value UUID to read.
|
||||
* @param[in] p_handle_range A pointer to the range of handles to perform this procedure on.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started or resumed the Read using Characteristic UUID procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_CHAR_VALUE_BY_UUID_READ, uint32_t, sd_ble_gattc_char_value_by_uuid_read(uint16_t conn_handle, ble_uuid_t const *p_uuid, ble_gattc_handle_range_t const *p_handle_range));
|
||||
|
||||
|
||||
/**@brief Initiate or continue a GATT Read (Long) Characteristic or Descriptor procedure.
|
||||
*
|
||||
* @details This function initiates or resumes a GATT Read (Long) Characteristic or Descriptor procedure. If the Characteristic or Descriptor
|
||||
* to be read is longer than ATT_MTU - 1, this function must be called multiple times with appropriate offset to read the
|
||||
* complete value.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_READ_RSP}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_VALUE_READ_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] handle The handle of the attribute to be read.
|
||||
* @param[in] offset Offset into the attribute value to be read.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started or resumed the Read (Long) procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_READ, uint32_t, sd_ble_gattc_read(uint16_t conn_handle, uint16_t handle, uint16_t offset));
|
||||
|
||||
|
||||
/**@brief Initiate a GATT Read Multiple Characteristic Values procedure.
|
||||
*
|
||||
* @details This function initiates a GATT Read Multiple Characteristic Values procedure.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_CHAR_VALS_READ_RSP}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_READ_MULT_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] p_handles A pointer to the handle(s) of the attribute(s) to be read.
|
||||
* @param[in] handle_count The number of handles in p_handles.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started the Read Multiple Characteristic Values procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_CHAR_VALUES_READ, uint32_t, sd_ble_gattc_char_values_read(uint16_t conn_handle, uint16_t const *p_handles, uint16_t handle_count));
|
||||
|
||||
|
||||
/**@brief Perform a Write (Characteristic Value or Descriptor, with or without response, signed or not, long or reliable) procedure.
|
||||
*
|
||||
* @details This function can perform all write procedures described in GATT.
|
||||
*
|
||||
* @note It is important to note that a write without response will <b>consume an application buffer</b>, and will therefore
|
||||
* generate a @ref BLE_EVT_TX_COMPLETE event when the packet has been transmitted. A write (with response) on the other hand will use the
|
||||
* standard client internal buffer and thus will only generate a @ref BLE_GATTC_EVT_WRITE_RSP event as soon as the write response
|
||||
* has been received from the peer. Please see the documentation of @ref sd_ble_tx_packet_count_get for more details.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_WRITE_RSP, Generated when using write request or queued writes.}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_VALUE_WRITE_MSC}
|
||||
* @mmsc{@ref BLE_GATTC_VALUE_LONG_WRITE_MSC}
|
||||
* @mmsc{@ref BLE_GATTC_VALUE_RELIABLE_WRITE_MSC}
|
||||
* @mmsc{@ref BLE_COMMON_APP_BUFF_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] p_write_params A pointer to a write parameters structure.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started the Write procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Procedure already in progress.
|
||||
* @retval ::BLE_ERROR_NO_TX_PACKETS No available application packets for this connection.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_WRITE, uint32_t, sd_ble_gattc_write(uint16_t conn_handle, ble_gattc_write_params_t const *p_write_params));
|
||||
|
||||
|
||||
/**@brief Send a Handle Value Confirmation to the GATT Server.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_HVI_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] handle The handle of the attribute in the indication.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully queued the Handle Value Confirmation for transmission.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no Indication pending to be confirmed.
|
||||
* @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_HV_CONFIRM, uint32_t, sd_ble_gattc_hv_confirm(uint16_t conn_handle, uint16_t handle));
|
||||
|
||||
/**@brief Discovers information about a range of attributes on a GATT server.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_ATTR_INFO_DISC_RSP, Generated when information about a range of attributes has been received.}
|
||||
* @endevents
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] p_handle_range The range of handles to request information about.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully started an attribute information discovery procedure.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid connection state
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_ATTR_INFO_DISCOVER, uint32_t, sd_ble_gattc_attr_info_discover(uint16_t conn_handle, ble_gattc_handle_range_t const * p_handle_range));
|
||||
|
||||
/**@brief Start an ATT_MTU exchange by sending an Exchange MTU Request to the server.
|
||||
*
|
||||
* @details The SoftDevice sets ATT_MTU to the minimum of:
|
||||
* - The Client RX MTU value, and
|
||||
* - The Server RX MTU value from @ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP.
|
||||
*
|
||||
* However, the SoftDevice never sets ATT_MTU lower than @ref BLE_GATT_MTU_SIZE_DEFAULT.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTC_EVT_EXCHANGE_MTU_RSP}
|
||||
* @event{@ref BLE_EVT_DATA_LENGTH_CHANGED, Generated if a data length update procedure is performed after the ATT_MTU exchange.}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTC_MTU_EXCHANGE}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] client_rx_mtu Client RX MTU size.
|
||||
* - The minimum value is @ref BLE_GATT_MTU_SIZE_DEFAULT.
|
||||
* - The maximum value is @ref ble_gatt_enable_params_t::att_mtu.
|
||||
* - The value must be equal to Server RX MTU size given in @ref sd_ble_gatts_exchange_mtu_reply
|
||||
* if an ATT_MTU exchange has already been performed in the other direction.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully sent request to the server.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid connection state or an ATT_MTU exchange was already requested once.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid Client RX MTU size supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Client procedure already in progress.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTC_EXCHANGE_MTU_REQUEST, uint32_t, sd_ble_gattc_exchange_mtu_request(uint16_t conn_handle, uint16_t client_rx_mtu));
|
||||
|
||||
/**@brief Iterate through Handle-Value(s) list in @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP event.
|
||||
*
|
||||
* @param[in] p_gattc_evt Pointer to event buffer containing @ref BLE_GATTC_EVT_CHAR_VAL_BY_UUID_READ_RSP event.
|
||||
* @note If the buffer contains different event, behavior is undefined.
|
||||
* @param[in,out] p_iter Iterator, points to @ref ble_gattc_handle_value_t structure that will be filled in with
|
||||
* the next Handle-Value pair in each iteration. If the function returns other than
|
||||
* @ref NRF_SUCCESS, it will not be changed.
|
||||
* - To start iteration, initialize the structure to zero.
|
||||
* - To continue, pass the value from previous iteration.
|
||||
*
|
||||
* \code
|
||||
* ble_gattc_handle_value_t iter;
|
||||
* memset(&iter, 0, sizeof(ble_gattc_handle_value_t));
|
||||
* while (sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(&ble_evt.evt.gattc_evt, &iter) == NRF_SUCCESS)
|
||||
* {
|
||||
* app_handle = iter.handle;
|
||||
* memcpy(app_value, iter.p_value, ble_evt.evt.gattc_evt.params.char_val_by_uuid_read_rsp.value_len);
|
||||
* }
|
||||
* \endcode
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully retrieved the next Handle-Value pair.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND No more Handle-Value pairs available in the list.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(ble_gattc_evt_t *p_gattc_evt, ble_gattc_handle_value_t *p_iter);
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE uint32_t sd_ble_gattc_evt_char_val_by_uuid_read_rsp_iter(ble_gattc_evt_t *p_gattc_evt, ble_gattc_handle_value_t *p_iter)
|
||||
{
|
||||
uint32_t value_len = p_gattc_evt->params.char_val_by_uuid_read_rsp.value_len;
|
||||
uint8_t *p_first = p_gattc_evt->params.char_val_by_uuid_read_rsp.handle_value;
|
||||
uint8_t *p_next = p_iter->p_value ? p_iter->p_value + value_len : p_first;
|
||||
|
||||
if ((p_next - p_first) / (sizeof(uint16_t) + value_len) < p_gattc_evt->params.char_val_by_uuid_read_rsp.count)
|
||||
{
|
||||
p_iter->handle = (uint16_t)p_next[1] << 8 | p_next[0];
|
||||
p_iter->p_value = p_next + sizeof(uint16_t);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRF_ERROR_NOT_FOUND;
|
||||
}
|
||||
}
|
||||
|
||||
#endif /* SUPPRESS_INLINE_IMPLEMENTATION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* BLE_GATTC_H__ */
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,778 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_GATTS Generic Attribute Profile (GATT) Server
|
||||
@{
|
||||
@brief Definitions and prototypes for the GATTS interface.
|
||||
*/
|
||||
|
||||
#ifndef BLE_GATTS_H__
|
||||
#define BLE_GATTS_H__
|
||||
|
||||
#include "ble_types.h"
|
||||
#include "ble_ranges.h"
|
||||
#include "ble_l2cap.h"
|
||||
#include "ble_gap.h"
|
||||
#include "ble_gatt.h"
|
||||
#include "nrf_svc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup BLE_GATTS_ENUMERATIONS Enumerations
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief GATTS API SVC numbers.
|
||||
*/
|
||||
enum BLE_GATTS_SVCS
|
||||
{
|
||||
SD_BLE_GATTS_SERVICE_ADD = BLE_GATTS_SVC_BASE, /**< Add a service. */
|
||||
SD_BLE_GATTS_INCLUDE_ADD, /**< Add an included service. */
|
||||
SD_BLE_GATTS_CHARACTERISTIC_ADD, /**< Add a characteristic. */
|
||||
SD_BLE_GATTS_DESCRIPTOR_ADD, /**< Add a generic attribute. */
|
||||
SD_BLE_GATTS_VALUE_SET, /**< Set an attribute value. */
|
||||
SD_BLE_GATTS_VALUE_GET, /**< Get an attribute value. */
|
||||
SD_BLE_GATTS_HVX, /**< Handle Value Notification or Indication. */
|
||||
SD_BLE_GATTS_SERVICE_CHANGED, /**< Perform a Service Changed Indication to one or more peers. */
|
||||
SD_BLE_GATTS_RW_AUTHORIZE_REPLY, /**< Reply to an authorization request for a read or write operation on one or more attributes. */
|
||||
SD_BLE_GATTS_SYS_ATTR_SET, /**< Set the persistent system attributes for a connection. */
|
||||
SD_BLE_GATTS_SYS_ATTR_GET, /**< Retrieve the persistent system attributes. */
|
||||
SD_BLE_GATTS_INITIAL_USER_HANDLE_GET, /**< Retrieve the first valid user handle. */
|
||||
SD_BLE_GATTS_ATTR_GET, /**< Retrieve the UUID and/or metadata of an attribute. */
|
||||
SD_BLE_GATTS_EXCHANGE_MTU_REPLY /**< Reply to Exchange MTU Request. */
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief GATT Server Event IDs.
|
||||
*/
|
||||
enum BLE_GATTS_EVTS
|
||||
{
|
||||
BLE_GATTS_EVT_WRITE = BLE_GATTS_EVT_BASE, /**< Write operation performed. \n See @ref ble_gatts_evt_write_t. */
|
||||
BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST, /**< Read/Write Authorization request. \n Reply with @ref sd_ble_gatts_rw_authorize_reply. \n See @ref ble_gatts_evt_rw_authorize_request_t. */
|
||||
BLE_GATTS_EVT_SYS_ATTR_MISSING, /**< A persistent system attribute access is pending. \n Respond with @ref sd_ble_gatts_sys_attr_set. \n See @ref ble_gatts_evt_sys_attr_missing_t. */
|
||||
BLE_GATTS_EVT_HVC, /**< Handle Value Confirmation. \n See @ref ble_gatts_evt_hvc_t. */
|
||||
BLE_GATTS_EVT_SC_CONFIRM, /**< Service Changed Confirmation. No additional event structure applies. */
|
||||
BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST, /**< Exchange MTU Request. \n Reply with @ref sd_ble_gatts_exchange_mtu_reply. \n See @ref ble_gatts_evt_exchange_mtu_request_t. */
|
||||
BLE_GATTS_EVT_TIMEOUT /**< Peer failed to resonpond to an ATT request in time. \n See @ref ble_gatts_evt_timeout_t. */
|
||||
};
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_GATTS_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/** @defgroup BLE_ERRORS_GATTS SVC return values specific to GATTS
|
||||
* @{ */
|
||||
#define BLE_ERROR_GATTS_INVALID_ATTR_TYPE (NRF_GATTS_ERR_BASE + 0x000) /**< Invalid attribute type. */
|
||||
#define BLE_ERROR_GATTS_SYS_ATTR_MISSING (NRF_GATTS_ERR_BASE + 0x001) /**< System Attributes missing. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATTS_ATTR_LENS_MAX Maximum attribute lengths
|
||||
* @{ */
|
||||
#define BLE_GATTS_FIX_ATTR_LEN_MAX (510) /**< Maximum length for fixed length Attribute Values. */
|
||||
#define BLE_GATTS_VAR_ATTR_LEN_MAX (512) /**< Maximum length for variable length Attribute Values. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATTS_SRVC_TYPES GATT Server Service Types
|
||||
* @{ */
|
||||
#define BLE_GATTS_SRVC_TYPE_INVALID 0x00 /**< Invalid Service Type. */
|
||||
#define BLE_GATTS_SRVC_TYPE_PRIMARY 0x01 /**< Primary Service. */
|
||||
#define BLE_GATTS_SRVC_TYPE_SECONDARY 0x02 /**< Secondary Type. */
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @defgroup BLE_GATTS_ATTR_TYPES GATT Server Attribute Types
|
||||
* @{ */
|
||||
#define BLE_GATTS_ATTR_TYPE_INVALID 0x00 /**< Invalid Attribute Type. */
|
||||
#define BLE_GATTS_ATTR_TYPE_PRIM_SRVC_DECL 0x01 /**< Primary Service Declaration. */
|
||||
#define BLE_GATTS_ATTR_TYPE_SEC_SRVC_DECL 0x02 /**< Secondary Service Declaration. */
|
||||
#define BLE_GATTS_ATTR_TYPE_INC_DECL 0x03 /**< Include Declaration. */
|
||||
#define BLE_GATTS_ATTR_TYPE_CHAR_DECL 0x04 /**< Characteristic Declaration. */
|
||||
#define BLE_GATTS_ATTR_TYPE_CHAR_VAL 0x05 /**< Characteristic Value. */
|
||||
#define BLE_GATTS_ATTR_TYPE_DESC 0x06 /**< Descriptor. */
|
||||
#define BLE_GATTS_ATTR_TYPE_OTHER 0x07 /**< Other, non-GATT specific type. */
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @defgroup BLE_GATTS_OPS GATT Server Operations
|
||||
* @{ */
|
||||
#define BLE_GATTS_OP_INVALID 0x00 /**< Invalid Operation. */
|
||||
#define BLE_GATTS_OP_WRITE_REQ 0x01 /**< Write Request. */
|
||||
#define BLE_GATTS_OP_WRITE_CMD 0x02 /**< Write Command. */
|
||||
#define BLE_GATTS_OP_SIGN_WRITE_CMD 0x03 /**< Signed Write Command. */
|
||||
#define BLE_GATTS_OP_PREP_WRITE_REQ 0x04 /**< Prepare Write Request. */
|
||||
#define BLE_GATTS_OP_EXEC_WRITE_REQ_CANCEL 0x05 /**< Execute Write Request: Cancel all prepared writes. */
|
||||
#define BLE_GATTS_OP_EXEC_WRITE_REQ_NOW 0x06 /**< Execute Write Request: Immediately execute all prepared writes. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATTS_VLOCS GATT Value Locations
|
||||
* @{ */
|
||||
#define BLE_GATTS_VLOC_INVALID 0x00 /**< Invalid Location. */
|
||||
#define BLE_GATTS_VLOC_STACK 0x01 /**< Attribute Value is located in stack memory, no user memory is required. */
|
||||
#define BLE_GATTS_VLOC_USER 0x02 /**< Attribute Value is located in user memory. This requires the user to maintain a valid buffer through the lifetime of the attribute, since the stack
|
||||
will read and write directly to the memory using the pointer provided in the APIs. There are no alignment requirements for the buffer. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATTS_AUTHORIZE_TYPES GATT Server Authorization Types
|
||||
* @{ */
|
||||
#define BLE_GATTS_AUTHORIZE_TYPE_INVALID 0x00 /**< Invalid Type. */
|
||||
#define BLE_GATTS_AUTHORIZE_TYPE_READ 0x01 /**< Authorize a Read Operation. */
|
||||
#define BLE_GATTS_AUTHORIZE_TYPE_WRITE 0x02 /**< Authorize a Write Request Operation. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATTS_SYS_ATTR_FLAGS System Attribute Flags
|
||||
* @{ */
|
||||
#define BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS (1 << 0) /**< Restrict system attributes to system services only. */
|
||||
#define BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS (1 << 1) /**< Restrict system attributes to user services only. */
|
||||
/** @} */
|
||||
|
||||
/** @defgroup BLE_GATTS_ATTR_TAB_SIZE Attribute Table size
|
||||
* @{
|
||||
*/
|
||||
#define BLE_GATTS_ATTR_TAB_SIZE_MIN 248 /**< Minimum Attribute Table size */
|
||||
#define BLE_GATTS_ATTR_TAB_SIZE_DEFAULT 0x0000 /**< Default Attribute Table size (0x580 bytes for this version of the SoftDevice). */
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_GATTS_STRUCTURES Structures
|
||||
* @{ */
|
||||
|
||||
/**
|
||||
* @brief BLE GATTS initialization parameters.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint8_t service_changed:1; /**< Include the Service Changed characteristic in the Attribute Table. */
|
||||
uint32_t attr_tab_size; /**< Attribute Table size in bytes. The size must be a multiple of 4. @ref BLE_GATTS_ATTR_TAB_SIZE_DEFAULT is used to set the default size. */
|
||||
} ble_gatts_enable_params_t;
|
||||
|
||||
/**@brief Attribute metadata. */
|
||||
typedef struct
|
||||
{
|
||||
ble_gap_conn_sec_mode_t read_perm; /**< Read permissions. */
|
||||
ble_gap_conn_sec_mode_t write_perm; /**< Write permissions. */
|
||||
uint8_t vlen :1; /**< Variable length attribute. */
|
||||
uint8_t vloc :2; /**< Value location, see @ref BLE_GATTS_VLOCS.*/
|
||||
uint8_t rd_auth :1; /**< Read authorization and value will be requested from the application on every read operation. */
|
||||
uint8_t wr_auth :1; /**< Write authorization will be requested from the application on every Write Request operation (but not Write Command). */
|
||||
} ble_gatts_attr_md_t;
|
||||
|
||||
|
||||
/**@brief GATT Attribute. */
|
||||
typedef struct
|
||||
{
|
||||
ble_uuid_t *p_uuid; /**< Pointer to the attribute UUID. */
|
||||
ble_gatts_attr_md_t *p_attr_md; /**< Pointer to the attribute metadata structure. */
|
||||
uint16_t init_len; /**< Initial attribute value length in bytes. */
|
||||
uint16_t init_offs; /**< Initial attribute value offset in bytes. If different from zero, the first init_offs bytes of the attribute value will be left uninitialized. */
|
||||
uint16_t max_len; /**< Maximum attribute value length in bytes, see @ref BLE_GATTS_ATTR_LENS_MAX for maximum values. */
|
||||
uint8_t* p_value; /**< Pointer to the attribute data. Please note that if the @ref BLE_GATTS_VLOC_USER value location is selected in the attribute metadata, this will have to point to a buffer
|
||||
that remains valid through the lifetime of the attribute. This excludes usage of automatic variables that may go out of scope or any other temporary location.
|
||||
The stack may access that memory directly without the application's knowledge. For writable characteristics, this value must not be a location in flash memory.*/
|
||||
} ble_gatts_attr_t;
|
||||
|
||||
/**@brief GATT Attribute Value. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t len; /**< Length in bytes to be written or read. Length in bytes written or read after successful return.*/
|
||||
uint16_t offset; /**< Attribute value offset. */
|
||||
uint8_t *p_value; /**< Pointer to where value is stored or will be stored.
|
||||
If value is stored in user memory, only the attribute length is updated when p_value == NULL.
|
||||
Set to NULL when reading to obtain the complete length of the attribute value */
|
||||
} ble_gatts_value_t;
|
||||
|
||||
|
||||
/**@brief GATT Characteristic Presentation Format. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t format; /**< Format of the value, see @ref BLE_GATT_CPF_FORMATS. */
|
||||
int8_t exponent; /**< Exponent for integer data types. */
|
||||
uint16_t unit; /**< Unit from Bluetooth Assigned Numbers. */
|
||||
uint8_t name_space; /**< Namespace from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */
|
||||
uint16_t desc; /**< Namespace description from Bluetooth Assigned Numbers, see @ref BLE_GATT_CPF_NAMESPACES. */
|
||||
} ble_gatts_char_pf_t;
|
||||
|
||||
|
||||
/**@brief GATT Characteristic metadata. */
|
||||
typedef struct
|
||||
{
|
||||
ble_gatt_char_props_t char_props; /**< Characteristic Properties. */
|
||||
ble_gatt_char_ext_props_t char_ext_props; /**< Characteristic Extended Properties. */
|
||||
uint8_t *p_char_user_desc; /**< Pointer to a UTF-8 encoded string (non-NULL terminated), NULL if the descriptor is not required. */
|
||||
uint16_t char_user_desc_max_size; /**< The maximum size in bytes of the user description descriptor. */
|
||||
uint16_t char_user_desc_size; /**< The size of the user description, must be smaller or equal to char_user_desc_max_size. */
|
||||
ble_gatts_char_pf_t* p_char_pf; /**< Pointer to a presentation format structure or NULL if the CPF descriptor is not required. */
|
||||
ble_gatts_attr_md_t* p_user_desc_md; /**< Attribute metadata for the User Description descriptor, or NULL for default values. */
|
||||
ble_gatts_attr_md_t* p_cccd_md; /**< Attribute metadata for the Client Characteristic Configuration Descriptor, or NULL for default values. */
|
||||
ble_gatts_attr_md_t* p_sccd_md; /**< Attribute metadata for the Server Characteristic Configuration Descriptor, or NULL for default values. */
|
||||
} ble_gatts_char_md_t;
|
||||
|
||||
|
||||
/**@brief GATT Characteristic Definition Handles. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t value_handle; /**< Handle to the characteristic value. */
|
||||
uint16_t user_desc_handle; /**< Handle to the User Description descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */
|
||||
uint16_t cccd_handle; /**< Handle to the Client Characteristic Configuration Descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */
|
||||
uint16_t sccd_handle; /**< Handle to the Server Characteristic Configuration Descriptor, or @ref BLE_GATT_HANDLE_INVALID if not present. */
|
||||
} ble_gatts_char_handles_t;
|
||||
|
||||
|
||||
/**@brief GATT HVx parameters. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Characteristic Value Handle. */
|
||||
uint8_t type; /**< Indication or Notification, see @ref BLE_GATT_HVX_TYPES. */
|
||||
uint16_t offset; /**< Offset within the attribute value. */
|
||||
uint16_t *p_len; /**< Length in bytes to be written, length in bytes written after successful return. */
|
||||
uint8_t *p_data; /**< Actual data content, use NULL to use the current attribute value. */
|
||||
} ble_gatts_hvx_params_t;
|
||||
|
||||
/**@brief GATT Authorization parameters. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t gatt_status; /**< GATT status code for the operation, see @ref BLE_GATT_STATUS_CODES. */
|
||||
uint8_t update : 1; /**< If set, data supplied in p_data will be used to update the attribute value.
|
||||
Please note that for @ref BLE_GATTS_AUTHORIZE_TYPE_WRITE operations this bit must always be set,
|
||||
as the data to be written needs to be stored and later provided by the application. */
|
||||
uint16_t offset; /**< Offset of the attribute value being updated. */
|
||||
uint16_t len; /**< Length in bytes of the value in p_data pointer, see @ref BLE_GATTS_ATTR_LENS_MAX. */
|
||||
const uint8_t *p_data; /**< Pointer to new value used to update the attribute value. */
|
||||
} ble_gatts_authorize_params_t;
|
||||
|
||||
/**@brief GATT Read or Write Authorize Reply parameters. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< Type of authorize operation, see @ref BLE_GATTS_AUTHORIZE_TYPES. */
|
||||
union {
|
||||
ble_gatts_authorize_params_t read; /**< Read authorization parameters. */
|
||||
ble_gatts_authorize_params_t write; /**< Write authorization parameters. */
|
||||
} params; /**< Reply Parameters. */
|
||||
} ble_gatts_rw_authorize_reply_params_t;
|
||||
|
||||
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTS_EVT_WRITE. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute Handle. */
|
||||
ble_uuid_t uuid; /**< Attribute UUID. */
|
||||
uint8_t op; /**< Type of write operation, see @ref BLE_GATTS_OPS. */
|
||||
uint8_t auth_required; /**< Writing operation deferred due to authorization requirement. Application may use @ref sd_ble_gatts_value_set to finalise the writing operation. */
|
||||
uint16_t offset; /**< Offset for the write operation. */
|
||||
uint16_t len; /**< Length of the received data. */
|
||||
uint8_t data[1]; /**< Received data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_gatts_evt_write_t;
|
||||
|
||||
/**@brief Event substructure for authorized read requests, see @ref ble_gatts_evt_rw_authorize_request_t. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute Handle. */
|
||||
ble_uuid_t uuid; /**< Attribute UUID. */
|
||||
uint16_t offset; /**< Offset for the read operation. */
|
||||
} ble_gatts_evt_read_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t type; /**< Type of authorize operation, see @ref BLE_GATTS_AUTHORIZE_TYPES. */
|
||||
union {
|
||||
ble_gatts_evt_read_t read; /**< Attribute Read Parameters. */
|
||||
ble_gatts_evt_write_t write; /**< Attribute Write Parameters. */
|
||||
} request; /**< Request Parameters. */
|
||||
} ble_gatts_evt_rw_authorize_request_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTS_EVT_SYS_ATTR_MISSING. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t hint; /**< Hint (currently unused). */
|
||||
} ble_gatts_evt_sys_attr_missing_t;
|
||||
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTS_EVT_HVC. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t handle; /**< Attribute Handle. */
|
||||
} ble_gatts_evt_hvc_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t client_rx_mtu; /**< Client RX MTU size. */
|
||||
} ble_gatts_evt_exchange_mtu_request_t;
|
||||
|
||||
/**@brief Event structure for @ref BLE_GATTS_EVT_TIMEOUT. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t src; /**< Timeout source, see @ref BLE_GATT_TIMEOUT_SOURCES. */
|
||||
} ble_gatts_evt_timeout_t;
|
||||
|
||||
|
||||
/**@brief GATTS event structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t conn_handle; /**< Connection Handle on which the event occurred. */
|
||||
union
|
||||
{
|
||||
ble_gatts_evt_write_t write; /**< Write Event Parameters. */
|
||||
ble_gatts_evt_rw_authorize_request_t authorize_request; /**< Read or Write Authorize Request Parameters. */
|
||||
ble_gatts_evt_sys_attr_missing_t sys_attr_missing; /**< System attributes missing. */
|
||||
ble_gatts_evt_hvc_t hvc; /**< Handle Value Confirmation Event Parameters. */
|
||||
ble_gatts_evt_exchange_mtu_request_t exchange_mtu_request; /**< Exchange MTU Request Event Parameters. */
|
||||
ble_gatts_evt_timeout_t timeout; /**< Timeout Event. */
|
||||
} params; /**< Event Parameters. */
|
||||
} ble_gatts_evt_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_GATTS_FUNCTIONS Functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Add a service declaration to the Attribute Table.
|
||||
*
|
||||
* @note Secondary Services are only relevant in the context of the entity that references them, it is therefore forbidden to
|
||||
* add a secondary service declaration that is not referenced by another service later in the Attribute Table.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] type Toggles between primary and secondary services, see @ref BLE_GATTS_SRVC_TYPES.
|
||||
* @param[in] p_uuid Pointer to service UUID.
|
||||
* @param[out] p_handle Pointer to a 16-bit word where the assigned handle will be stored.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully added a service declaration.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, Vendor Specific UUIDs need to be present in the table.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack.
|
||||
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_SERVICE_ADD, uint32_t, sd_ble_gatts_service_add(uint8_t type, ble_uuid_t const *p_uuid, uint16_t *p_handle));
|
||||
|
||||
|
||||
/**@brief Add an include declaration to the Attribute Table.
|
||||
*
|
||||
* @note It is currently only possible to add an include declaration to the last added service (i.e. only sequential population is supported at this time).
|
||||
*
|
||||
* @note The included service must already be present in the Attribute Table prior to this call.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] service_handle Handle of the service where the included service is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
|
||||
* @param[in] inc_srvc_handle Handle of the included service.
|
||||
* @param[out] p_include_handle Pointer to a 16-bit word where the assigned handle will be stored.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully added an include declaration.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, handle values need to match previously added services.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation.
|
||||
* @retval ::NRF_ERROR_NOT_SUPPORTED Feature is not supported, service_handle must be that of the last added service.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, self inclusions are not allowed.
|
||||
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_INCLUDE_ADD, uint32_t, sd_ble_gatts_include_add(uint16_t service_handle, uint16_t inc_srvc_handle, uint16_t *p_include_handle));
|
||||
|
||||
|
||||
/**@brief Add a characteristic declaration, a characteristic value declaration and optional characteristic descriptor declarations to the Attribute Table.
|
||||
*
|
||||
* @note It is currently only possible to add a characteristic to the last added service (i.e. only sequential population is supported at this time).
|
||||
*
|
||||
* @note Several restrictions apply to the parameters, such as matching permissions between the user description descriptor and the writeable auxiliaries bits,
|
||||
* readable (no security) and writeable (selectable) CCCDs and SCCDs and valid presentation format values.
|
||||
*
|
||||
* @note If no metadata is provided for the optional descriptors, their permissions will be derived from the characteristic permissions.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] service_handle Handle of the service where the characteristic is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
|
||||
* @param[in] p_char_md Characteristic metadata.
|
||||
* @param[in] p_attr_char_value Pointer to the attribute structure corresponding to the characteristic value.
|
||||
* @param[out] p_handles Pointer to the structure where the assigned handles will be stored.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully added a characteristic.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, service handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation, a service context is required.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack.
|
||||
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_CHARACTERISTIC_ADD, uint32_t, sd_ble_gatts_characteristic_add(uint16_t service_handle, ble_gatts_char_md_t const *p_char_md, ble_gatts_attr_t const *p_attr_char_value, ble_gatts_char_handles_t *p_handles));
|
||||
|
||||
|
||||
/**@brief Add a descriptor to the Attribute Table.
|
||||
*
|
||||
* @note It is currently only possible to add a descriptor to the last added characteristic (i.e. only sequential population is supported at this time).
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_ATT_TABLE_POP_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] char_handle Handle of the characteristic where the descriptor is to be placed, if @ref BLE_GATT_HANDLE_INVALID is used, it will be placed sequentially.
|
||||
* @param[in] p_attr Pointer to the attribute structure.
|
||||
* @param[out] p_handle Pointer to a 16-bit word where the assigned handle will be stored.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully added a descriptor.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, characteristic handle, Vendor Specific UUIDs, lengths, and permissions need to adhere to the constraints.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid state to perform operation, a characteristic context is required.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Forbidden value supplied, certain UUIDs are reserved for the stack.
|
||||
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_DESCRIPTOR_ADD, uint32_t, sd_ble_gatts_descriptor_add(uint16_t char_handle, ble_gatts_attr_t const *p_attr, uint16_t *p_handle));
|
||||
|
||||
/**@brief Set the value of a given attribute.
|
||||
*
|
||||
* @note Values other than system attributes can be set at any time, regardless of wheter any active connections exist.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle Connection handle. Ignored if the value does not belong to a system attribute.
|
||||
* @param[in] handle Attribute handle.
|
||||
* @param[in,out] p_value Attribute value information.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully set the value of the attribute.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Forbidden handle supplied, certain attributes are not modifiable by the application.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, attribute lengths are restricted by @ref BLE_GATTS_ATTR_LENS_MAX.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied on a system attribute.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_VALUE_SET, uint32_t, sd_ble_gatts_value_set(uint16_t conn_handle, uint16_t handle, ble_gatts_value_t *p_value));
|
||||
|
||||
/**@brief Get the value of a given attribute.
|
||||
*
|
||||
* @note If the attribute value is longer than the size of the supplied buffer,
|
||||
* p_len will return the total attribute value length (excluding offset),
|
||||
* and not the number of bytes actually returned in p_data.
|
||||
* The application may use this information to allocate a suitable buffer size.
|
||||
*
|
||||
* @note When retrieving system attribute values with this function, the connection handle
|
||||
* may refer to an already disconnected connection. Refer to the documentation of
|
||||
* @ref sd_ble_gatts_sys_attr_get for further information.
|
||||
*
|
||||
* @param[in] conn_handle Connection handle. Ignored if the value does not belong to a system attribute.
|
||||
* @param[in] handle Attribute handle.
|
||||
* @param[in,out] p_value Attribute value information.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully retrieved the value of the attribute.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid attribute offset supplied.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid connection handle supplied on a system attribute.
|
||||
* @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_VALUE_GET, uint32_t, sd_ble_gatts_value_get(uint16_t conn_handle, uint16_t handle, ble_gatts_value_t *p_value));
|
||||
|
||||
/**@brief Notify or Indicate an attribute value.
|
||||
*
|
||||
* @details This function checks for the relevant Client Characteristic Configuration descriptor value to verify that the relevant operation
|
||||
* (notification or indication) has been enabled by the client. It is also able to update the attribute value before issuing the PDU, so that
|
||||
* the application can atomically perform a value update and a server initiated transaction with a single API call.
|
||||
* If the application chooses to indicate an attribute value, a @ref BLE_GATTS_EVT_HVC event will be issued as soon as the confirmation arrives from
|
||||
* the peer.
|
||||
*
|
||||
* @note The local attribute value may be updated even if an outgoing packet is not sent to the peer due to an error during execution.
|
||||
* The Attribute Table has been updated if one of the following error codes is returned: @ref NRF_ERROR_INVALID_STATE, @ref NRF_ERROR_BUSY,
|
||||
* @ref NRF_ERROR_FORBIDDEN, @ref BLE_ERROR_GATTS_SYS_ATTR_MISSING and @ref BLE_ERROR_NO_TX_PACKETS.
|
||||
* The caller can check whether the value has been updated by looking at the contents of *(p_hvx_params->p_len).
|
||||
*
|
||||
* @note It is important to note that a notification will <b>consume an application buffer</b>, and will therefore
|
||||
* generate a @ref BLE_EVT_TX_COMPLETE event when the packet has been transmitted. An indication on the other hand will use the
|
||||
* standard server internal buffer and thus will only generate a @ref BLE_GATTS_EVT_HVC event as soon as the confirmation
|
||||
* has been received from the peer. Please see the documentation of @ref sd_ble_tx_packet_count_get for more details.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_EVT_TX_COMPLETE, Transmission complete.}
|
||||
* @event{@ref BLE_GATTS_EVT_HVC, Confirmation received from peer.}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_HVX_SYS_ATTRS_MISSING_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_HVN_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_HVI_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_HVX_DISABLED_MSC}
|
||||
* @mmsc{@ref BLE_COMMON_APP_BUFF_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle Connection handle.
|
||||
* @param[in] p_hvx_params Pointer to an HVx parameters structure. If the p_data member contains a non-NULL pointer the attribute value will be updated with
|
||||
* the contents pointed by it before sending the notification or indication.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully queued a notification or indication for transmission, and optionally updated the attribute value.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true:
|
||||
* - Invalid Connection State
|
||||
* - Notifications and/or indications not enabled in the CCCD
|
||||
* - An ATT_MTU exchange is ongoing
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
|
||||
* @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied. Only attributes added directly by the application are available to notify and indicate.
|
||||
* @retval ::BLE_ERROR_GATTS_INVALID_ATTR_TYPE Invalid attribute type(s) supplied, only characteristic values may be notified and indicated.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND Attribute not found.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN The connection's current security level is lower than the one required by the write permissions of the CCCD associated with this characteristic.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied.
|
||||
* @retval ::NRF_ERROR_BUSY Procedure already in progress.
|
||||
* @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value.
|
||||
* @retval ::BLE_ERROR_NO_TX_PACKETS No available application packets for this connection, applies only to notifications.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_HVX, uint32_t, sd_ble_gatts_hvx(uint16_t conn_handle, ble_gatts_hvx_params_t const *p_hvx_params));
|
||||
|
||||
/**@brief Indicate the Service Changed attribute value.
|
||||
*
|
||||
* @details This call will send a Handle Value Indication to one or more peers connected to inform them that the Attribute
|
||||
* Table layout has changed. As soon as the peer has confirmed the indication, a @ref BLE_GATTS_EVT_SC_CONFIRM event will
|
||||
* be issued.
|
||||
*
|
||||
* @note Some of the restrictions and limitations that apply to @ref sd_ble_gatts_hvx also apply here.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_GATTS_EVT_SC_CONFIRM, Confirmation of attribute table change received from peer.}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_SC_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle Connection handle.
|
||||
* @param[in] start_handle Start of affected attribute handle range.
|
||||
* @param[in] end_handle End of affected attribute handle range.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully queued the Service Changed indication for transmission.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_NOT_SUPPORTED Service Changed not enabled at initialization. See @ref sd_ble_enable and @ref ble_gatts_enable_params_t.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE One or more of the following is true:
|
||||
* - Invalid Connection State
|
||||
* - Notifications and/or indications not enabled in the CCCD
|
||||
* - An ATT_MTU exchange is ongoing
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
|
||||
* @retval ::BLE_ERROR_INVALID_ATTR_HANDLE Invalid attribute handle(s) supplied, handles must be in the range populated by the application.
|
||||
* @retval ::NRF_ERROR_BUSY Procedure already in progress.
|
||||
* @retval ::BLE_ERROR_GATTS_SYS_ATTR_MISSING System attributes missing, use @ref sd_ble_gatts_sys_attr_set to set them to a known value.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_SERVICE_CHANGED, uint32_t, sd_ble_gatts_service_changed(uint16_t conn_handle, uint16_t start_handle, uint16_t end_handle));
|
||||
|
||||
/**@brief Respond to a Read/Write authorization request.
|
||||
*
|
||||
* @note This call should only be used as a response to a @ref BLE_GATTS_EVT_RW_AUTHORIZE_REQUEST event issued to the application.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_AUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_BUF_AUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_NOAUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_READ_REQ_AUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_WRITE_REQ_AUTH_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_QUEUE_FULL_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_QUEUED_WRITE_NOBUF_PEER_CANCEL_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle Connection handle.
|
||||
* @param[in] p_rw_authorize_reply_params Pointer to a structure with the attribute provided by the application.
|
||||
*
|
||||
* @note @ref ble_gatts_authorize_params_t::p_data is ignored when this function is used to respond
|
||||
* to a @ref BLE_GATTS_AUTHORIZE_TYPE_READ event if @ref ble_gatts_authorize_params_t::update
|
||||
* is set to 0.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully queued a response to the peer, and in the case of a write operation, Attribute Table updated.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no authorization request pending.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Authorization op invalid,
|
||||
* handle supplied does not match requested handle,
|
||||
* or invalid data to be written provided by the application.
|
||||
* @retval ::NRF_ERROR_BUSY The stack is busy. Retry at later time.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_RW_AUTHORIZE_REPLY, uint32_t, sd_ble_gatts_rw_authorize_reply(uint16_t conn_handle, ble_gatts_rw_authorize_reply_params_t const *p_rw_authorize_reply_params));
|
||||
|
||||
|
||||
/**@brief Update persistent system attribute information.
|
||||
*
|
||||
* @details Supply information about persistent system attributes to the stack,
|
||||
* previously obtained using @ref sd_ble_gatts_sys_attr_get.
|
||||
* This call is only allowed for active connections, and is usually
|
||||
* made immediately after a connection is established with an known bonded device,
|
||||
* often as a response to a @ref BLE_GATTS_EVT_SYS_ATTR_MISSING.
|
||||
*
|
||||
* p_sysattrs may point directly to the application's stored copy of the system attributes
|
||||
* obtained using @ref sd_ble_gatts_sys_attr_get.
|
||||
* If the pointer is NULL, the system attribute info is initialized, assuming that
|
||||
* the application does not have any previously saved system attribute data for this device.
|
||||
*
|
||||
* @note The state of persistent system attributes is reset upon connection establishment and then remembered for its duration.
|
||||
*
|
||||
* @note If this call returns with an error code different from @ref NRF_SUCCESS, the storage of persistent system attributes may have been completed only partially.
|
||||
* This means that the state of the attribute table is undefined, and the application should either provide a new set of attributes using this same call or
|
||||
* reset the SoftDevice to return to a known state.
|
||||
*
|
||||
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS is used with this function, only the system attributes included in system services will be modified.
|
||||
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS is used with this function, only the system attributes included in user services will be modified.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_HVX_SYS_ATTRS_MISSING_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_SYS_ATTRS_UNK_PEER_MSC}
|
||||
* @mmsc{@ref BLE_GATTS_SYS_ATTRS_BONDED_PEER_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle Connection handle.
|
||||
* @param[in] p_sys_attr_data Pointer to a saved copy of system attributes supplied to the stack, or NULL.
|
||||
* @param[in] len Size of data pointed by p_sys_attr_data, in octets.
|
||||
* @param[in] flags Optional additional flags, see @ref BLE_GATTS_SYS_ATTR_FLAGS
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully set the system attribute information.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid flags supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_DATA Invalid data supplied, the data should be exactly the same as retrieved with @ref sd_ble_gatts_sys_attr_get.
|
||||
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
|
||||
* @retval ::NRF_ERROR_BUSY The stack is busy. Retry at later time.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_SYS_ATTR_SET, uint32_t, sd_ble_gatts_sys_attr_set(uint16_t conn_handle, uint8_t const *p_sys_attr_data, uint16_t len, uint32_t flags));
|
||||
|
||||
|
||||
/**@brief Retrieve persistent system attribute information from the stack.
|
||||
*
|
||||
* @details This call is used to retrieve information about values to be stored perisistently by the application
|
||||
* during the lifetime of a connection or after it has been terminated. When a new connection is established with the same bonded device,
|
||||
* the system attribute information retrieved with this function should be restored using using @ref sd_ble_gatts_sys_attr_set.
|
||||
* If retrieved after disconnection, the data should be read before a new connection established. The connection handle for
|
||||
* the previous, now disconnected, connection will remain valid until a new one is created to allow this API call to refer to it.
|
||||
* Connection handles belonging to active connections can be used as well, but care should be taken since the system attributes
|
||||
* may be written to at any time by the peer during a connection's lifetime.
|
||||
*
|
||||
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_SYS_SRVCS is used with this function, only the system attributes included in system services will be returned.
|
||||
* @note When the @ref BLE_GATTS_SYS_ATTR_FLAG_USR_SRVCS is used with this function, only the system attributes included in user services will be returned.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_SYS_ATTRS_BONDED_PEER_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle Connection handle of the recently terminated connection.
|
||||
* @param[out] p_sys_attr_data Pointer to a buffer where updated information about system attributes will be filled in. The format of the data is described
|
||||
* in @ref BLE_GATTS_SYS_ATTRS_FORMAT. NULL can be provided to obtain the length of the data.
|
||||
* @param[in,out] p_len Size of application buffer if p_sys_attr_data is not NULL. Unconditially updated to actual length of system attribute data.
|
||||
* @param[in] flags Optional additional flags, see @ref BLE_GATTS_SYS_ATTR_FLAGS
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully retrieved the system attribute information.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid flags supplied.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE The system attribute information did not fit into the provided buffer.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND No system attributes found.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_SYS_ATTR_GET, uint32_t, sd_ble_gatts_sys_attr_get(uint16_t conn_handle, uint8_t *p_sys_attr_data, uint16_t *p_len, uint32_t flags));
|
||||
|
||||
|
||||
/**@brief Retrieve the first valid user attribute handle.
|
||||
*
|
||||
* @param[out] p_handle Pointer to an integer where the handle will be stored.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully retrieved the handle.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_INITIAL_USER_HANDLE_GET, uint32_t, sd_ble_gatts_initial_user_handle_get(uint16_t *p_handle));
|
||||
|
||||
/**@brief Retrieve the attribute UUID and/or metadata.
|
||||
*
|
||||
* @param[in] handle Attribute handle
|
||||
* @param[out] p_uuid UUID of the attribute. Use NULL to omit this field.
|
||||
* @param[out] p_md Metadata of the attribute. Use NULL to omit this field.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully retrieved the attribute metadata,
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameters supplied. Returned when both @c p_uuid and @c p_md are NULL.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND Attribute was not found.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_ATTR_GET, uint32_t, sd_ble_gatts_attr_get(uint16_t handle, ble_uuid_t * p_uuid, ble_gatts_attr_md_t * p_md));
|
||||
|
||||
/**@brief Reply to an ATT_MTU exchange request by sending an Exchange MTU Response to the client.
|
||||
*
|
||||
* @details This function is only used to reply to a @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST event.
|
||||
*
|
||||
* @details The SoftDevice sets ATT_MTU to the minimum of:
|
||||
* - The Client RX MTU value from @ref BLE_GATTS_EVT_EXCHANGE_MTU_REQUEST, and
|
||||
* - The Server RX MTU value.
|
||||
*
|
||||
* However, the SoftDevice never sets ATT_MTU lower than @ref BLE_GATT_MTU_SIZE_DEFAULT.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_EVT_DATA_LENGTH_CHANGED, Generated if a data length update procedure is performed after the ATT_MTU exchange.}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_GATTS_MTU_EXCHANGE}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle The connection handle identifying the connection to perform this procedure on.
|
||||
* @param[in] server_rx_mtu Server RX MTU size.
|
||||
* - The minimum value is @ref BLE_GATT_MTU_SIZE_DEFAULT.
|
||||
* - The maximum value is @ref ble_gatt_enable_params_t::att_mtu.
|
||||
* - The value must be equal to Client RX MTU size given in @ref sd_ble_gattc_exchange_mtu_request
|
||||
* if an ATT_MTU exchange has already been performed in the other direction.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully sent response to the client.
|
||||
* @retval ::BLE_ERROR_INVALID_CONN_HANDLE Invalid Connection Handle.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE Invalid Connection State or no ATT_MTU exchange request pending.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid Server RX MTU size supplied.
|
||||
* @retval ::NRF_ERROR_BUSY The stack is busy. Retry at later time.
|
||||
*/
|
||||
SVCALL(SD_BLE_GATTS_EXCHANGE_MTU_REPLY, uint32_t, sd_ble_gatts_exchange_mtu_reply(uint16_t conn_handle, uint16_t server_rx_mtu));
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BLE_GATTS_H__
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_COMMON
|
||||
@{
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BLE_HCI_H__
|
||||
#define BLE_HCI_H__
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup BLE_HCI_STATUS_CODES Bluetooth status codes
|
||||
* @{ */
|
||||
|
||||
#define BLE_HCI_STATUS_CODE_SUCCESS 0x00 /**< Success. */
|
||||
#define BLE_HCI_STATUS_CODE_UNKNOWN_BTLE_COMMAND 0x01 /**< Unknown BLE Command. */
|
||||
#define BLE_HCI_STATUS_CODE_UNKNOWN_CONNECTION_IDENTIFIER 0x02 /**< Unknown Connection Identifier. */
|
||||
/*0x03 Hardware Failure
|
||||
0x04 Page Timeout
|
||||
*/
|
||||
#define BLE_HCI_AUTHENTICATION_FAILURE 0x05 /**< Authentication Failure. */
|
||||
#define BLE_HCI_STATUS_CODE_PIN_OR_KEY_MISSING 0x06 /**< Pin or Key missing. */
|
||||
#define BLE_HCI_MEMORY_CAPACITY_EXCEEDED 0x07 /**< Memory Capacity Exceeded. */
|
||||
#define BLE_HCI_CONNECTION_TIMEOUT 0x08 /**< Connection Timeout. */
|
||||
/*0x09 Connection Limit Exceeded
|
||||
0x0A Synchronous Connection Limit To A Device Exceeded
|
||||
0x0B ACL Connection Already Exists*/
|
||||
#define BLE_HCI_STATUS_CODE_COMMAND_DISALLOWED 0x0C /**< Command Disallowed. */
|
||||
/*0x0D Connection Rejected due to Limited Resources
|
||||
0x0E Connection Rejected Due To Security Reasons
|
||||
0x0F Connection Rejected due to Unacceptable BD_ADDR
|
||||
0x10 Connection Accept Timeout Exceeded
|
||||
0x11 Unsupported Feature or Parameter Value*/
|
||||
#define BLE_HCI_STATUS_CODE_INVALID_BTLE_COMMAND_PARAMETERS 0x12 /**< Invalid BLE Command Parameters. */
|
||||
#define BLE_HCI_REMOTE_USER_TERMINATED_CONNECTION 0x13 /**< Remote User Terminated Connection. */
|
||||
#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_LOW_RESOURCES 0x14 /**< Remote Device Terminated Connection due to low resources.*/
|
||||
#define BLE_HCI_REMOTE_DEV_TERMINATION_DUE_TO_POWER_OFF 0x15 /**< Remote Device Terminated Connection due to power off. */
|
||||
#define BLE_HCI_LOCAL_HOST_TERMINATED_CONNECTION 0x16 /**< Local Host Terminated Connection. */
|
||||
/*
|
||||
0x17 Repeated Attempts
|
||||
0x18 Pairing Not Allowed
|
||||
0x19 Unknown LMP PDU
|
||||
*/
|
||||
#define BLE_HCI_UNSUPPORTED_REMOTE_FEATURE 0x1A /**< Unsupported Remote Feature. */
|
||||
/*
|
||||
0x1B SCO Offset Rejected
|
||||
0x1C SCO Interval Rejected
|
||||
0x1D SCO Air Mode Rejected*/
|
||||
#define BLE_HCI_STATUS_CODE_INVALID_LMP_PARAMETERS 0x1E /**< Invalid LMP Parameters. */
|
||||
#define BLE_HCI_STATUS_CODE_UNSPECIFIED_ERROR 0x1F /**< Unspecified Error. */
|
||||
/*0x20 Unsupported LMP Parameter Value
|
||||
0x21 Role Change Not Allowed
|
||||
*/
|
||||
#define BLE_HCI_STATUS_CODE_LMP_RESPONSE_TIMEOUT 0x22 /**< LMP Response Timeout. */
|
||||
#define BLE_HCI_STATUS_CODE_LMP_ERROR_TRANSACTION_COLLISION 0x23 /**< LMP Error Transaction Collision/LL Procedure Collision. */
|
||||
#define BLE_HCI_STATUS_CODE_LMP_PDU_NOT_ALLOWED 0x24 /**< LMP PDU Not Allowed. */
|
||||
/*0x25 Encryption Mode Not Acceptable
|
||||
0x26 Link Key Can Not be Changed
|
||||
0x27 Requested QoS Not Supported
|
||||
*/
|
||||
#define BLE_HCI_INSTANT_PASSED 0x28 /**< Instant Passed. */
|
||||
#define BLE_HCI_PAIRING_WITH_UNIT_KEY_UNSUPPORTED 0x29 /**< Pairing with Unit Key Unsupported. */
|
||||
#define BLE_HCI_DIFFERENT_TRANSACTION_COLLISION 0x2A /**< Different Transaction Collision. */
|
||||
/*
|
||||
0x2B Reserved
|
||||
0x2C QoS Unacceptable Parameter
|
||||
0x2D QoS Rejected
|
||||
0x2E Channel Classification Not Supported
|
||||
0x2F Insufficient Security
|
||||
0x30 Parameter Out Of Mandatory Range
|
||||
0x31 Reserved
|
||||
0x32 Role Switch Pending
|
||||
0x33 Reserved
|
||||
0x34 Reserved Slot Violation
|
||||
0x35 Role Switch Failed
|
||||
0x36 Extended Inquiry Response Too Large
|
||||
0x37 Secure Simple Pairing Not Supported By Host.
|
||||
0x38 Host Busy - Pairing
|
||||
0x39 Connection Rejected due to No Suitable Channel Found*/
|
||||
#define BLE_HCI_CONTROLLER_BUSY 0x3A /**< Controller Busy. */
|
||||
#define BLE_HCI_CONN_INTERVAL_UNACCEPTABLE 0x3B /**< Connection Interval Unacceptable. */
|
||||
#define BLE_HCI_DIRECTED_ADVERTISER_TIMEOUT 0x3C /**< Directed Adverisement Timeout. */
|
||||
#define BLE_HCI_CONN_TERMINATED_DUE_TO_MIC_FAILURE 0x3D /**< Connection Terminated due to MIC Failure. */
|
||||
#define BLE_HCI_CONN_FAILED_TO_BE_ESTABLISHED 0x3E /**< Connection Failed to be Established. */
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BLE_HCI_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,204 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_L2CAP Logical Link Control and Adaptation Protocol (L2CAP)
|
||||
@{
|
||||
@brief Definitions and prototypes for the L2CAP interface.
|
||||
*/
|
||||
|
||||
#ifndef BLE_L2CAP_H__
|
||||
#define BLE_L2CAP_H__
|
||||
|
||||
#include "ble_types.h"
|
||||
#include "ble_ranges.h"
|
||||
#include "ble_err.h"
|
||||
#include "nrf_svc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@addtogroup BLE_L2CAP_ENUMERATIONS Enumerations
|
||||
* @{ */
|
||||
|
||||
/**@brief L2CAP API SVC numbers. */
|
||||
enum BLE_L2CAP_SVCS
|
||||
{
|
||||
SD_BLE_L2CAP_CID_REGISTER = BLE_L2CAP_SVC_BASE, /**< Register a CID. */
|
||||
SD_BLE_L2CAP_CID_UNREGISTER, /**< Unregister a CID. */
|
||||
SD_BLE_L2CAP_TX /**< Transmit a packet. */
|
||||
};
|
||||
|
||||
/**@brief L2CAP Event IDs. */
|
||||
enum BLE_L2CAP_EVTS
|
||||
{
|
||||
BLE_L2CAP_EVT_RX = BLE_L2CAP_EVT_BASE /**< L2CAP packet received. */
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/**@addtogroup BLE_L2CAP_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/**@defgroup BLE_ERRORS_L2CAP SVC return values specific to L2CAP
|
||||
* @{ */
|
||||
#define BLE_ERROR_L2CAP_CID_IN_USE (NRF_L2CAP_ERR_BASE + 0x000) /**< CID already in use. */
|
||||
/** @} */
|
||||
|
||||
/**@brief Default L2CAP MTU. */
|
||||
#define BLE_L2CAP_MTU_DEF (23)
|
||||
|
||||
/**@brief Invalid Channel Identifier. */
|
||||
#define BLE_L2CAP_CID_INVALID (0x0000)
|
||||
|
||||
/**@brief Dynamic Channel Identifier base. */
|
||||
#define BLE_L2CAP_CID_DYN_BASE (0x0040)
|
||||
|
||||
/**@brief Maximum amount of dynamic CIDs. */
|
||||
#define BLE_L2CAP_CID_DYN_MAX (8)
|
||||
|
||||
/** @} */
|
||||
|
||||
/**@addtogroup BLE_L2CAP_STRUCTURES Structures
|
||||
* @{ */
|
||||
|
||||
/**@brief Packet header format for L2CAP transmission. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t len; /**< Length of valid info in data member. */
|
||||
uint16_t cid; /**< Channel ID on which packet is transmitted. */
|
||||
} ble_l2cap_header_t;
|
||||
|
||||
|
||||
/**@brief L2CAP Received packet event report. */
|
||||
typedef struct
|
||||
{
|
||||
ble_l2cap_header_t header; /**< L2CAP packet header. */
|
||||
uint8_t data[1]; /**< Packet data. @note This is a variable length array. The size of 1 indicated is only a placeholder for compilation.
|
||||
See @ref sd_ble_evt_get for more information on how to use event structures with variable length array members. */
|
||||
} ble_l2cap_evt_rx_t;
|
||||
|
||||
|
||||
/**@brief L2CAP event callback event structure. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t conn_handle; /**< Connection Handle on which event occured. */
|
||||
union
|
||||
{
|
||||
ble_l2cap_evt_rx_t rx; /**< RX Event parameters. */
|
||||
} params; /**< Event Parameters. */
|
||||
} ble_l2cap_evt_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/**@addtogroup BLE_L2CAP_FUNCTIONS Functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Register a CID with L2CAP.
|
||||
*
|
||||
* @details This registers a higher protocol layer with the L2CAP multiplexer, and is requried prior to all operations on the CID.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_L2CAP_API_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] cid L2CAP CID.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully registered a CID with the L2CAP layer.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, CID must be above @ref BLE_L2CAP_CID_DYN_BASE.
|
||||
* @retval ::BLE_ERROR_L2CAP_CID_IN_USE L2CAP CID already in use.
|
||||
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
|
||||
*/
|
||||
SVCALL(SD_BLE_L2CAP_CID_REGISTER, uint32_t, sd_ble_l2cap_cid_register(uint16_t cid));
|
||||
|
||||
/**@brief Unregister a CID with L2CAP.
|
||||
*
|
||||
* @details This unregisters a previously registerd higher protocol layer with the L2CAP multiplexer.
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_L2CAP_API_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] cid L2CAP CID.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully unregistered the CID.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND CID not previously registered.
|
||||
*/
|
||||
SVCALL(SD_BLE_L2CAP_CID_UNREGISTER, uint32_t, sd_ble_l2cap_cid_unregister(uint16_t cid));
|
||||
|
||||
/**@brief Transmit an L2CAP packet.
|
||||
*
|
||||
* @note It is important to note that a call to this function will <b>consume an application packet</b>, and will therefore
|
||||
* generate a @ref BLE_EVT_TX_COMPLETE event when the packet has been transmitted.
|
||||
* Please see the documentation of @ref sd_ble_tx_packet_count_get for more details.
|
||||
*
|
||||
* @events
|
||||
* @event{@ref BLE_EVT_TX_COMPLETE}
|
||||
* @event{@ref BLE_L2CAP_EVT_RX}
|
||||
* @endevents
|
||||
*
|
||||
* @mscs
|
||||
* @mmsc{@ref BLE_L2CAP_API_MSC}
|
||||
* @endmscs
|
||||
*
|
||||
* @param[in] conn_handle Connection Handle.
|
||||
* @param[in] p_header Pointer to a packet header containing length and CID.
|
||||
* @param[in] p_data Pointer to the data to be transmitted.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS Successfully queued an L2CAP packet for transmission.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM Invalid parameter(s) supplied, CIDs must be registered beforehand with @ref sd_ble_l2cap_cid_register.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND CID not found.
|
||||
* @retval ::NRF_ERROR_NO_MEM Not enough memory to complete operation.
|
||||
* @retval ::BLE_ERROR_NO_TX_PACKETS Not enough application packets available.
|
||||
* @retval ::NRF_ERROR_DATA_SIZE Invalid data size(s) supplied, see @ref BLE_L2CAP_MTU_DEF.
|
||||
*/
|
||||
SVCALL(SD_BLE_L2CAP_TX, uint32_t, sd_ble_l2cap_tx(uint16_t conn_handle, ble_l2cap_header_t const *p_header, uint8_t const *p_data));
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // BLE_L2CAP_H__
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,140 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_COMMON
|
||||
@{
|
||||
@defgroup ble_ranges Module specific SVC, event and option number subranges
|
||||
@{
|
||||
|
||||
@brief Definition of SVC, event and option number subranges for each API module.
|
||||
|
||||
@note
|
||||
SVCs, event and option numbers are split into subranges for each API module.
|
||||
Each module receives its entire allocated range of SVC calls, whether implemented or not,
|
||||
but return BLE_ERROR_NOT_SUPPORTED for unimplemented or undefined calls in its range.
|
||||
|
||||
Note that the symbols BLE_<module>_SVC_LAST is the end of the allocated SVC range,
|
||||
rather than the last SVC function call actually defined and implemented.
|
||||
|
||||
Specific SVC, event and option values are defined in each module's ble_<module>.h file,
|
||||
which defines names of each individual SVC code based on the range start value.
|
||||
*/
|
||||
|
||||
#ifndef BLE_RANGES_H__
|
||||
#define BLE_RANGES_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define BLE_SVC_BASE 0x60 /**< Common BLE SVC base. */
|
||||
#define BLE_SVC_LAST 0x6B /**< Common BLE SVC last. */
|
||||
|
||||
|
||||
#define BLE_GAP_SVC_BASE 0x6C /**< GAP BLE SVC base. */
|
||||
#define BLE_GAP_SVC_LAST 0x93 /**< GAP BLE SVC last. */
|
||||
|
||||
|
||||
#define BLE_GATTC_SVC_BASE 0x94 /**< GATTC BLE SVC base. */
|
||||
#define BLE_GATTC_SVC_LAST 0x9F /**< GATTC BLE SVC last. */
|
||||
|
||||
|
||||
#define BLE_GATTS_SVC_BASE 0xA0 /**< GATTS BLE SVC base. */
|
||||
#define BLE_GATTS_SVC_LAST 0xAF /**< GATTS BLE SVC last. */
|
||||
|
||||
|
||||
#define BLE_L2CAP_SVC_BASE 0xB0 /**< L2CAP BLE SVC base. */
|
||||
#define BLE_L2CAP_SVC_LAST 0xBF /**< L2CAP BLE SVC last. */
|
||||
|
||||
|
||||
#define BLE_EVT_INVALID 0x00 /**< Invalid BLE Event. */
|
||||
|
||||
|
||||
#define BLE_EVT_BASE 0x01 /**< Common BLE Event base. */
|
||||
#define BLE_EVT_LAST 0x0F /**< Common BLE Event last. */
|
||||
|
||||
|
||||
#define BLE_GAP_EVT_BASE 0x10 /**< GAP BLE Event base. */
|
||||
#define BLE_GAP_EVT_LAST 0x2F /**< GAP BLE Event last. */
|
||||
|
||||
|
||||
#define BLE_GATTC_EVT_BASE 0x30 /**< GATTC BLE Event base. */
|
||||
#define BLE_GATTC_EVT_LAST 0x4F /**< GATTC BLE Event last. */
|
||||
|
||||
|
||||
#define BLE_GATTS_EVT_BASE 0x50 /**< GATTS BLE Event base. */
|
||||
#define BLE_GATTS_EVT_LAST 0x6F /**< GATTS BLE Event last. */
|
||||
|
||||
|
||||
#define BLE_L2CAP_EVT_BASE 0x70 /**< L2CAP BLE Event base. */
|
||||
#define BLE_L2CAP_EVT_LAST 0x8F /**< L2CAP BLE Event last. */
|
||||
|
||||
|
||||
#define BLE_OPT_INVALID 0x00 /**< Invalid BLE Option. */
|
||||
|
||||
|
||||
#define BLE_OPT_BASE 0x01 /**< Common BLE Option base. */
|
||||
#define BLE_OPT_LAST 0x1F /**< Common BLE Option last. */
|
||||
|
||||
|
||||
#define BLE_GAP_OPT_BASE 0x20 /**< GAP BLE Option base. */
|
||||
#define BLE_GAP_OPT_LAST 0x3F /**< GAP BLE Option last. */
|
||||
|
||||
|
||||
#define BLE_GATTC_OPT_BASE 0x40 /**< GATTC BLE Option base. */
|
||||
#define BLE_GATTC_OPT_LAST 0x5F /**< GATTC BLE Option last. */
|
||||
|
||||
|
||||
#define BLE_GATTS_OPT_BASE 0x60 /**< GATTS BLE Option base. */
|
||||
#define BLE_GATTS_OPT_LAST 0x7F /**< GATTS BLE Option last. */
|
||||
|
||||
|
||||
#define BLE_L2CAP_OPT_BASE 0x80 /**< L2CAP BLE Option base. */
|
||||
#define BLE_L2CAP_OPT_LAST 0x9F /**< L2CAP BLE Option last. */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif /* BLE_RANGES_H__ */
|
||||
|
||||
/**
|
||||
@}
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,207 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
@addtogroup BLE_COMMON
|
||||
@{
|
||||
@defgroup ble_types Common types and macro definitions
|
||||
@{
|
||||
|
||||
@brief Common types and macro definitions for the BLE SoftDevice.
|
||||
*/
|
||||
|
||||
#ifndef BLE_TYPES_H__
|
||||
#define BLE_TYPES_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup BLE_TYPES_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/** @defgroup BLE_CONN_HANDLES BLE Connection Handles
|
||||
* @{ */
|
||||
#define BLE_CONN_HANDLE_INVALID 0xFFFF /**< Invalid Connection Handle. */
|
||||
#define BLE_CONN_HANDLE_ALL 0xFFFE /**< Applies to all Connection Handles. */
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @defgroup BLE_UUID_VALUES Assigned Values for BLE UUIDs
|
||||
* @{ */
|
||||
/* Generic UUIDs, applicable to all services */
|
||||
#define BLE_UUID_UNKNOWN 0x0000 /**< Reserved UUID. */
|
||||
#define BLE_UUID_SERVICE_PRIMARY 0x2800 /**< Primary Service. */
|
||||
#define BLE_UUID_SERVICE_SECONDARY 0x2801 /**< Secondary Service. */
|
||||
#define BLE_UUID_SERVICE_INCLUDE 0x2802 /**< Include. */
|
||||
#define BLE_UUID_CHARACTERISTIC 0x2803 /**< Characteristic. */
|
||||
#define BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP 0x2900 /**< Characteristic Extended Properties Descriptor. */
|
||||
#define BLE_UUID_DESCRIPTOR_CHAR_USER_DESC 0x2901 /**< Characteristic User Description Descriptor. */
|
||||
#define BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG 0x2902 /**< Client Characteristic Configuration Descriptor. */
|
||||
#define BLE_UUID_DESCRIPTOR_SERVER_CHAR_CONFIG 0x2903 /**< Server Characteristic Configuration Descriptor. */
|
||||
#define BLE_UUID_DESCRIPTOR_CHAR_PRESENTATION_FORMAT 0x2904 /**< Characteristic Presentation Format Descriptor. */
|
||||
#define BLE_UUID_DESCRIPTOR_CHAR_AGGREGATE_FORMAT 0x2905 /**< Characteristic Aggregate Format Descriptor. */
|
||||
/* GATT specific UUIDs */
|
||||
#define BLE_UUID_GATT 0x1801 /**< Generic Attribute Profile. */
|
||||
#define BLE_UUID_GATT_CHARACTERISTIC_SERVICE_CHANGED 0x2A05 /**< Service Changed Characteristic. */
|
||||
/* GAP specific UUIDs */
|
||||
#define BLE_UUID_GAP 0x1800 /**< Generic Access Profile. */
|
||||
#define BLE_UUID_GAP_CHARACTERISTIC_DEVICE_NAME 0x2A00 /**< Device Name Characteristic. */
|
||||
#define BLE_UUID_GAP_CHARACTERISTIC_APPEARANCE 0x2A01 /**< Appearance Characteristic. */
|
||||
#define BLE_UUID_GAP_CHARACTERISTIC_RECONN_ADDR 0x2A03 /**< Reconnection Address Characteristic. */
|
||||
#define BLE_UUID_GAP_CHARACTERISTIC_PPCP 0x2A04 /**< Peripheral Preferred Connection Parameters Characteristic. */
|
||||
#define BLE_UUID_GAP_CHARACTERISTIC_CAR 0x2AA6 /**< Central Address Resolution Characteristic. */
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @defgroup BLE_UUID_TYPES Types of UUID
|
||||
* @{ */
|
||||
#define BLE_UUID_TYPE_UNKNOWN 0x00 /**< Invalid UUID type. */
|
||||
#define BLE_UUID_TYPE_BLE 0x01 /**< Bluetooth SIG UUID (16-bit). */
|
||||
#define BLE_UUID_TYPE_VENDOR_BEGIN 0x02 /**< Vendor UUID types start at this index (128-bit). */
|
||||
/** @} */
|
||||
|
||||
|
||||
/** @defgroup BLE_APPEARANCES Bluetooth Appearance values
|
||||
* @note Retrieved from http://developer.bluetooth.org/gatt/characteristics/Pages/CharacteristicViewer.aspx?u=org.bluetooth.characteristic.gap.appearance.xml
|
||||
* @{ */
|
||||
#define BLE_APPEARANCE_UNKNOWN 0 /**< Unknown. */
|
||||
#define BLE_APPEARANCE_GENERIC_PHONE 64 /**< Generic Phone. */
|
||||
#define BLE_APPEARANCE_GENERIC_COMPUTER 128 /**< Generic Computer. */
|
||||
#define BLE_APPEARANCE_GENERIC_WATCH 192 /**< Generic Watch. */
|
||||
#define BLE_APPEARANCE_WATCH_SPORTS_WATCH 193 /**< Watch: Sports Watch. */
|
||||
#define BLE_APPEARANCE_GENERIC_CLOCK 256 /**< Generic Clock. */
|
||||
#define BLE_APPEARANCE_GENERIC_DISPLAY 320 /**< Generic Display. */
|
||||
#define BLE_APPEARANCE_GENERIC_REMOTE_CONTROL 384 /**< Generic Remote Control. */
|
||||
#define BLE_APPEARANCE_GENERIC_EYE_GLASSES 448 /**< Generic Eye-glasses. */
|
||||
#define BLE_APPEARANCE_GENERIC_TAG 512 /**< Generic Tag. */
|
||||
#define BLE_APPEARANCE_GENERIC_KEYRING 576 /**< Generic Keyring. */
|
||||
#define BLE_APPEARANCE_GENERIC_MEDIA_PLAYER 640 /**< Generic Media Player. */
|
||||
#define BLE_APPEARANCE_GENERIC_BARCODE_SCANNER 704 /**< Generic Barcode Scanner. */
|
||||
#define BLE_APPEARANCE_GENERIC_THERMOMETER 768 /**< Generic Thermometer. */
|
||||
#define BLE_APPEARANCE_THERMOMETER_EAR 769 /**< Thermometer: Ear. */
|
||||
#define BLE_APPEARANCE_GENERIC_HEART_RATE_SENSOR 832 /**< Generic Heart rate Sensor. */
|
||||
#define BLE_APPEARANCE_HEART_RATE_SENSOR_HEART_RATE_BELT 833 /**< Heart Rate Sensor: Heart Rate Belt. */
|
||||
#define BLE_APPEARANCE_GENERIC_BLOOD_PRESSURE 896 /**< Generic Blood Pressure. */
|
||||
#define BLE_APPEARANCE_BLOOD_PRESSURE_ARM 897 /**< Blood Pressure: Arm. */
|
||||
#define BLE_APPEARANCE_BLOOD_PRESSURE_WRIST 898 /**< Blood Pressure: Wrist. */
|
||||
#define BLE_APPEARANCE_GENERIC_HID 960 /**< Human Interface Device (HID). */
|
||||
#define BLE_APPEARANCE_HID_KEYBOARD 961 /**< Keyboard (HID Subtype). */
|
||||
#define BLE_APPEARANCE_HID_MOUSE 962 /**< Mouse (HID Subtype). */
|
||||
#define BLE_APPEARANCE_HID_JOYSTICK 963 /**< Joystiq (HID Subtype). */
|
||||
#define BLE_APPEARANCE_HID_GAMEPAD 964 /**< Gamepad (HID Subtype). */
|
||||
#define BLE_APPEARANCE_HID_DIGITIZERSUBTYPE 965 /**< Digitizer Tablet (HID Subtype). */
|
||||
#define BLE_APPEARANCE_HID_CARD_READER 966 /**< Card Reader (HID Subtype). */
|
||||
#define BLE_APPEARANCE_HID_DIGITAL_PEN 967 /**< Digital Pen (HID Subtype). */
|
||||
#define BLE_APPEARANCE_HID_BARCODE 968 /**< Barcode Scanner (HID Subtype). */
|
||||
#define BLE_APPEARANCE_GENERIC_GLUCOSE_METER 1024 /**< Generic Glucose Meter. */
|
||||
#define BLE_APPEARANCE_GENERIC_RUNNING_WALKING_SENSOR 1088 /**< Generic Running Walking Sensor. */
|
||||
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_IN_SHOE 1089 /**< Running Walking Sensor: In-Shoe. */
|
||||
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_SHOE 1090 /**< Running Walking Sensor: On-Shoe. */
|
||||
#define BLE_APPEARANCE_RUNNING_WALKING_SENSOR_ON_HIP 1091 /**< Running Walking Sensor: On-Hip. */
|
||||
#define BLE_APPEARANCE_GENERIC_CYCLING 1152 /**< Generic Cycling. */
|
||||
#define BLE_APPEARANCE_CYCLING_CYCLING_COMPUTER 1153 /**< Cycling: Cycling Computer. */
|
||||
#define BLE_APPEARANCE_CYCLING_SPEED_SENSOR 1154 /**< Cycling: Speed Sensor. */
|
||||
#define BLE_APPEARANCE_CYCLING_CADENCE_SENSOR 1155 /**< Cycling: Cadence Sensor. */
|
||||
#define BLE_APPEARANCE_CYCLING_POWER_SENSOR 1156 /**< Cycling: Power Sensor. */
|
||||
#define BLE_APPEARANCE_CYCLING_SPEED_CADENCE_SENSOR 1157 /**< Cycling: Speed and Cadence Sensor. */
|
||||
#define BLE_APPEARANCE_GENERIC_PULSE_OXIMETER 3136 /**< Generic Pulse Oximeter. */
|
||||
#define BLE_APPEARANCE_PULSE_OXIMETER_FINGERTIP 3137 /**< Fingertip (Pulse Oximeter subtype). */
|
||||
#define BLE_APPEARANCE_PULSE_OXIMETER_WRIST_WORN 3138 /**< Wrist Worn(Pulse Oximeter subtype). */
|
||||
#define BLE_APPEARANCE_GENERIC_WEIGHT_SCALE 3200 /**< Generic Weight Scale. */
|
||||
#define BLE_APPEARANCE_GENERIC_OUTDOOR_SPORTS_ACT 5184 /**< Generic Outdoor Sports Activity. */
|
||||
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_DISP 5185 /**< Location Display Device (Outdoor Sports Activity subtype). */
|
||||
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_DISP 5186 /**< Location and Navigation Display Device (Outdoor Sports Activity subtype). */
|
||||
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_POD 5187 /**< Location Pod (Outdoor Sports Activity subtype). */
|
||||
#define BLE_APPEARANCE_OUTDOOR_SPORTS_ACT_LOC_AND_NAV_POD 5188 /**< Location and Navigation Pod (Outdoor Sports Activity subtype). */
|
||||
/** @} */
|
||||
|
||||
/** @brief Set .type and .uuid fields of ble_uuid_struct to specified uuid value. */
|
||||
#define BLE_UUID_BLE_ASSIGN(instance, value) do {\
|
||||
instance.type = BLE_UUID_TYPE_BLE; \
|
||||
instance.uuid = value;} while(0)
|
||||
|
||||
/** @brief Copy type and uuid members from src to dst ble_uuid_t pointer. Both pointers must be valid/non-null. */
|
||||
#define BLE_UUID_COPY_PTR(dst, src) do {\
|
||||
(dst)->type = (src)->type; \
|
||||
(dst)->uuid = (src)->uuid;} while(0)
|
||||
|
||||
/** @brief Copy type and uuid members from src to dst ble_uuid_t struct. */
|
||||
#define BLE_UUID_COPY_INST(dst, src) do {\
|
||||
(dst).type = (src).type; \
|
||||
(dst).uuid = (src).uuid;} while(0)
|
||||
|
||||
/** @brief Compare for equality both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */
|
||||
#define BLE_UUID_EQ(p_uuid1, p_uuid2) \
|
||||
(((p_uuid1)->type == (p_uuid2)->type) && ((p_uuid1)->uuid == (p_uuid2)->uuid))
|
||||
|
||||
/** @brief Compare for difference both type and uuid members of two (valid, non-null) ble_uuid_t pointers. */
|
||||
#define BLE_UUID_NEQ(p_uuid1, p_uuid2) \
|
||||
(((p_uuid1)->type != (p_uuid2)->type) || ((p_uuid1)->uuid != (p_uuid2)->uuid))
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup BLE_TYPES_STRUCTURES Structures
|
||||
* @{ */
|
||||
|
||||
/** @brief 128 bit UUID values. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t uuid128[16]; /**< Little-Endian UUID bytes. */
|
||||
} ble_uuid128_t;
|
||||
|
||||
/** @brief Bluetooth Low Energy UUID type, encapsulates both 16-bit and 128-bit UUIDs. */
|
||||
typedef struct
|
||||
{
|
||||
uint16_t uuid; /**< 16-bit UUID value or octets 12-13 of 128-bit UUID. */
|
||||
uint8_t type; /**< UUID type, see @ref BLE_UUID_TYPES. If type is @ref BLE_UUID_TYPE_UNKNOWN, the value of uuid is undefined. */
|
||||
} ble_uuid_t;
|
||||
|
||||
/** @} */
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BLE_TYPES_H__ */
|
||||
|
||||
/**
|
||||
@}
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,219 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
@defgroup nrf_mbr_api Master Boot Record API
|
||||
@{
|
||||
|
||||
@brief APIs for updating SoftDevice and BootLoader
|
||||
|
||||
*/
|
||||
|
||||
/* Header guard */
|
||||
#ifndef NRF_MBR_H__
|
||||
#define NRF_MBR_H__
|
||||
|
||||
#include "nrf_svc.h"
|
||||
#include <stdint.h>
|
||||
|
||||
#ifndef NRF52840_XXAA
|
||||
#error "This header file shall only be included for nRF52 projects"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup NRF_MBR_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/**@brief MBR SVC Base number. */
|
||||
#define MBR_SVC_BASE (0x18)
|
||||
|
||||
/**@brief Page size in words. */
|
||||
#define MBR_PAGE_SIZE_IN_WORDS (1024)
|
||||
|
||||
/** @brief The size that must be reserved for the MBR when a softdevice is written to flash.
|
||||
This is the offset where the first byte of the softdevice hex file is written.*/
|
||||
#define MBR_SIZE (0x1000)
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup NRF_MBR_ENUMS Enumerations
|
||||
* @{ */
|
||||
|
||||
/**@brief nRF Master Boot Record API SVC numbers. */
|
||||
enum NRF_MBR_SVCS
|
||||
{
|
||||
SD_MBR_COMMAND = MBR_SVC_BASE, /**< ::sd_mbr_command */
|
||||
};
|
||||
|
||||
/**@brief Possible values for ::sd_mbr_command_t.command */
|
||||
enum NRF_MBR_COMMANDS
|
||||
{
|
||||
SD_MBR_COMMAND_COPY_BL, /**< Copy a new BootLoader. @see sd_mbr_command_copy_bl_t */
|
||||
SD_MBR_COMMAND_COPY_SD, /**< Copy a new SoftDevice. @see ::sd_mbr_command_copy_sd_t*/
|
||||
SD_MBR_COMMAND_INIT_SD, /**< Init forwarding interrupts to SD, and run reset function in SD*/
|
||||
SD_MBR_COMMAND_COMPARE, /**< This command works like memcmp. @see ::sd_mbr_command_compare_t*/
|
||||
SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET, /**< Start forwarding all exception to this address @see ::sd_mbr_command_vector_table_base_set_t*/
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup NRF_MBR_TYPES Types
|
||||
* @{ */
|
||||
|
||||
/**@brief This command copies part of a new SoftDevice
|
||||
* The destination area is erased before copying.
|
||||
* If dst is in the middle of a flash page, that whole flash page will be erased.
|
||||
* If (dst+len) is in the middle of a flash page, that whole flash page will be erased.
|
||||
*
|
||||
* The user of this function is responsible for setting the BPROT registers.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS indicates that the contents of the memory blocks where copied correctly.
|
||||
* @retval ::NRF_ERROR_INTERNAL indicates that the contents of the memory blocks where not verified correctly after copying.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t *src; /**< Pointer to the source of data to be copied.*/
|
||||
uint32_t *dst; /**< Pointer to the destination where the content is to be copied.*/
|
||||
uint32_t len; /**< Number of 32 bit words to copy. Must be a multiple of @ref MBR_PAGE_SIZE_IN_WORDS words.*/
|
||||
} sd_mbr_command_copy_sd_t;
|
||||
|
||||
|
||||
/**@brief This command works like memcmp, but takes the length in words.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS indicates that the contents of both memory blocks are equal.
|
||||
* @retval ::NRF_ERROR_NULL indicates that the contents of the memory blocks are not equal.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t *ptr1; /**< Pointer to block of memory. */
|
||||
uint32_t *ptr2; /**< Pointer to block of memory. */
|
||||
uint32_t len; /**< Number of 32 bit words to compare.*/
|
||||
} sd_mbr_command_compare_t;
|
||||
|
||||
|
||||
/**@brief This command copies a new BootLoader.
|
||||
* With this command, destination of BootLoader is always the address written in NRF_UICR->BOOTADDR.
|
||||
*
|
||||
* Destination is erased by this function.
|
||||
* If (destination+bl_len) is in the middle of a flash page, that whole flash page will be erased.
|
||||
*
|
||||
* This function will use PROTENSET to protect the flash that is not intended to be written.
|
||||
*
|
||||
* On Success, this function will not return. It will start the new BootLoader from reset-vector as normal.
|
||||
*
|
||||
* @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN if NRF_UICR->BOOTADDR is not set.
|
||||
* @retval ::NRF_ERROR_INVALID_LENGTH if parameters attempts to read or write outside flash area.
|
||||
* @retval ::NRF_ERROR_NO_MEM if no parameter page is provided (see sds for more info)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t *bl_src; /**< Pointer to the source of the Bootloader to be be copied.*/
|
||||
uint32_t bl_len; /**< Number of 32 bit words to copy for BootLoader. */
|
||||
} sd_mbr_command_copy_bl_t;
|
||||
|
||||
/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the MBR
|
||||
*
|
||||
* Once this function has been called, this address is where the MBR will start to forward interrupts to after a reset.
|
||||
*
|
||||
* To restore default forwarding this function should be called with @param address set to 0.
|
||||
* The MBR will then start forwarding to interrupts to the address in NFR_UICR->BOOTADDR or to the SoftDevice if the BOOTADDR is not set.
|
||||
*
|
||||
* On Success, this function will not return. It will reset the device.
|
||||
*
|
||||
* @retval ::NRF_ERROR_INTERNAL indicates an internal error that should not happen.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR if parameter address is outside of the flash size.
|
||||
* @retval ::NRF_ERROR_NO_MEM if no parameter page is provided (see sds for more info)
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
uint32_t address; /**< The base address of the interrupt vector table for forwarded interrupts.*/
|
||||
} sd_mbr_command_vector_table_base_set_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t command; /**< type of command to be issued see @ref NRF_MBR_COMMANDS. */
|
||||
union
|
||||
{
|
||||
sd_mbr_command_copy_sd_t copy_sd; /**< Parameters for copy SoftDevice.*/
|
||||
sd_mbr_command_compare_t compare; /**< Parameters for verify.*/
|
||||
sd_mbr_command_copy_bl_t copy_bl; /**< Parameters for copy BootLoader. Requires parameter page. */
|
||||
sd_mbr_command_vector_table_base_set_t base_set; /**< Parameters for vector table base set. Requires parameter page.*/
|
||||
} params;
|
||||
} sd_mbr_command_t;
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup NRF_MBR_FUNCTIONS Functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Issue Master Boot Record commands
|
||||
*
|
||||
* Commands used when updating a SoftDevice and bootloader.
|
||||
*
|
||||
* The SD_MBR_COMMAND_COPY_BL and SD_MBR_COMMAND_VECTOR_TABLE_BASE_SET requires parameters to be
|
||||
* retained by the MBR when resetting the IC. This is done in a separate flash page
|
||||
* provided by the application. The uicr register UICR.NRFFW[1] must be set
|
||||
* to an address corresponding to a page in the application flash space. This page will be cleared
|
||||
* by the MBR and used to store the command before reset. When the UICR.NRFFW[1] field is set
|
||||
* the page it refers to must not be used by the application. If the UICR.NRFFW[1] is set to
|
||||
* 0xFFFFFFFF (the default) MBR commands which use flash will be unavailable and return
|
||||
* NRF_ERROR_NO_MEM.
|
||||
*
|
||||
* @param[in] param Pointer to a struct describing the command.
|
||||
*
|
||||
* @note for retvals see ::sd_mbr_command_copy_sd_t ::sd_mbr_command_copy_bl_t ::sd_mbr_command_compare_t ::sd_mbr_command_vector_table_base_set_t
|
||||
*
|
||||
* @retval NRF_ERROR_NO_MEM if UICR.NRFFW[1] is not set (i.e. is 0xFFFFFFFF).
|
||||
* @retval NRF_ERROR_INVALID_PARAM if an invalid command is given.
|
||||
*/
|
||||
SVCALL(SD_MBR_COMMAND, uint32_t, sd_mbr_command(sd_mbr_command_t* param));
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_MBR_H__
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,89 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
@defgroup nrf_error SoftDevice Global Error Codes
|
||||
@{
|
||||
|
||||
@brief Global Error definitions
|
||||
*/
|
||||
|
||||
/* Header guard */
|
||||
#ifndef NRF_ERROR_H__
|
||||
#define NRF_ERROR_H__
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @defgroup NRF_ERRORS_BASE Error Codes Base number definitions
|
||||
* @{ */
|
||||
#define NRF_ERROR_BASE_NUM (0x0) ///< Global error base
|
||||
#define NRF_ERROR_SDM_BASE_NUM (0x1000) ///< SDM error base
|
||||
#define NRF_ERROR_SOC_BASE_NUM (0x2000) ///< SoC error base
|
||||
#define NRF_ERROR_STK_BASE_NUM (0x3000) ///< STK error base
|
||||
/** @} */
|
||||
|
||||
#define NRF_SUCCESS (NRF_ERROR_BASE_NUM + 0) ///< Successful command
|
||||
#define NRF_ERROR_SVC_HANDLER_MISSING (NRF_ERROR_BASE_NUM + 1) ///< SVC handler is missing
|
||||
#define NRF_ERROR_SOFTDEVICE_NOT_ENABLED (NRF_ERROR_BASE_NUM + 2) ///< SoftDevice has not been enabled
|
||||
#define NRF_ERROR_INTERNAL (NRF_ERROR_BASE_NUM + 3) ///< Internal Error
|
||||
#define NRF_ERROR_NO_MEM (NRF_ERROR_BASE_NUM + 4) ///< No Memory for operation
|
||||
#define NRF_ERROR_NOT_FOUND (NRF_ERROR_BASE_NUM + 5) ///< Not found
|
||||
#define NRF_ERROR_NOT_SUPPORTED (NRF_ERROR_BASE_NUM + 6) ///< Not supported
|
||||
#define NRF_ERROR_INVALID_PARAM (NRF_ERROR_BASE_NUM + 7) ///< Invalid Parameter
|
||||
#define NRF_ERROR_INVALID_STATE (NRF_ERROR_BASE_NUM + 8) ///< Invalid state, operation disallowed in this state
|
||||
#define NRF_ERROR_INVALID_LENGTH (NRF_ERROR_BASE_NUM + 9) ///< Invalid Length
|
||||
#define NRF_ERROR_INVALID_FLAGS (NRF_ERROR_BASE_NUM + 10) ///< Invalid Flags
|
||||
#define NRF_ERROR_INVALID_DATA (NRF_ERROR_BASE_NUM + 11) ///< Invalid Data
|
||||
#define NRF_ERROR_DATA_SIZE (NRF_ERROR_BASE_NUM + 12) ///< Invalid Data size
|
||||
#define NRF_ERROR_TIMEOUT (NRF_ERROR_BASE_NUM + 13) ///< Operation timed out
|
||||
#define NRF_ERROR_NULL (NRF_ERROR_BASE_NUM + 14) ///< Null Pointer
|
||||
#define NRF_ERROR_FORBIDDEN (NRF_ERROR_BASE_NUM + 15) ///< Forbidden Operation
|
||||
#define NRF_ERROR_INVALID_ADDR (NRF_ERROR_BASE_NUM + 16) ///< Bad Memory Address
|
||||
#define NRF_ERROR_BUSY (NRF_ERROR_BASE_NUM + 17) ///< Busy
|
||||
#define NRF_ERROR_CONN_COUNT (NRF_ERROR_BASE_NUM + 18) ///< Maximum connection count exceeded.
|
||||
#define NRF_ERROR_RESOURCES (NRF_ERROR_BASE_NUM + 19) ///< Not enough resources for operation
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_ERROR_H__
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,69 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
@addtogroup nrf_sdm_api
|
||||
@{
|
||||
@defgroup nrf_sdm_error SoftDevice Manager Error Codes
|
||||
@{
|
||||
|
||||
@brief Error definitions for the SDM API
|
||||
*/
|
||||
|
||||
/* Header guard */
|
||||
#ifndef NRF_ERROR_SDM_H__
|
||||
#define NRF_ERROR_SDM_H__
|
||||
|
||||
#include "nrf_error.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN (NRF_ERROR_SDM_BASE_NUM + 0) ///< Unknown lfclk source.
|
||||
#define NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION (NRF_ERROR_SDM_BASE_NUM + 1) ///< Incorrect interrupt configuration (can be caused by using illegal priority levels, or having enabled SoftDevice interrupts).
|
||||
#define NRF_ERROR_SDM_INCORRECT_CLENR0 (NRF_ERROR_SDM_BASE_NUM + 2) ///< Incorrect CLENR0 (can be caused by erronous SoftDevice flashing).
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_ERROR_SDM_H__
|
||||
|
||||
/**
|
||||
@}
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,84 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
@addtogroup nrf_soc_api
|
||||
@{
|
||||
@defgroup nrf_soc_error SoC Library Error Codes
|
||||
@{
|
||||
|
||||
@brief Error definitions for the SoC library
|
||||
|
||||
*/
|
||||
|
||||
/* Header guard */
|
||||
#ifndef NRF_ERROR_SOC_H__
|
||||
#define NRF_ERROR_SOC_H__
|
||||
|
||||
#include "nrf_error.h"
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/* Mutex Errors */
|
||||
#define NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN (NRF_ERROR_SOC_BASE_NUM + 0) ///< Mutex already taken
|
||||
|
||||
/* NVIC errors */
|
||||
#define NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE (NRF_ERROR_SOC_BASE_NUM + 1) ///< NVIC interrupt not available
|
||||
#define NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED (NRF_ERROR_SOC_BASE_NUM + 2) ///< NVIC interrupt priority not allowed
|
||||
#define NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 3) ///< NVIC should not return
|
||||
|
||||
/* Power errors */
|
||||
#define NRF_ERROR_SOC_POWER_MODE_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 4) ///< Power mode unknown
|
||||
#define NRF_ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN (NRF_ERROR_SOC_BASE_NUM + 5) ///< Power POF threshold unknown
|
||||
#define NRF_ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN (NRF_ERROR_SOC_BASE_NUM + 6) ///< Power off should not return
|
||||
|
||||
/* Rand errors */
|
||||
#define NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES (NRF_ERROR_SOC_BASE_NUM + 7) ///< RAND not enough values
|
||||
|
||||
/* PPI errors */
|
||||
#define NRF_ERROR_SOC_PPI_INVALID_CHANNEL (NRF_ERROR_SOC_BASE_NUM + 8) ///< Invalid PPI Channel
|
||||
#define NRF_ERROR_SOC_PPI_INVALID_GROUP (NRF_ERROR_SOC_BASE_NUM + 9) ///< Invalid PPI Group
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_ERROR_SOC_H__
|
||||
/**
|
||||
@}
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,521 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @defgroup nrf_nvic_api SoftDevice NVIC API
|
||||
* @{
|
||||
*
|
||||
* @note In order to use this module, the following code has to be added to a .c file:
|
||||
* \code
|
||||
* nrf_nvic_state_t nrf_nvic_state = {0};
|
||||
* \endcode
|
||||
*
|
||||
* @note Definitions and declarations starting with __ (double underscore) in this header file are
|
||||
* not intended for direct use by the application.
|
||||
*
|
||||
* @brief APIs for the accessing NVIC when using a SoftDevice.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NRF_NVIC_H__
|
||||
#define NRF_NVIC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf.h"
|
||||
|
||||
#include "nrf_error_soc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@addtogroup NRF_NVIC_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/**@defgroup NRF_NVIC_ISER_DEFINES SoftDevice NVIC internal definitions
|
||||
* @{ */
|
||||
|
||||
#define __NRF_NVIC_NVMC_IRQn (30) /**< The peripheral ID of the NVMC. IRQ numbers are used to identify peripherals, but the NVMC doesn't have an IRQ number in the MDK. */
|
||||
|
||||
#ifdef NRF51
|
||||
#define __NRF_NVIC_ISER_COUNT (1) /**< The number of ISER/ICER registers in the NVIC that are used. */
|
||||
|
||||
/**@brief Interrupts used by the SoftDevice. */
|
||||
#define __NRF_NVIC_SD_IRQS_0 ((uint32_t)( \
|
||||
(1U << POWER_CLOCK_IRQn) \
|
||||
| (1U << RADIO_IRQn) \
|
||||
| (1U << RTC0_IRQn) \
|
||||
| (1U << TIMER0_IRQn) \
|
||||
| (1U << RNG_IRQn) \
|
||||
| (1U << ECB_IRQn) \
|
||||
| (1U << CCM_AAR_IRQn) \
|
||||
| (1U << TEMP_IRQn) \
|
||||
| (1U << __NRF_NVIC_NVMC_IRQn) \
|
||||
| (1U << (uint32_t)SWI4_IRQn) \
|
||||
| (1U << (uint32_t)SWI5_IRQn) \
|
||||
))
|
||||
|
||||
/**@brief Interrupts available for to application. */
|
||||
#define __NRF_NVIC_APP_IRQS_0 (~__NRF_NVIC_SD_IRQS_0)
|
||||
#endif
|
||||
|
||||
#ifdef NRF52_SERIES
|
||||
#define __NRF_NVIC_ISER_COUNT (2) /**< The number of ISER/ICER registers in the NVIC that are used. */
|
||||
|
||||
/**@brief Interrupts used by the SoftDevice. */
|
||||
#define __NRF_NVIC_SD_IRQS_0 ((uint32_t)( \
|
||||
(1U << POWER_CLOCK_IRQn) \
|
||||
| (1U << RADIO_IRQn) \
|
||||
| (1U << RTC0_IRQn) \
|
||||
| (1U << TIMER0_IRQn) \
|
||||
| (1U << RNG_IRQn) \
|
||||
| (1U << ECB_IRQn) \
|
||||
| (1U << CCM_AAR_IRQn) \
|
||||
| (1U << TEMP_IRQn) \
|
||||
| (1U << __NRF_NVIC_NVMC_IRQn) \
|
||||
| (1U << (uint32_t)SWI4_EGU4_IRQn) \
|
||||
| (1U << (uint32_t)SWI5_EGU5_IRQn) \
|
||||
))
|
||||
#define __NRF_NVIC_SD_IRQS_1 ((uint32_t)0)
|
||||
|
||||
/**@brief Interrupts available for to application. */
|
||||
#define __NRF_NVIC_APP_IRQS_0 (~__NRF_NVIC_SD_IRQS_0)
|
||||
#define __NRF_NVIC_APP_IRQS_1 (~__NRF_NVIC_SD_IRQS_1)
|
||||
#endif
|
||||
/**@} */
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@addtogroup NRF_NVIC_VARIABLES Variables
|
||||
* @{ */
|
||||
|
||||
/**@brief Type representing the state struct for the SoftDevice NVIC module. */
|
||||
typedef struct
|
||||
{
|
||||
uint32_t volatile __irq_masks[__NRF_NVIC_ISER_COUNT]; /**< IRQs enabled by the application in the NVIC. */
|
||||
uint32_t volatile __cr_flag; /**< Non-zero if already in a critical region */
|
||||
} nrf_nvic_state_t;
|
||||
|
||||
/**@brief Variable keeping the state for the SoftDevice NVIC module. This must be declared in an
|
||||
* application source file. */
|
||||
extern nrf_nvic_state_t nrf_nvic_state;
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@addtogroup NRF_NVIC_INTERNAL_FUNCTIONS SoftDevice NVIC internal functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Disables IRQ interrupts globally, including the SoftDevice's interrupts.
|
||||
*
|
||||
* @retval The value of PRIMASK prior to disabling the interrupts.
|
||||
*/
|
||||
__STATIC_INLINE int __sd_nvic_irq_disable(void);
|
||||
|
||||
/**@brief Enables IRQ interrupts globally, including the SoftDevice's interrupts.
|
||||
*/
|
||||
__STATIC_INLINE void __sd_nvic_irq_enable(void);
|
||||
|
||||
/**@brief Checks if IRQn is available to application
|
||||
* @param[in] IRQn irq to check
|
||||
*
|
||||
* @retval 1 (true) if the irq to check is available to the application
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __sd_nvic_app_accessible_irq(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Checks if priority is available to application
|
||||
* @param[in] priority priority to check
|
||||
*
|
||||
* @retval 1 (true) if the priority to check is available to the application
|
||||
*/
|
||||
__STATIC_INLINE uint32_t __sd_nvic_is_app_accessible_priority(uint32_t priority);
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@addtogroup NRF_NVIC_FUNCTIONS SoftDevice NVIC public functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Enable External Interrupt.
|
||||
* @note Corresponds to NVIC_EnableIRQ in CMSIS.
|
||||
*
|
||||
* @pre IRQn is valid and not reserved by the stack.
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_EnableIRQ documentation in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt was enabled.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE The interrupt is not available for the application.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED The interrupt has a priority not available for the application.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Disable External Interrupt.
|
||||
* @note Corresponds to NVIC_DisableIRQ in CMSIS.
|
||||
*
|
||||
* @pre IRQn is valid and not reserved by the stack.
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_DisableIRQ documentation in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt was disabled.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE The interrupt is not available for the application.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Get Pending Interrupt.
|
||||
* @note Corresponds to NVIC_GetPendingIRQ in CMSIS.
|
||||
*
|
||||
* @pre IRQn is valid and not reserved by the stack.
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_GetPendingIRQ documentation in CMSIS.
|
||||
* @param[out] p_pending_irq Return value from NVIC_GetPendingIRQ.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt is available for the application.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq);
|
||||
|
||||
/**@brief Set Pending Interrupt.
|
||||
* @note Corresponds to NVIC_SetPendingIRQ in CMSIS.
|
||||
*
|
||||
* @pre IRQn is valid and not reserved by the stack.
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_SetPendingIRQ documentation in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt is set pending.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Clear Pending Interrupt.
|
||||
* @note Corresponds to NVIC_ClearPendingIRQ in CMSIS.
|
||||
*
|
||||
* @pre IRQn is valid and not reserved by the stack.
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_ClearPendingIRQ documentation in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt pending flag is cleared.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn);
|
||||
|
||||
/**@brief Set Interrupt Priority.
|
||||
* @note Corresponds to NVIC_SetPriority in CMSIS.
|
||||
*
|
||||
* @pre IRQn is valid and not reserved by the stack.
|
||||
* @pre Priority is valid and not reserved by the stack.
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_SetPriority documentation in CMSIS.
|
||||
* @param[in] priority A valid IRQ priority for use by the application.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt and priority level is available for the application.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE IRQn is not available for the application.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED The interrupt priority is not available for the application.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority);
|
||||
|
||||
/**@brief Get Interrupt Priority.
|
||||
* @note Corresponds to NVIC_GetPriority in CMSIS.
|
||||
*
|
||||
* @pre IRQn is valid and not reserved by the stack.
|
||||
*
|
||||
* @param[in] IRQn See the NVIC_GetPriority documentation in CMSIS.
|
||||
* @param[out] p_priority Return value from NVIC_GetPriority.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The interrupt priority is returned in p_priority.
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE - IRQn is not available for the application.
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority);
|
||||
|
||||
/**@brief System Reset.
|
||||
* @note Corresponds to NVIC_SystemReset in CMSIS.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_SystemReset(void);
|
||||
|
||||
/**@brief Enter critical region.
|
||||
*
|
||||
* @post Application interrupts will be disabled.
|
||||
* @note sd_nvic_critical_region_enter() and ::sd_nvic_critical_region_exit() must be called in matching pairs inside each
|
||||
* execution context
|
||||
* @sa sd_nvic_critical_region_exit
|
||||
*
|
||||
* @param[out] p_is_nested_critical_region If 1, the application is now in a nested critical region.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region);
|
||||
|
||||
/**@brief Exit critical region.
|
||||
*
|
||||
* @pre Application has entered a critical region using ::sd_nvic_critical_region_enter.
|
||||
* @post If not in a nested critical region, the application interrupts will restored to the state before ::sd_nvic_critical_region_enter was called.
|
||||
*
|
||||
* @param[in] is_nested_critical_region If this is set to 1, the critical region won't be exited. @sa sd_nvic_critical_region_enter.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
__STATIC_INLINE uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region);
|
||||
|
||||
/**@} */
|
||||
|
||||
#ifndef SUPPRESS_INLINE_IMPLEMENTATION
|
||||
|
||||
__STATIC_INLINE int __sd_nvic_irq_disable(void)
|
||||
{
|
||||
int pm = __get_PRIMASK();
|
||||
__disable_irq();
|
||||
return pm;
|
||||
}
|
||||
|
||||
__STATIC_INLINE void __sd_nvic_irq_enable(void)
|
||||
{
|
||||
__enable_irq();
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t __sd_nvic_app_accessible_irq(IRQn_Type IRQn)
|
||||
{
|
||||
if (IRQn < 32)
|
||||
{
|
||||
return ((1UL<<IRQn) & __NRF_NVIC_APP_IRQS_0) != 0;
|
||||
}
|
||||
#ifdef NRF52_SERIES
|
||||
else if (IRQn < 64)
|
||||
{
|
||||
return ((1UL<<(IRQn-32)) & __NRF_NVIC_APP_IRQS_1) != 0;
|
||||
}
|
||||
#endif
|
||||
else
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t __sd_nvic_is_app_accessible_priority(uint32_t priority)
|
||||
{
|
||||
if(priority >= (1 << __NVIC_PRIO_BITS))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#ifdef NRF51
|
||||
if( priority == 0
|
||||
|| priority == 2
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#ifdef NRF52_SERIES
|
||||
if( priority == 0
|
||||
|| priority == 1
|
||||
|| priority == 4
|
||||
|| priority == 5
|
||||
)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_EnableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
if (!__sd_nvic_app_accessible_irq(IRQn))
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
|
||||
}
|
||||
if (!__sd_nvic_is_app_accessible_priority(NVIC_GetPriority(IRQn)))
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
if (nrf_nvic_state.__cr_flag)
|
||||
{
|
||||
nrf_nvic_state.__irq_masks[(uint32_t)((int32_t)IRQn) >> 5] |= (uint32_t)(1 << ((uint32_t)((int32_t)IRQn) & (uint32_t)0x1F));
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_EnableIRQ(IRQn);
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_DisableIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
if (!__sd_nvic_app_accessible_irq(IRQn))
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (nrf_nvic_state.__cr_flag)
|
||||
{
|
||||
nrf_nvic_state.__irq_masks[(uint32_t)((int32_t)IRQn) >> 5] &= ~(1UL << ((uint32_t)(IRQn) & 0x1F));
|
||||
}
|
||||
else
|
||||
{
|
||||
NVIC_DisableIRQ(IRQn);
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_GetPendingIRQ(IRQn_Type IRQn, uint32_t * p_pending_irq)
|
||||
{
|
||||
if (__sd_nvic_app_accessible_irq(IRQn))
|
||||
{
|
||||
*p_pending_irq = NVIC_GetPendingIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_SetPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
if (__sd_nvic_app_accessible_irq(IRQn))
|
||||
{
|
||||
NVIC_SetPendingIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_ClearPendingIRQ(IRQn_Type IRQn)
|
||||
{
|
||||
if (__sd_nvic_app_accessible_irq(IRQn))
|
||||
{
|
||||
NVIC_ClearPendingIRQ(IRQn);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_SetPriority(IRQn_Type IRQn, uint32_t priority)
|
||||
{
|
||||
if (!__sd_nvic_app_accessible_irq(IRQn))
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
if (!__sd_nvic_is_app_accessible_priority(priority))
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_PRIORITY_NOT_ALLOWED;
|
||||
}
|
||||
|
||||
NVIC_SetPriority(IRQn, (uint32_t)priority);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_GetPriority(IRQn_Type IRQn, uint32_t * p_priority)
|
||||
{
|
||||
if (__sd_nvic_app_accessible_irq(IRQn))
|
||||
{
|
||||
*p_priority = (NVIC_GetPriority(IRQn) & 0xFF);
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRF_ERROR_SOC_NVIC_INTERRUPT_NOT_AVAILABLE;
|
||||
}
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_SystemReset(void)
|
||||
{
|
||||
NVIC_SystemReset();
|
||||
return NRF_ERROR_SOC_NVIC_SHOULD_NOT_RETURN;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_critical_region_enter(uint8_t * p_is_nested_critical_region)
|
||||
{
|
||||
int was_masked = __sd_nvic_irq_disable();
|
||||
if (!nrf_nvic_state.__cr_flag)
|
||||
{
|
||||
nrf_nvic_state.__cr_flag = 1;
|
||||
nrf_nvic_state.__irq_masks[0] = ( NVIC->ICER[0] & __NRF_NVIC_APP_IRQS_0 );
|
||||
NVIC->ICER[0] = __NRF_NVIC_APP_IRQS_0;
|
||||
#ifdef NRF52_SERIES
|
||||
nrf_nvic_state.__irq_masks[1] = ( NVIC->ICER[1] & __NRF_NVIC_APP_IRQS_1 );
|
||||
NVIC->ICER[1] = __NRF_NVIC_APP_IRQS_1;
|
||||
#endif
|
||||
*p_is_nested_critical_region = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
*p_is_nested_critical_region = 1;
|
||||
}
|
||||
if (!was_masked)
|
||||
{
|
||||
__sd_nvic_irq_enable();
|
||||
}
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
__STATIC_INLINE uint32_t sd_nvic_critical_region_exit(uint8_t is_nested_critical_region)
|
||||
{
|
||||
if (nrf_nvic_state.__cr_flag && (is_nested_critical_region == 0))
|
||||
{
|
||||
int was_masked = __sd_nvic_irq_disable();
|
||||
NVIC->ISER[0] = nrf_nvic_state.__irq_masks[0];
|
||||
#ifdef NRF52_SERIES
|
||||
NVIC->ISER[1] = nrf_nvic_state.__irq_masks[1];
|
||||
#endif
|
||||
nrf_nvic_state.__cr_flag = 0;
|
||||
if (!was_masked)
|
||||
{
|
||||
__sd_nvic_irq_enable();
|
||||
}
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
#endif /* SUPPRESS_INLINE_IMPLEMENTATION */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // NRF_NVIC_H__
|
||||
|
||||
/**@} */
|
|
@ -0,0 +1,58 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NRF_SD_DEF_H__
|
||||
#define NRF_SD_DEF_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#define SD_PPI_CHANNELS_USED 0xFFFE0000uL /**< PPI channels utilized by SotfDevice (not available to the application). */
|
||||
#define SD_PPI_GROUPS_USED 0x0000000CuL /**< PPI groups utilized by SoftDevice (not available to the application). */
|
||||
#define SD_TIMERS_USED 0x00000001uL /**< Timers used by SoftDevice. */
|
||||
#define SD_SWI_USED 0x0000003CuL /**< Software interrupts used by SoftDevice */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* NRF_SD_DEF_H__ */
|
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
@defgroup nrf_sdm_api SoftDevice Manager API
|
||||
@{
|
||||
|
||||
@brief APIs for SoftDevice management.
|
||||
|
||||
*/
|
||||
|
||||
#ifndef NRF_SDM_H__
|
||||
#define NRF_SDM_H__
|
||||
|
||||
#include "nrf_svc.h"
|
||||
#include "nrf.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "nrf_error_sdm.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/** @addtogroup NRF_SDM_DEFINES Defines
|
||||
* @{ */
|
||||
#ifdef NRFSOC_DOXYGEN
|
||||
/// Declared in nrf_mbr.h
|
||||
#define MBR_SIZE 0
|
||||
#warning test
|
||||
#endif
|
||||
|
||||
/** @brief The major version for the SoftDevice binary distributed with this header file. */
|
||||
#define SD_MAJOR_VERSION (5)
|
||||
|
||||
/** @brief The minor version for the SoftDevice binary distributed with this header file. */
|
||||
#define SD_MINOR_VERSION (0)
|
||||
|
||||
/** @brief The bugfix version for the SoftDevice binary distributed with this header file. */
|
||||
#define SD_BUGFIX_VERSION (0)
|
||||
|
||||
/** @brief The full version number for the SoftDevice binary this header file was distributed
|
||||
* with, as a decimal number in the form Mmmmbbb, where:
|
||||
* - M is major version (one or more digits)
|
||||
* - mmm is minor version (three digits)
|
||||
* - bbb is bugfix version (three digits). */
|
||||
#define SD_VERSION (SD_MAJOR_VERSION * 1000000 + SD_MINOR_VERSION * 1000 + SD_BUGFIX_VERSION)
|
||||
|
||||
/** @brief SoftDevice Manager SVC Base number. */
|
||||
#define SDM_SVC_BASE 0x10
|
||||
|
||||
/** @brief Invalid info field. Returned when an info field does not exist. */
|
||||
#define SDM_INFO_FIELD_INVALID (0)
|
||||
|
||||
/** @brief Defines the SoftDevice Information Structure location (address) as an offset from
|
||||
the start of the softdevice (without MBR)*/
|
||||
#define SOFTDEVICE_INFO_STRUCT_OFFSET (0x2000)
|
||||
|
||||
/** @brief Defines the absolute SoftDevice Information Structure location (address) when the
|
||||
* SoftDevice is installed just above the MBR (the usual case). */
|
||||
#define SOFTDEVICE_INFO_STRUCT_ADDRESS (SOFTDEVICE_INFO_STRUCT_OFFSET + MBR_SIZE)
|
||||
|
||||
/** @brief Defines the offset for the SoftDevice Information Structure size value relative to the
|
||||
* SoftDevice base address. The size value is of type uint8_t. */
|
||||
#define SD_INFO_STRUCT_SIZE_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET)
|
||||
|
||||
/** @brief Defines the offset for the SoftDevice size value relative to the SoftDevice base address.
|
||||
* The size value is of type uint32_t. */
|
||||
#define SD_SIZE_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x08)
|
||||
|
||||
/** @brief Defines the offset for FWID value relative to the SoftDevice base address. The FWID value
|
||||
* is of type uint16_t. */
|
||||
#define SD_FWID_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x0C)
|
||||
|
||||
/** @brief Defines the offset for the SoftDevice ID relative to the SoftDevice base address. The ID
|
||||
* is of type uint32_t. */
|
||||
#define SD_ID_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x10)
|
||||
|
||||
/** @brief Defines the offset for the SoftDevice version relative to the SoftDevice base address in
|
||||
* the same format as @ref SD_VERSION, stored as an uint32_t. */
|
||||
#define SD_VERSION_OFFSET (SOFTDEVICE_INFO_STRUCT_OFFSET + 0x14)
|
||||
|
||||
/** @brief Defines a macro for retreiving the actual SoftDevice Information Structure size value
|
||||
* from a given base address. Use @ref MBR_SIZE as the argument when the SoftDevice is
|
||||
* installed just above the MBR (the usual case). */
|
||||
#define SD_INFO_STRUCT_SIZE_GET(baseaddr) (*((uint8_t *) ((baseaddr) + SD_INFO_STRUCT_SIZE_OFFSET)))
|
||||
|
||||
/** @brief Defines a macro for retreiving the actual SoftDevice size value from a given base
|
||||
* address. Use @ref MBR_SIZE as the argument when the SoftDevice is installed just above
|
||||
* the MBR (the usual case). */
|
||||
#define SD_SIZE_GET(baseaddr) (*((uint32_t *) ((baseaddr) + SD_SIZE_OFFSET)))
|
||||
|
||||
/** @brief Defines a macro for retreiving the actual FWID value from a given base address. Use @ref
|
||||
* MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the usual
|
||||
* case). */
|
||||
#define SD_FWID_GET(baseaddr) (*((uint16_t *) ((baseaddr) + SD_FWID_OFFSET)))
|
||||
|
||||
/** @brief Defines a macro for retreiving the actual SoftDevice ID from a given base address. Use
|
||||
* @ref MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the
|
||||
* usual case). */
|
||||
#define SD_ID_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_ID_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \
|
||||
? (*((uint32_t *) ((baseaddr) + SD_ID_OFFSET))) : SDM_INFO_FIELD_INVALID)
|
||||
|
||||
/** @brief Defines a macro for retreiving the actual FWID value from a given base address. Use @ref
|
||||
* MBR_SIZE as the argument when the SoftDevice is installed just above the MBR (the usual
|
||||
* case). */
|
||||
#define SD_VERSION_GET(baseaddr) ((SD_INFO_STRUCT_SIZE_GET(baseaddr) > (SD_VERSION_OFFSET - SOFTDEVICE_INFO_STRUCT_OFFSET)) \
|
||||
? (*((uint32_t *) ((baseaddr) + SD_VERSION_OFFSET))) : SDM_INFO_FIELD_INVALID)
|
||||
|
||||
/**@defgroup NRF_FAULT_ID_RANGES Fault ID ranges
|
||||
* @{ */
|
||||
#define NRF_FAULT_ID_SD_RANGE_START 0x00000000 /**< SoftDevice ID range start. */
|
||||
#define NRF_FAULT_ID_APP_RANGE_START 0x00001000 /**< Application ID range start. */
|
||||
/**@} */
|
||||
|
||||
/**@defgroup NRF_FAULT_IDS Fault ID types
|
||||
* @{ */
|
||||
#define NRF_FAULT_ID_SD_ASSERT (NRF_FAULT_ID_SD_RANGE_START + 1) /**< SoftDevice assertion. The info parameter is reserved for future used. */
|
||||
#define NRF_FAULT_ID_APP_MEMACC (NRF_FAULT_ID_APP_RANGE_START + 1) /**< Application invalid memory access (nRF52 only). The info parameter will contain 0x00000000, in case of SoftDevice RAM
|
||||
access violation. In case of SoftDevice peripheral register violation the info parameter will contain the sub-region number of PREGION[0], on whose address range the unallowed
|
||||
write access caused the memory access fault. */
|
||||
/**@} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup NRF_SDM_ENUMS Enumerations
|
||||
* @{ */
|
||||
|
||||
/**@brief nRF SoftDevice Manager API SVC numbers. */
|
||||
enum NRF_SD_SVCS
|
||||
{
|
||||
SD_SOFTDEVICE_ENABLE = SDM_SVC_BASE, /**< ::sd_softdevice_enable */
|
||||
SD_SOFTDEVICE_DISABLE, /**< ::sd_softdevice_disable */
|
||||
SD_SOFTDEVICE_IS_ENABLED, /**< ::sd_softdevice_is_enabled */
|
||||
SD_SOFTDEVICE_VECTOR_TABLE_BASE_SET, /**< ::sd_softdevice_vector_table_base_set */
|
||||
SVC_SDM_LAST /**< Placeholder for last SDM SVC */
|
||||
};
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup NRF_SDM_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/**@defgroup NRF_CLOCK_LF_XTAL_ACCURACY Clock accuracy
|
||||
* @{ */
|
||||
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_250_PPM (0) /**< Default: 250 ppm */
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_500_PPM (1) /**< 500 ppm */
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_150_PPM (2) /**< 150 ppm */
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_100_PPM (3) /**< 100 ppm */
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_75_PPM (4) /**< 75 ppm */
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_50_PPM (5) /**< 50 ppm */
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_30_PPM (6) /**< 30 ppm */
|
||||
#define NRF_CLOCK_LF_XTAL_ACCURACY_20_PPM (7) /**< 20 ppm */
|
||||
|
||||
/** @} */
|
||||
|
||||
/**@defgroup NRF_CLOCK_LF_SRC Possible lfclk oscillator sources
|
||||
* @{ */
|
||||
|
||||
#define NRF_CLOCK_LF_SRC_RC (0) /**< LFCLK RC oscillator. */
|
||||
#define NRF_CLOCK_LF_SRC_XTAL (1) /**< LFCLK crystal oscillator. */
|
||||
#define NRF_CLOCK_LF_SRC_SYNTH (2) /**< LFCLK Synthesized from HFCLK. */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup NRF_SDM_TYPES Types
|
||||
* @{ */
|
||||
|
||||
/**@brief Type representing lfclk oscillator source. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t source; /**< LF oscillator clock source, see @ref NRF_CLOCK_LF_SRC. */
|
||||
uint8_t rc_ctiv; /**< Only for NRF_CLOCK_LF_SRC_RC: Calibration timer interval in 1/4 second
|
||||
units (nRF51: 1-64, nRF52: 1-32).
|
||||
@note To avoid excessive clock drift, 0.5 degrees Celsius is the
|
||||
maximum temperature change allowed in one calibration timer
|
||||
interval. The interval should be selected to ensure this.
|
||||
|
||||
@note Must be 0 if source is not NRF_CLOCK_LF_SRC_RC. */
|
||||
uint8_t rc_temp_ctiv; /**< Only for NRF_CLOCK_LF_SRC_RC: How often (in number of calibration
|
||||
intervals) the RC oscillator shall be calibrated if the temperature
|
||||
hasn't changed.
|
||||
0: Always calibrate even if the temperature hasn't changed.
|
||||
1: Only calibrate if the temperature has changed (nRF51 only).
|
||||
2-33: Check the temperature and only calibrate if it has changed,
|
||||
however calibration will take place every rc_temp_ctiv
|
||||
intervals in any case.
|
||||
|
||||
@note Must be 0 if source is not NRF_CLOCK_LF_SRC_RC.
|
||||
|
||||
@note For nRF52, the application must ensure calibration at least once
|
||||
every 8 seconds to ensure +/-250ppm clock stability. The
|
||||
recommended configuration for NRF_CLOCK_LF_SRC_RC on nRF52 is
|
||||
rc_ctiv=16 and rc_temp_ctiv=2. This will ensure calibration at
|
||||
least once every 8 seconds and for temperature changes of 0.5
|
||||
degrees Celsius every 4 seconds. See the Product Specification
|
||||
for the nRF52 device being used for more information.*/
|
||||
uint8_t xtal_accuracy; /**< External crystal clock accuracy used in the LL to compute timing windows.
|
||||
|
||||
@note For the NRF_CLOCK_LF_SRC_RC clock source this parameter is ignored. */
|
||||
} nrf_clock_lf_cfg_t;
|
||||
|
||||
/**@brief Fault Handler type.
|
||||
*
|
||||
* When certain unrecoverable errors occur within the application or SoftDevice the fault handler will be called back.
|
||||
* The protocol stack will be in an undefined state when this happens and the only way to recover will be to
|
||||
* perform a reset, using e.g. CMSIS NVIC_SystemReset().
|
||||
* If the application returns from the fault handler the SoftDevice will call NVIC_SystemReset().
|
||||
*
|
||||
* @note This callback is executed in HardFault context, thus SVC functions cannot be called from the fault callback.
|
||||
*
|
||||
* @param[in] id Fault identifier. See @ref NRF_FAULT_IDS.
|
||||
* @param[in] pc The program counter of the instruction that triggered the fault.
|
||||
* @param[in] info Optional additional information regarding the fault. Refer to each Fault identifier for details.
|
||||
*
|
||||
* @note When id is set to NRF_FAULT_ID_APP_MEMACC, pc will contain the address of the instruction being executed at the time when
|
||||
* the fault is detected by the CPU. The CPU program counter may have advanced up to 2 instructions (no branching) after the one that triggered the fault.
|
||||
*/
|
||||
typedef void (*nrf_fault_handler_t)(uint32_t id, uint32_t pc, uint32_t info);
|
||||
|
||||
/** @} */
|
||||
|
||||
/** @addtogroup NRF_SDM_FUNCTIONS Functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Enables the SoftDevice and by extension the protocol stack.
|
||||
*
|
||||
* @note Some care must be taken if a low frequency clock source is already running when calling this function:
|
||||
* If the LF clock has a different source then the one currently running, it will be stopped. Then, the new
|
||||
* clock source will be started.
|
||||
*
|
||||
* @note This function has no effect when returning with an error.
|
||||
*
|
||||
* @post If return code is ::NRF_SUCCESS
|
||||
* - SoC library and protocol stack APIs are made available.
|
||||
* - A portion of RAM will be unavailable (see relevant SDS documentation).
|
||||
* - Some peripherals will be unavailable or available only through the SoC API (see relevant SDS documentation).
|
||||
* - Interrupts will not arrive from protected peripherals or interrupts.
|
||||
* - nrf_nvic_ functions must be used instead of CMSIS NVIC_ functions for reliable usage of the SoftDevice.
|
||||
* - Interrupt latency may be affected by the SoftDevice (see relevant SDS documentation).
|
||||
* - Chosen low frequency clock source will be running.
|
||||
*
|
||||
* @param p_clock_lf_cfg Low frequency clock source and accuracy.
|
||||
If NULL the clock will be configured as an rc source with rc_ctiv = 16 and .rc_temp_ctiv = 2
|
||||
In the case of XTAL source, the PPM accuracy of the chosen clock source must be greater than or equal to the actual characteristics of your XTAL clock.
|
||||
* @param fault_handler Callback to be invoked in case of fault, cannot be NULL.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Invalid or NULL pointer supplied.
|
||||
* @retval ::NRF_ERROR_INVALID_STATE SoftDevice is already enabled, and the clock source and fault handler cannot be updated.
|
||||
* @retval ::NRF_ERROR_SDM_INCORRECT_INTERRUPT_CONFIGURATION SoftDevice interrupt is already enabled, or an enabled interrupt has an illegal priority level.
|
||||
* @retval ::NRF_ERROR_SDM_LFCLK_SOURCE_UNKNOWN Unknown low frequency clock source selected.
|
||||
*/
|
||||
SVCALL(SD_SOFTDEVICE_ENABLE, uint32_t, sd_softdevice_enable(nrf_clock_lf_cfg_t const * p_clock_lf_cfg, nrf_fault_handler_t fault_handler));
|
||||
|
||||
|
||||
/**@brief Disables the SoftDevice and by extension the protocol stack.
|
||||
*
|
||||
* Idempotent function to disable the SoftDevice.
|
||||
*
|
||||
* @post SoC library and protocol stack APIs are made unavailable.
|
||||
* @post All interrupts that was protected by the SoftDevice will be disabled and initialized to priority 0 (highest).
|
||||
* @post All peripherals used by the SoftDevice will be reset to default values.
|
||||
* @post All of RAM become available.
|
||||
* @post All interrupts are forwarded to the application.
|
||||
* @post LFCLK source chosen in ::sd_softdevice_enable will be left running.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_SOFTDEVICE_DISABLE, uint32_t, sd_softdevice_disable(void));
|
||||
|
||||
/**@brief Check if the SoftDevice is enabled.
|
||||
*
|
||||
* @param[out] p_softdevice_enabled If the SoftDevice is enabled: 1 else 0.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_SOFTDEVICE_IS_ENABLED, uint32_t, sd_softdevice_is_enabled(uint8_t * p_softdevice_enabled));
|
||||
|
||||
/**@brief Sets the base address of the interrupt vector table for interrupts forwarded from the SoftDevice
|
||||
*
|
||||
* This function is only intended to be called when a bootloader is enabled.
|
||||
*
|
||||
* @param[in] address The base address of the interrupt vector table for forwarded interrupts.
|
||||
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_SOFTDEVICE_VECTOR_TABLE_BASE_SET, uint32_t, sd_softdevice_vector_table_base_set(uint32_t address));
|
||||
|
||||
/** @} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_SDM_H__
|
||||
|
||||
/**
|
||||
@}
|
||||
*/
|
|
@ -0,0 +1,908 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
/**
|
||||
* @defgroup nrf_soc_api SoC Library API
|
||||
* @{
|
||||
*
|
||||
* @brief APIs for the SoC library.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NRF_SOC_H__
|
||||
#define NRF_SOC_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdbool.h>
|
||||
#include "nrf_svc.h"
|
||||
#include "nrf.h"
|
||||
|
||||
#include "nrf_error_soc.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@addtogroup NRF_SOC_DEFINES Defines
|
||||
* @{ */
|
||||
|
||||
/**@brief The number of the lowest SVC number reserved for the SoC library. */
|
||||
#define SOC_SVC_BASE (0x20) /**< Base value for SVCs that are available when the SoftDevice is disabled. */
|
||||
#define SOC_SVC_BASE_NOT_AVAILABLE (0x2B) /**< Base value for SVCs that are not available when the SoftDevice is disabled. */
|
||||
|
||||
/**@brief Guranteed time for application to process radio inactive notification. */
|
||||
#define NRF_RADIO_NOTIFICATION_INACTIVE_GUARANTEED_TIME_US (62)
|
||||
|
||||
/**@brief The minimum allowed timeslot extension time. */
|
||||
#define NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_US (200)
|
||||
|
||||
#define SOC_ECB_KEY_LENGTH (16) /**< ECB key length. */
|
||||
#define SOC_ECB_CLEARTEXT_LENGTH (16) /**< ECB cleartext length. */
|
||||
#define SOC_ECB_CIPHERTEXT_LENGTH (SOC_ECB_CLEARTEXT_LENGTH) /**< ECB ciphertext length. */
|
||||
|
||||
#ifdef NRF51
|
||||
#define SD_EVT_IRQn (SWI2_IRQn) /**< SoftDevice Event IRQ number. Used for both protocol events and SoC events. */
|
||||
#define SD_EVT_IRQHandler (SWI2_IRQHandler) /**< SoftDevice Event IRQ handler. Used for both protocol events and SoC events. */
|
||||
#define RADIO_NOTIFICATION_IRQn (SWI1_IRQn) /**< The radio notification IRQ number. */
|
||||
#define RADIO_NOTIFICATION_IRQHandler (SWI1_IRQHandler) /**< The radio notification IRQ handler. */
|
||||
#endif
|
||||
#ifdef NRF52_SERIES
|
||||
#define SD_EVT_IRQn (SWI2_EGU2_IRQn) /**< SoftDevice Event IRQ number. Used for both protocol events and SoC events. */
|
||||
#define SD_EVT_IRQHandler (SWI2_EGU2_IRQHandler) /**< SoftDevice Event IRQ handler. Used for both protocol events and SoC events. */
|
||||
#define RADIO_NOTIFICATION_IRQn (SWI1_EGU1_IRQn) /**< The radio notification IRQ number. */
|
||||
#define RADIO_NOTIFICATION_IRQHandler (SWI1_EGU1_IRQHandler) /**< The radio notification IRQ handler. */
|
||||
#endif
|
||||
|
||||
#define NRF_RADIO_LENGTH_MIN_US (100) /**< The shortest allowed radio timeslot, in microseconds. */
|
||||
#define NRF_RADIO_LENGTH_MAX_US (100000) /**< The longest allowed radio timeslot, in microseconds. */
|
||||
|
||||
#define NRF_RADIO_DISTANCE_MAX_US (128000000UL - 1UL) /**< The longest timeslot distance, in microseconds, allowed for the distance parameter (see @ref nrf_radio_request_normal_t) in the request. */
|
||||
|
||||
#define NRF_RADIO_EARLIEST_TIMEOUT_MAX_US (128000000UL - 1UL) /**< The longest timeout, in microseconds, allowed when requesting the earliest possible timeslot. */
|
||||
|
||||
#define NRF_RADIO_START_JITTER_US (2) /**< The maximum jitter in @ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START relative to the requested start time. */
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@addtogroup NRF_SOC_ENUMS Enumerations
|
||||
* @{ */
|
||||
|
||||
/**@brief The SVC numbers used by the SVC functions in the SoC library. */
|
||||
enum NRF_SOC_SVCS
|
||||
{
|
||||
SD_PPI_CHANNEL_ENABLE_GET = SOC_SVC_BASE,
|
||||
SD_PPI_CHANNEL_ENABLE_SET,
|
||||
SD_PPI_CHANNEL_ENABLE_CLR,
|
||||
SD_PPI_CHANNEL_ASSIGN,
|
||||
SD_PPI_GROUP_TASK_ENABLE,
|
||||
SD_PPI_GROUP_TASK_DISABLE,
|
||||
SD_PPI_GROUP_ASSIGN,
|
||||
SD_PPI_GROUP_GET,
|
||||
SD_FLASH_PAGE_ERASE,
|
||||
SD_FLASH_WRITE,
|
||||
SD_FLASH_PROTECT,
|
||||
SD_MUTEX_NEW = SOC_SVC_BASE_NOT_AVAILABLE,
|
||||
SD_MUTEX_ACQUIRE,
|
||||
SD_MUTEX_RELEASE,
|
||||
SD_RAND_APPLICATION_POOL_CAPACITY_GET,
|
||||
SD_RAND_APPLICATION_BYTES_AVAILABLE_GET,
|
||||
SD_RAND_APPLICATION_VECTOR_GET,
|
||||
SD_POWER_MODE_SET,
|
||||
SD_POWER_SYSTEM_OFF,
|
||||
SD_POWER_RESET_REASON_GET,
|
||||
SD_POWER_RESET_REASON_CLR,
|
||||
SD_POWER_POF_ENABLE,
|
||||
SD_POWER_POF_THRESHOLD_SET,
|
||||
SD_POWER_RAMON_SET,
|
||||
SD_POWER_RAMON_CLR,
|
||||
SD_POWER_RAMON_GET,
|
||||
SD_POWER_GPREGRET_SET,
|
||||
SD_POWER_GPREGRET_CLR,
|
||||
SD_POWER_GPREGRET_GET,
|
||||
SD_POWER_DCDC_MODE_SET,
|
||||
SD_APP_EVT_WAIT,
|
||||
SD_CLOCK_HFCLK_REQUEST,
|
||||
SD_CLOCK_HFCLK_RELEASE,
|
||||
SD_CLOCK_HFCLK_IS_RUNNING,
|
||||
SD_RADIO_NOTIFICATION_CFG_SET,
|
||||
SD_ECB_BLOCK_ENCRYPT,
|
||||
SD_ECB_BLOCKS_ENCRYPT,
|
||||
SD_RADIO_SESSION_OPEN,
|
||||
SD_RADIO_SESSION_CLOSE,
|
||||
SD_RADIO_REQUEST,
|
||||
SD_EVT_GET,
|
||||
SD_TEMP_GET,
|
||||
SVC_SOC_LAST
|
||||
};
|
||||
|
||||
/**@brief Possible values of a ::nrf_mutex_t. */
|
||||
enum NRF_MUTEX_VALUES
|
||||
{
|
||||
NRF_MUTEX_FREE,
|
||||
NRF_MUTEX_TAKEN
|
||||
};
|
||||
|
||||
/**@brief Power modes. */
|
||||
enum NRF_POWER_MODES
|
||||
{
|
||||
NRF_POWER_MODE_CONSTLAT, /**< Constant latency mode. See power management in the reference manual. */
|
||||
NRF_POWER_MODE_LOWPWR /**< Low power mode. See power management in the reference manual. */
|
||||
};
|
||||
|
||||
|
||||
/**@brief Power failure thresholds */
|
||||
enum NRF_POWER_THRESHOLDS
|
||||
{
|
||||
NRF_POWER_THRESHOLD_V21, /**< 2.1 Volts power failure threshold. */
|
||||
NRF_POWER_THRESHOLD_V23, /**< 2.3 Volts power failure threshold. */
|
||||
NRF_POWER_THRESHOLD_V25, /**< 2.5 Volts power failure threshold. */
|
||||
NRF_POWER_THRESHOLD_V27 /**< 2.7 Volts power failure threshold. */
|
||||
};
|
||||
|
||||
|
||||
/**@brief DC/DC converter modes. */
|
||||
enum NRF_POWER_DCDC_MODES
|
||||
{
|
||||
NRF_POWER_DCDC_DISABLE, /**< The DCDC is disabled. */
|
||||
NRF_POWER_DCDC_ENABLE /**< The DCDC is enabled. */
|
||||
};
|
||||
|
||||
/**@brief Radio notification distances. */
|
||||
enum NRF_RADIO_NOTIFICATION_DISTANCES
|
||||
{
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_NONE = 0, /**< The event does not have a notification. */
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_800US, /**< The distance from the active notification to start of radio activity. */
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_1740US, /**< The distance from the active notification to start of radio activity. */
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_2680US, /**< The distance from the active notification to start of radio activity. */
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_3620US, /**< The distance from the active notification to start of radio activity. */
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_4560US, /**< The distance from the active notification to start of radio activity. */
|
||||
NRF_RADIO_NOTIFICATION_DISTANCE_5500US /**< The distance from the active notification to start of radio activity. */
|
||||
};
|
||||
|
||||
|
||||
/**@brief Radio notification types. */
|
||||
enum NRF_RADIO_NOTIFICATION_TYPES
|
||||
{
|
||||
NRF_RADIO_NOTIFICATION_TYPE_NONE = 0, /**< The event does not have a radio notification signal. */
|
||||
NRF_RADIO_NOTIFICATION_TYPE_INT_ON_ACTIVE, /**< Using interrupt for notification when the radio will be enabled. */
|
||||
NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE, /**< Using interrupt for notification when the radio has been disabled. */
|
||||
NRF_RADIO_NOTIFICATION_TYPE_INT_ON_BOTH, /**< Using interrupt for notification both when the radio will be enabled and disabled. */
|
||||
};
|
||||
|
||||
/**@brief The Radio signal callback types. */
|
||||
enum NRF_RADIO_CALLBACK_SIGNAL_TYPE
|
||||
{
|
||||
NRF_RADIO_CALLBACK_SIGNAL_TYPE_START, /**< This signal indicates the start of the radio timeslot. */
|
||||
NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0, /**< This signal indicates the NRF_TIMER0 interrupt. */
|
||||
NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO, /**< This signal indicates the NRF_RADIO interrupt. */
|
||||
NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_FAILED, /**< This signal indicates extend action failed. */
|
||||
NRF_RADIO_CALLBACK_SIGNAL_TYPE_EXTEND_SUCCEEDED /**< This signal indicates extend action succeeded. */
|
||||
};
|
||||
|
||||
/**@brief The actions requested by the signal callback.
|
||||
*
|
||||
* This code gives the SOC instructions about what action to take when the signal callback has
|
||||
* returned.
|
||||
*/
|
||||
enum NRF_RADIO_SIGNAL_CALLBACK_ACTION
|
||||
{
|
||||
NRF_RADIO_SIGNAL_CALLBACK_ACTION_NONE, /**< Return without action. */
|
||||
NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND, /**< Request an extension of the current timeslot (maximum execution time for this action is when the extension succeeded). */
|
||||
NRF_RADIO_SIGNAL_CALLBACK_ACTION_END, /**< End the current radio timeslot. */
|
||||
NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END /**< Request a new radio timeslot and end the current timeslot. */
|
||||
};
|
||||
|
||||
/**@brief Radio timeslot high frequency clock source configuration. */
|
||||
enum NRF_RADIO_HFCLK_CFG
|
||||
{
|
||||
NRF_RADIO_HFCLK_CFG_XTAL_GUARANTEED, /**< The SoftDevice will guarantee that the high frequency clock source is the
|
||||
external crystal for the whole duration of the timeslot. This should be the
|
||||
preferred option for events that use the radio or require high timing accuracy. */
|
||||
NRF_RADIO_HFCLK_CFG_NO_GUARANTEE /**< This configuration allows for earlier and tighter scheduling of timeslots.
|
||||
The RC oscillator may be the clock source in part or for the whole duration of the timeslot.
|
||||
The RC oscillator's accuracy must therefore be taken into consideration.
|
||||
@note If the application will use the radio peripheral in timeslots with this configuration,
|
||||
it must make sure that the crystal is running and stable before starting the radio. */
|
||||
};
|
||||
|
||||
/**@brief Radio timeslot priorities. */
|
||||
enum NRF_RADIO_PRIORITY
|
||||
{
|
||||
NRF_RADIO_PRIORITY_HIGH, /**< High (equal priority as the normal connection priority of the SoftDevice stack(s)). */
|
||||
NRF_RADIO_PRIORITY_NORMAL, /**< Normal (equal priority as the priority of secondary activites of the SoftDevice stack(s)). */
|
||||
};
|
||||
|
||||
/**@brief Radio timeslot request type. */
|
||||
enum NRF_RADIO_REQUEST_TYPE
|
||||
{
|
||||
NRF_RADIO_REQ_TYPE_EARLIEST, /**< Request radio timeslot as early as possible. This should always be used for the first request in a session. */
|
||||
NRF_RADIO_REQ_TYPE_NORMAL /**< Normal radio timeslot request. */
|
||||
};
|
||||
|
||||
/**@brief SoC Events. */
|
||||
enum NRF_SOC_EVTS
|
||||
{
|
||||
NRF_EVT_HFCLKSTARTED, /**< Event indicating that the HFCLK has started. */
|
||||
NRF_EVT_POWER_FAILURE_WARNING, /**< Event indicating that a power failure warning has occurred. */
|
||||
NRF_EVT_FLASH_OPERATION_SUCCESS, /**< Event indicating that the ongoing flash operation has completed successfully. */
|
||||
NRF_EVT_FLASH_OPERATION_ERROR, /**< Event indicating that the ongoing flash operation has timed out with an error. */
|
||||
NRF_EVT_RADIO_BLOCKED, /**< Event indicating that a radio timeslot was blocked. */
|
||||
NRF_EVT_RADIO_CANCELED, /**< Event indicating that a radio timeslot was canceled by SoftDevice. */
|
||||
NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN, /**< Event indicating that a radio timeslot signal callback handler return was invalid. */
|
||||
NRF_EVT_RADIO_SESSION_IDLE, /**< Event indicating that a radio timeslot session is idle. */
|
||||
NRF_EVT_RADIO_SESSION_CLOSED, /**< Event indicating that a radio timeslot session is closed. */
|
||||
NRF_EVT_NUMBER_OF_EVTS
|
||||
};
|
||||
|
||||
/**@} */
|
||||
|
||||
|
||||
/**@addtogroup NRF_SOC_STRUCTURES Structures
|
||||
* @{ */
|
||||
|
||||
/**@brief Represents a mutex for use with the nrf_mutex functions.
|
||||
* @note Accessing the value directly is not safe, use the mutex functions!
|
||||
*/
|
||||
typedef volatile uint8_t nrf_mutex_t;
|
||||
|
||||
/**@brief Parameters for a request for a timeslot as early as possible. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t hfclk; /**< High frequency clock source, see @ref NRF_RADIO_HFCLK_CFG. */
|
||||
uint8_t priority; /**< The radio timeslot priority, see @ref NRF_RADIO_PRIORITY. */
|
||||
uint32_t length_us; /**< The radio timeslot length (in the range 100 to 100,000] microseconds). */
|
||||
uint32_t timeout_us; /**< Longest acceptable delay until the start of the requested timeslot (up to @ref NRF_RADIO_EARLIEST_TIMEOUT_MAX_US microseconds). */
|
||||
} nrf_radio_request_earliest_t;
|
||||
|
||||
/**@brief Parameters for a normal radio timeslot request. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t hfclk; /**< High frequency clock source, see @ref NRF_RADIO_HFCLK_CFG. */
|
||||
uint8_t priority; /**< The radio timeslot priority, see @ref NRF_RADIO_PRIORITY. */
|
||||
uint32_t distance_us; /**< Distance from the start of the previous radio timeslot (up to @ref NRF_RADIO_DISTANCE_MAX_US microseconds). */
|
||||
uint32_t length_us; /**< The radio timeslot length (in the range [100..100,000] microseconds). */
|
||||
} nrf_radio_request_normal_t;
|
||||
|
||||
/**@brief Radio timeslot request parameters. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t request_type; /**< Type of request, see @ref NRF_RADIO_REQUEST_TYPE. */
|
||||
union
|
||||
{
|
||||
nrf_radio_request_earliest_t earliest; /**< Parameters for requesting a radio timeslot as early as possible. */
|
||||
nrf_radio_request_normal_t normal; /**< Parameters for requesting a normal radio timeslot. */
|
||||
} params; /**< Parameter union. */
|
||||
} nrf_radio_request_t;
|
||||
|
||||
/**@brief Return parameters of the radio timeslot signal callback. */
|
||||
typedef struct
|
||||
{
|
||||
uint8_t callback_action; /**< The action requested by the application when returning from the signal callback, see @ref NRF_RADIO_SIGNAL_CALLBACK_ACTION. */
|
||||
union
|
||||
{
|
||||
struct
|
||||
{
|
||||
nrf_radio_request_t * p_next; /**< The request parameters for the next radio timeslot. */
|
||||
} request; /**< Additional parameters for return_code @ref NRF_RADIO_SIGNAL_CALLBACK_ACTION_REQUEST_AND_END. */
|
||||
struct
|
||||
{
|
||||
uint32_t length_us; /**< Requested extension of the radio timeslot duration (microseconds) (for minimum time see @ref NRF_RADIO_MINIMUM_TIMESLOT_LENGTH_EXTENSION_TIME_US). */
|
||||
} extend; /**< Additional parameters for return_code @ref NRF_RADIO_SIGNAL_CALLBACK_ACTION_EXTEND. */
|
||||
} params; /**< Parameter union. */
|
||||
} nrf_radio_signal_callback_return_param_t;
|
||||
|
||||
/**@brief The radio timeslot signal callback type.
|
||||
*
|
||||
* @note In case of invalid return parameters, the radio timeslot will automatically end
|
||||
* immediately after returning from the signal callback and the
|
||||
* @ref NRF_EVT_RADIO_SIGNAL_CALLBACK_INVALID_RETURN event will be sent.
|
||||
* @note The returned struct pointer must remain valid after the signal callback
|
||||
* function returns. For instance, this means that it must not point to a stack variable.
|
||||
*
|
||||
* @param[in] signal_type Type of signal, see @ref NRF_RADIO_CALLBACK_SIGNAL_TYPE.
|
||||
*
|
||||
* @return Pointer to structure containing action requested by the application.
|
||||
*/
|
||||
typedef nrf_radio_signal_callback_return_param_t * (*nrf_radio_signal_callback_t) (uint8_t signal_type);
|
||||
|
||||
/**@brief AES ECB parameter typedefs */
|
||||
typedef uint8_t soc_ecb_key_t[SOC_ECB_KEY_LENGTH]; /**< Encryption key type. */
|
||||
typedef uint8_t soc_ecb_cleartext_t[SOC_ECB_CLEARTEXT_LENGTH]; /**< Cleartext data type. */
|
||||
typedef uint8_t soc_ecb_ciphertext_t[SOC_ECB_CIPHERTEXT_LENGTH]; /**< Ciphertext data type. */
|
||||
|
||||
/**@brief AES ECB data structure */
|
||||
typedef struct
|
||||
{
|
||||
soc_ecb_key_t key; /**< Encryption key. */
|
||||
soc_ecb_cleartext_t cleartext; /**< Cleartext data. */
|
||||
soc_ecb_ciphertext_t ciphertext; /**< Ciphertext data. */
|
||||
} nrf_ecb_hal_data_t;
|
||||
|
||||
/**@brief AES ECB block. Used to provide multiple blocks in a single call
|
||||
to @ref sd_ecb_blocks_encrypt.*/
|
||||
typedef struct
|
||||
{
|
||||
soc_ecb_key_t* p_key; /**< Pointer to the Encryption key. */
|
||||
soc_ecb_cleartext_t* p_cleartext; /**< Pointer to the Cleartext data. */
|
||||
soc_ecb_ciphertext_t* p_ciphertext; /**< Pointer to the Ciphertext data. */
|
||||
} nrf_ecb_hal_data_block_t;
|
||||
|
||||
/**@} */
|
||||
|
||||
/**@addtogroup NRF_SOC_FUNCTIONS Functions
|
||||
* @{ */
|
||||
|
||||
/**@brief Initialize a mutex.
|
||||
*
|
||||
* @param[in] p_mutex Pointer to the mutex to initialize.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_MUTEX_NEW, uint32_t, sd_mutex_new(nrf_mutex_t * p_mutex));
|
||||
|
||||
/**@brief Attempt to acquire a mutex.
|
||||
*
|
||||
* @param[in] p_mutex Pointer to the mutex to acquire.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The mutex was successfully acquired.
|
||||
* @retval ::NRF_ERROR_SOC_MUTEX_ALREADY_TAKEN The mutex could not be acquired.
|
||||
*/
|
||||
SVCALL(SD_MUTEX_ACQUIRE, uint32_t, sd_mutex_acquire(nrf_mutex_t * p_mutex));
|
||||
|
||||
/**@brief Release a mutex.
|
||||
*
|
||||
* @param[in] p_mutex Pointer to the mutex to release.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_MUTEX_RELEASE, uint32_t, sd_mutex_release(nrf_mutex_t * p_mutex));
|
||||
|
||||
/**@brief Query the capacity of the application random pool.
|
||||
*
|
||||
* @param[out] p_pool_capacity The capacity of the pool.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_RAND_APPLICATION_POOL_CAPACITY_GET, uint32_t, sd_rand_application_pool_capacity_get(uint8_t * p_pool_capacity));
|
||||
|
||||
/**@brief Get number of random bytes available to the application.
|
||||
*
|
||||
* @param[out] p_bytes_available The number of bytes currently available in the pool.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_RAND_APPLICATION_BYTES_AVAILABLE_GET, uint32_t, sd_rand_application_bytes_available_get(uint8_t * p_bytes_available));
|
||||
|
||||
/**@brief Get random bytes from the application pool.
|
||||
*
|
||||
* @param[out] p_buff Pointer to unit8_t buffer for storing the bytes.
|
||||
* @param[in] length Number of bytes to take from pool and place in p_buff.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The requested bytes were written to p_buff.
|
||||
* @retval ::NRF_ERROR_SOC_RAND_NOT_ENOUGH_VALUES No bytes were written to the buffer, because there were not enough bytes available.
|
||||
*/
|
||||
SVCALL(SD_RAND_APPLICATION_VECTOR_GET, uint32_t, sd_rand_application_vector_get(uint8_t * p_buff, uint8_t length));
|
||||
|
||||
/**@brief Gets the reset reason register.
|
||||
*
|
||||
* @param[out] p_reset_reason Contents of the NRF_POWER->RESETREAS register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_RESET_REASON_GET, uint32_t, sd_power_reset_reason_get(uint32_t * p_reset_reason));
|
||||
|
||||
/**@brief Clears the bits of the reset reason register.
|
||||
*
|
||||
* @param[in] reset_reason_clr_msk Contains the bits to clear from the reset reason register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_RESET_REASON_CLR, uint32_t, sd_power_reset_reason_clr(uint32_t reset_reason_clr_msk));
|
||||
|
||||
/**@brief Sets the power mode when in CPU sleep.
|
||||
*
|
||||
* @param[in] power_mode The power mode to use when in CPU sleep, see @ref NRF_POWER_MODES. @sa sd_app_evt_wait
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The power mode was set.
|
||||
* @retval ::NRF_ERROR_SOC_POWER_MODE_UNKNOWN The power mode was unknown.
|
||||
*/
|
||||
SVCALL(SD_POWER_MODE_SET, uint32_t, sd_power_mode_set(uint8_t power_mode));
|
||||
|
||||
/**@brief Puts the chip in System OFF mode.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_POWER_OFF_SHOULD_NOT_RETURN
|
||||
*/
|
||||
SVCALL(SD_POWER_SYSTEM_OFF, uint32_t, sd_power_system_off(void));
|
||||
|
||||
/**@brief Enables or disables the power-fail comparator.
|
||||
*
|
||||
* Enabling this will give a softdevice event (NRF_EVT_POWER_FAILURE_WARNING) when the power failure warning occurs.
|
||||
* The event can be retrieved with sd_evt_get();
|
||||
*
|
||||
* @param[in] pof_enable True if the power-fail comparator should be enabled, false if it should be disabled.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_POF_ENABLE, uint32_t, sd_power_pof_enable(uint8_t pof_enable));
|
||||
|
||||
/**@brief Sets the power-fail threshold value.
|
||||
*
|
||||
* @param[in] threshold The power-fail threshold value to use, see @ref NRF_POWER_THRESHOLDS.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS The power failure threshold was set.
|
||||
* @retval ::NRF_ERROR_SOC_POWER_POF_THRESHOLD_UNKNOWN The power failure threshold is unknown.
|
||||
*/
|
||||
SVCALL(SD_POWER_POF_THRESHOLD_SET, uint32_t, sd_power_pof_threshold_set(uint8_t threshold));
|
||||
|
||||
/**@brief Sets bits in the NRF_POWER->RAMON register.
|
||||
*
|
||||
* @param[in] ramon Contains the bits needed to be set in the NRF_POWER->RAMON register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_RAMON_SET, uint32_t, sd_power_ramon_set(uint32_t ramon));
|
||||
|
||||
/**@brief Clears bits in the NRF_POWER->RAMON register.
|
||||
*
|
||||
* @param ramon Contains the bits needed to be cleared in the NRF_POWER->RAMON register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_RAMON_CLR, uint32_t, sd_power_ramon_clr(uint32_t ramon));
|
||||
|
||||
/**@brief Get contents of NRF_POWER->RAMON register, indicates power status of ram blocks.
|
||||
*
|
||||
* @param[out] p_ramon Content of NRF_POWER->RAMON register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_RAMON_GET, uint32_t, sd_power_ramon_get(uint32_t * p_ramon));
|
||||
|
||||
/**@brief Set bits in the general purpose retention registers (NRF_POWER->GPREGRET*).
|
||||
*
|
||||
* @param[in] gpregret_id 0 for GPREGRET, 1 for GPREGRET2.
|
||||
* @param[in] gpregret_msk Bits to be set in the GPREGRET register.
|
||||
*
|
||||
* @note nRF51 does only have one general purpose retained register, so gpregret_id must be 0 on nRF51.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_GPREGRET_SET, uint32_t, sd_power_gpregret_set(uint32_t gpregret_id, uint32_t gpregret_msk));
|
||||
|
||||
/**@brief Clear bits in the general purpose retention registers (NRF_POWER->GPREGRET*).
|
||||
*
|
||||
* @param[in] gpregret_id 0 for GPREGRET, 1 for GPREGRET2.
|
||||
* @param[in] gpregret_msk Bits to be clear in the GPREGRET register.
|
||||
*
|
||||
* @note nRF51 does only have one general purpose retained register, so gpregret_id must be 0 on nRF51.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_GPREGRET_CLR, uint32_t, sd_power_gpregret_clr(uint32_t gpregret_id, uint32_t gpregret_msk));
|
||||
|
||||
/**@brief Get contents of the general purpose retention registers (NRF_POWER->GPREGRET*).
|
||||
*
|
||||
* @param[in] gpregret_id 0 for GPREGRET, 1 for GPREGRET2.
|
||||
* @param[out] p_gpregret Contents of the GPREGRET register.
|
||||
*
|
||||
* @note nRF51 does only have one general purpose retained register, so gpregret_id must be 0 on nRF51.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_POWER_GPREGRET_GET, uint32_t, sd_power_gpregret_get(uint32_t gpregret_id, uint32_t *p_gpregret));
|
||||
|
||||
/**@brief Sets the DCDC mode.
|
||||
*
|
||||
* Enable or disable the DCDC peripheral.
|
||||
*
|
||||
* @param[in] dcdc_mode The mode of the DCDC, see @ref NRF_POWER_DCDC_MODES.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM The DCDC mode is invalid.
|
||||
*/
|
||||
SVCALL(SD_POWER_DCDC_MODE_SET, uint32_t, sd_power_dcdc_mode_set(uint8_t dcdc_mode));
|
||||
|
||||
/**@brief Request the high frequency crystal oscillator.
|
||||
*
|
||||
* Will start the high frequency crystal oscillator, the startup time of the crystal varies
|
||||
* and the ::sd_clock_hfclk_is_running function can be polled to check if it has started.
|
||||
*
|
||||
* @see sd_clock_hfclk_is_running
|
||||
* @see sd_clock_hfclk_release
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_CLOCK_HFCLK_REQUEST, uint32_t, sd_clock_hfclk_request(void));
|
||||
|
||||
/**@brief Releases the high frequency crystal oscillator.
|
||||
*
|
||||
* Will stop the high frequency crystal oscillator, this happens immediately.
|
||||
*
|
||||
* @see sd_clock_hfclk_is_running
|
||||
* @see sd_clock_hfclk_request
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_CLOCK_HFCLK_RELEASE, uint32_t, sd_clock_hfclk_release(void));
|
||||
|
||||
/**@brief Checks if the high frequency crystal oscillator is running.
|
||||
*
|
||||
* @see sd_clock_hfclk_request
|
||||
* @see sd_clock_hfclk_release
|
||||
*
|
||||
* @param[out] p_is_running 1 if the external crystal oscillator is running, 0 if not.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_CLOCK_HFCLK_IS_RUNNING, uint32_t, sd_clock_hfclk_is_running(uint32_t * p_is_running));
|
||||
|
||||
/**@brief Waits for an application event.
|
||||
*
|
||||
* An application event is either an application interrupt or a pended interrupt when the
|
||||
* interrupt is disabled. When the interrupt is enabled it will be taken immediately since
|
||||
* this function will wait in thread mode, then the execution will return in the application's
|
||||
* main thread. When an interrupt is disabled and gets pended it will return to the application's
|
||||
* thread main. The application must ensure that the pended flag is cleared using
|
||||
* ::sd_nvic_ClearPendingIRQ in order to sleep using this function. This is only necessary for
|
||||
* disabled interrupts, as the interrupt handler will clear the pending flag automatically for
|
||||
* enabled interrupts.
|
||||
*
|
||||
* In order to wake up from disabled interrupts, the SEVONPEND flag has to be set in the Cortex-M0
|
||||
* System Control Register (SCR). @sa CMSIS_SCB
|
||||
*
|
||||
* @note If an application interrupt has happened since the last time sd_app_evt_wait was
|
||||
* called this function will return immediately and not go to sleep. This is to avoid race
|
||||
* conditions that can occur when a flag is updated in the interrupt handler and processed
|
||||
* in the main loop.
|
||||
*
|
||||
* @post An application interrupt has happened or a interrupt pending flag is set.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_APP_EVT_WAIT, uint32_t, sd_app_evt_wait(void));
|
||||
|
||||
/**@brief Get PPI channel enable register contents.
|
||||
*
|
||||
* @param[out] p_channel_enable The contents of the PPI CHEN register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_CHANNEL_ENABLE_GET, uint32_t, sd_ppi_channel_enable_get(uint32_t * p_channel_enable));
|
||||
|
||||
/**@brief Set PPI channel enable register.
|
||||
*
|
||||
* @param[in] channel_enable_set_msk Mask containing the bits to set in the PPI CHEN register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_CHANNEL_ENABLE_SET, uint32_t, sd_ppi_channel_enable_set(uint32_t channel_enable_set_msk));
|
||||
|
||||
/**@brief Clear PPI channel enable register.
|
||||
*
|
||||
* @param[in] channel_enable_clr_msk Mask containing the bits to clear in the PPI CHEN register.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_CHANNEL_ENABLE_CLR, uint32_t, sd_ppi_channel_enable_clr(uint32_t channel_enable_clr_msk));
|
||||
|
||||
/**@brief Assign endpoints to a PPI channel.
|
||||
*
|
||||
* @param[in] channel_num Number of the PPI channel to assign.
|
||||
* @param[in] evt_endpoint Event endpoint of the PPI channel.
|
||||
* @param[in] task_endpoint Task endpoint of the PPI channel.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_PPI_INVALID_CHANNEL The channel number is invalid.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_CHANNEL_ASSIGN, uint32_t, sd_ppi_channel_assign(uint8_t channel_num, const volatile void * evt_endpoint, const volatile void * task_endpoint));
|
||||
|
||||
/**@brief Task to enable a channel group.
|
||||
*
|
||||
* @param[in] group_num Number of the channel group.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_GROUP_TASK_ENABLE, uint32_t, sd_ppi_group_task_enable(uint8_t group_num));
|
||||
|
||||
/**@brief Task to disable a channel group.
|
||||
*
|
||||
* @param[in] group_num Number of the PPI group.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_GROUP_TASK_DISABLE, uint32_t, sd_ppi_group_task_disable(uint8_t group_num));
|
||||
|
||||
/**@brief Assign PPI channels to a channel group.
|
||||
*
|
||||
* @param[in] group_num Number of the channel group.
|
||||
* @param[in] channel_msk Mask of the channels to assign to the group.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_GROUP_ASSIGN, uint32_t, sd_ppi_group_assign(uint8_t group_num, uint32_t channel_msk));
|
||||
|
||||
/**@brief Gets the PPI channels of a channel group.
|
||||
*
|
||||
* @param[in] group_num Number of the channel group.
|
||||
* @param[out] p_channel_msk Mask of the channels assigned to the group.
|
||||
*
|
||||
* @retval ::NRF_ERROR_SOC_PPI_INVALID_GROUP The group number is invalid.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_PPI_GROUP_GET, uint32_t, sd_ppi_group_get(uint8_t group_num, uint32_t * p_channel_msk));
|
||||
|
||||
/**@brief Configures the Radio Notification signal.
|
||||
*
|
||||
* @note
|
||||
* - The notification signal latency depends on the interrupt priority settings of SWI used
|
||||
* for notification signal.
|
||||
* - To ensure that the radio notification signal behaves in a consistent way, always
|
||||
* configure radio notifications when there is no protocol stack or other SoftDevice
|
||||
* activity in progress. It is recommended that the radio notification signal is
|
||||
* configured directly after the SoftDevice has been enabled.
|
||||
* - In the period between the ACTIVE signal and the start of the Radio Event, the SoftDevice
|
||||
* will interrupt the application to do Radio Event preparation.
|
||||
* - Using the Radio Notification feature may limit the bandwidth, as the SoftDevice may have
|
||||
* to shorten the connection events to have time for the Radio Notification signals.
|
||||
*
|
||||
* @param[in] type Type of notification signal, see @ref NRF_RADIO_NOTIFICATION_TYPES.
|
||||
* @ref NRF_RADIO_NOTIFICATION_TYPE_NONE shall be used to turn off radio
|
||||
* notification. Using @ref NRF_RADIO_NOTIFICATION_DISTANCE_NONE is
|
||||
* recommended (but not required) to be used with
|
||||
* @ref NRF_RADIO_NOTIFICATION_TYPE_NONE.
|
||||
*
|
||||
* @param[in] distance Distance between the notification signal and start of radio activity, see @ref NRF_RADIO_NOTIFICATION_DISTANCES.
|
||||
* This parameter is ignored when @ref NRF_RADIO_NOTIFICATION_TYPE_NONE or
|
||||
* @ref NRF_RADIO_NOTIFICATION_TYPE_INT_ON_INACTIVE is used.
|
||||
*
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM The group number is invalid.
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_RADIO_NOTIFICATION_CFG_SET, uint32_t, sd_radio_notification_cfg_set(uint8_t type, uint8_t distance));
|
||||
|
||||
/**@brief Encrypts a block according to the specified parameters.
|
||||
*
|
||||
* 128-bit AES encryption.
|
||||
*
|
||||
* @note:
|
||||
* - The application may set the SEVONPEND bit in the SCR to 1 to make the SoftDevice sleep while
|
||||
* the ECB is running. The SEVONPEND bit should only be cleared (set to 0) from application
|
||||
* main or low interrupt level.
|
||||
*
|
||||
* @param[in, out] p_ecb_data Pointer to the ECB parameters' struct (two input
|
||||
* parameters and one output parameter).
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_ECB_BLOCK_ENCRYPT, uint32_t, sd_ecb_block_encrypt(nrf_ecb_hal_data_t * p_ecb_data));
|
||||
|
||||
/**@brief Encrypts multiple data blocks provided as an array of data block structures.
|
||||
*
|
||||
* @details: Performs 128-bit AES encryption on multiple data blocks
|
||||
*
|
||||
* @note:
|
||||
* - The application may set the SEVONPEND bit in the SCR to 1 to make the SoftDevice sleep while
|
||||
* the ECB is running. The SEVONPEND bit should only be cleared (set to 0) from application
|
||||
* main or low interrupt level.
|
||||
*
|
||||
* @param[in] block_count Count of blocks in the p_data_blocks array.
|
||||
* @param[in,out] p_data_blocks Pointer to the first entry in a contiguous array of
|
||||
* @ref nrf_ecb_hal_data_block_t structures.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS
|
||||
*/
|
||||
SVCALL(SD_ECB_BLOCKS_ENCRYPT, uint32_t, sd_ecb_blocks_encrypt(uint8_t block_count, nrf_ecb_hal_data_block_t * p_data_blocks));
|
||||
|
||||
/**@brief Gets any pending events generated by the SoC API.
|
||||
*
|
||||
* The application should keep calling this function to get events, until ::NRF_ERROR_NOT_FOUND is returned.
|
||||
*
|
||||
* @param[out] p_evt_id Set to one of the values in @ref NRF_SOC_EVTS, if any events are pending.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS An event was pending. The event id is written in the p_evt_id parameter.
|
||||
* @retval ::NRF_ERROR_NOT_FOUND No pending events.
|
||||
*/
|
||||
SVCALL(SD_EVT_GET, uint32_t, sd_evt_get(uint32_t * p_evt_id));
|
||||
|
||||
/**@brief Get the temperature measured on the chip
|
||||
*
|
||||
* This function will block until the temperature measurement is done.
|
||||
* It takes around 50us from call to return.
|
||||
*
|
||||
* @param[out] p_temp Result of temperature measurement. Die temperature in 0.25 degrees celsius.
|
||||
*
|
||||
* @retval ::NRF_SUCCESS A temperature measurement was done, and the temperature was written to temp
|
||||
*/
|
||||
SVCALL(SD_TEMP_GET, uint32_t, sd_temp_get(int32_t * p_temp));
|
||||
|
||||
/**@brief Flash Write
|
||||
*
|
||||
* Commands to write a buffer to flash
|
||||
*
|
||||
* If the SoftDevice is enabled:
|
||||
* This call initiates the flash access command, and its completion will be communicated to the
|
||||
* application with exactly one of the following events:
|
||||
* - @ref NRF_EVT_FLASH_OPERATION_SUCCESS - The command was successfully completed.
|
||||
* - @ref NRF_EVT_FLASH_OPERATION_ERROR - The command could not be started.
|
||||
*
|
||||
* If the SoftDevice is not enabled no event will be generated, and this call will return @ref NRF_SUCCESS when the
|
||||
* write has been completed
|
||||
*
|
||||
* @note
|
||||
* - This call takes control over the radio and the CPU during flash erase and write to make sure that
|
||||
* they will not interfere with the flash access. This means that all interrupts will be blocked
|
||||
* for a predictable time (depending on the NVMC specification in nRF51 Series Reference Manual
|
||||
* and the command parameters).
|
||||
* - The data in the p_src buffer should not be modified before the @ref NRF_EVT_FLASH_OPERATION_SUCCESS
|
||||
* or the @ref NRF_EVT_FLASH_OPERATION_ERROR have been received if the SoftDevice is enabled.
|
||||
*
|
||||
*
|
||||
* @param[in] p_dst Pointer to start of flash location to be written.
|
||||
* @param[in] p_src Pointer to buffer with data to be written.
|
||||
* @param[in] size Number of 32-bit words to write. Maximum size is 256 32-bit words for nRF51 and 1024 for nRF52.
|
||||
*
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Tried to write to a non existing flash address, or p_dst or p_src was unaligned.
|
||||
* @retval ::NRF_ERROR_BUSY The previous command has not yet completed.
|
||||
* @retval ::NRF_ERROR_INVALID_LENGTH Size was 0, or higher than the maximum allowed size.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Tried to write to or read from protected location.
|
||||
* @retval ::NRF_SUCCESS The command was accepted.
|
||||
*/
|
||||
SVCALL(SD_FLASH_WRITE, uint32_t, sd_flash_write(uint32_t * const p_dst, uint32_t const * const p_src, uint32_t size));
|
||||
|
||||
|
||||
/**@brief Flash Erase page
|
||||
*
|
||||
* Commands to erase a flash page
|
||||
* If the SoftDevice is enabled:
|
||||
* This call initiates the flash access command, and its completion will be communicated to the
|
||||
* application with exactly one of the following events:
|
||||
* - @ref NRF_EVT_FLASH_OPERATION_SUCCESS - The command was successfully completed.
|
||||
* - @ref NRF_EVT_FLASH_OPERATION_ERROR - The command could not be started.
|
||||
*
|
||||
* If the SoftDevice is not enabled no event will be generated, and this call will return @ref NRF_SUCCESS when the
|
||||
* erase has been completed
|
||||
*
|
||||
* @note
|
||||
* - This call takes control over the radio and the CPU during flash erase and write to make sure that
|
||||
* they will not interfere with the flash access. This means that all interrupts will be blocked
|
||||
* for a predictable time (depending on the NVMC specification in nRF51 Series Reference Manual
|
||||
* and the command parameters).
|
||||
*
|
||||
*
|
||||
* @param[in] page_number Pagenumber of the page to erase
|
||||
* @retval ::NRF_ERROR_INTERNAL If a new session could not be opened due to an internal error.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR Tried to erase to a non existing flash page.
|
||||
* @retval ::NRF_ERROR_BUSY The previous command has not yet completed.
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Tried to erase a protected page.
|
||||
* @retval ::NRF_SUCCESS The command was accepted.
|
||||
*/
|
||||
SVCALL(SD_FLASH_PAGE_ERASE, uint32_t, sd_flash_page_erase(uint32_t page_number));
|
||||
|
||||
|
||||
/**@brief Flash Protection set
|
||||
*
|
||||
* Commands to set the flash protection configuration registers.
|
||||
On nRF51 this sets the PROTENSETx registers of the MPU peripheral.
|
||||
On nRF52 this sets the CONFIGx registers of the BPROT peripheral.
|
||||
*
|
||||
* @note To read the values read them directly. They are only write-protected.
|
||||
*
|
||||
* @param[in] block_cfg0 Value to be written to the configuration register.
|
||||
* @param[in] block_cfg1 Value to be written to the configuration register.
|
||||
* @param[in] block_cfg2 Value to be written to the configuration register (ignored on nRF51).
|
||||
* @param[in] block_cfg3 Value to be written to the configuration register (ignored on nRF51).
|
||||
*
|
||||
* @retval ::NRF_ERROR_FORBIDDEN Tried to protect the SoftDevice.
|
||||
* @retval ::NRF_SUCCESS Values successfully written to configuration registers.
|
||||
*/
|
||||
SVCALL(SD_FLASH_PROTECT, uint32_t, sd_flash_protect(uint32_t block_cfg0, uint32_t block_cfg1, uint32_t block_cfg2, uint32_t block_cfg3));
|
||||
|
||||
/**@brief Opens a session for radio timeslot requests.
|
||||
*
|
||||
* @note Only one session can be open at a time.
|
||||
* @note p_radio_signal_callback(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START) will be called when the radio timeslot
|
||||
* starts. From this point the NRF_RADIO and NRF_TIMER0 peripherals can be freely accessed
|
||||
* by the application.
|
||||
* @note p_radio_signal_callback(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_TIMER0) is called whenever the NRF_TIMER0
|
||||
* interrupt occurs.
|
||||
* @note p_radio_signal_callback(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_RADIO) is called whenever the NRF_RADIO
|
||||
* interrupt occurs.
|
||||
* @note p_radio_signal_callback() will be called at ARM interrupt priority level 0. This
|
||||
* implies that none of the sd_* API calls can be used from p_radio_signal_callback().
|
||||
*
|
||||
* @param[in] p_radio_signal_callback The signal callback.
|
||||
*
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR p_radio_signal_callback is an invalid function pointer.
|
||||
* @retval ::NRF_ERROR_BUSY If session cannot be opened.
|
||||
* @retval ::NRF_ERROR_INTERNAL If a new session could not be opened due to an internal error.
|
||||
* @retval ::NRF_SUCCESS Otherwise.
|
||||
*/
|
||||
SVCALL(SD_RADIO_SESSION_OPEN, uint32_t, sd_radio_session_open(nrf_radio_signal_callback_t p_radio_signal_callback));
|
||||
|
||||
/**@brief Closes a session for radio timeslot requests.
|
||||
*
|
||||
* @note Any current radio timeslot will be finished before the session is closed.
|
||||
* @note If a radio timeslot is scheduled when the session is closed, it will be canceled.
|
||||
* @note The application cannot consider the session closed until the @ref NRF_EVT_RADIO_SESSION_CLOSED
|
||||
* event is received.
|
||||
*
|
||||
* @retval ::NRF_ERROR_FORBIDDEN If session not opened.
|
||||
* @retval ::NRF_ERROR_BUSY If session is currently being closed.
|
||||
* @retval ::NRF_SUCCESS Otherwise.
|
||||
*/
|
||||
SVCALL(SD_RADIO_SESSION_CLOSE, uint32_t, sd_radio_session_close(void));
|
||||
|
||||
/**@brief Requests a radio timeslot.
|
||||
*
|
||||
* @note The request type is determined by p_request->request_type, and can be one of @ref NRF_RADIO_REQ_TYPE_EARLIEST
|
||||
* and @ref NRF_RADIO_REQ_TYPE_NORMAL. The first request in a session must always be of type @ref NRF_RADIO_REQ_TYPE_EARLIEST.
|
||||
* @note For a normal request (@ref NRF_RADIO_REQ_TYPE_NORMAL), the start time of a radio timeslot is specified by
|
||||
* p_request->distance_us and is given relative to the start of the previous timeslot.
|
||||
* @note A too small p_request->distance_us will lead to a @ref NRF_EVT_RADIO_BLOCKED event.
|
||||
* @note Timeslots scheduled too close will lead to a @ref NRF_EVT_RADIO_BLOCKED event.
|
||||
* @note See the SoftDevice Specification for more on radio timeslot scheduling, distances and lengths.
|
||||
* @note If an opportunity for the first radio timeslot is not found before 100ms after the call to this
|
||||
* function, it is not scheduled, and instead a @ref NRF_EVT_RADIO_BLOCKED event is sent.
|
||||
* The application may then try to schedule the first radio timeslot again.
|
||||
* @note Successful requests will result in nrf_radio_signal_callback_t(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START).
|
||||
* Unsuccessful requests will result in a @ref NRF_EVT_RADIO_BLOCKED event, see @ref NRF_SOC_EVTS.
|
||||
* @note The jitter in the start time of the radio timeslots is +/- @ref NRF_RADIO_START_JITTER_US us.
|
||||
* @note The nrf_radio_signal_callback_t(@ref NRF_RADIO_CALLBACK_SIGNAL_TYPE_START) call has a latency relative to the
|
||||
* specified radio timeslot start, but this does not affect the actual start time of the timeslot.
|
||||
* @note NRF_TIMER0 is reset at the start of the radio timeslot, and is clocked at 1MHz from the high frequency
|
||||
* (16 MHz) clock source. If p_request->hfclk_force_xtal is true, the high frequency clock is
|
||||
* guaranteed to be clocked from the external crystal.
|
||||
* @note The SoftDevice will neither access the NRF_RADIO peripheral nor the NRF_TIMER0 peripheral
|
||||
* during the radio timeslot.
|
||||
*
|
||||
* @param[in] p_request Pointer to the request parameters.
|
||||
*
|
||||
* @retval ::NRF_ERROR_FORBIDDEN If session not opened or the session is not IDLE.
|
||||
* @retval ::NRF_ERROR_INVALID_ADDR If the p_request pointer is invalid.
|
||||
* @retval ::NRF_ERROR_INVALID_PARAM If the parameters of p_request are not valid.
|
||||
* @retval ::NRF_SUCCESS Otherwise.
|
||||
*/
|
||||
SVCALL(SD_RADIO_REQUEST, uint32_t, sd_radio_request(nrf_radio_request_t * p_request ));
|
||||
|
||||
/**@} */
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_SOC_H__
|
||||
|
||||
/**@} */
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* Copyright (c) 2000 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef NRF_SVC__
|
||||
#define NRF_SVC__
|
||||
|
||||
#include "stdint.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#ifdef SVCALL_AS_NORMAL_FUNCTION
|
||||
#define SVCALL(number, return_type, signature) return_type signature
|
||||
#else
|
||||
|
||||
#ifndef SVCALL
|
||||
#if defined (__CC_ARM)
|
||||
#define SVCALL(number, return_type, signature) return_type __svc(number) signature
|
||||
#elif defined (__GNUC__)
|
||||
#ifdef __cplusplus
|
||||
#define GCC_CAST_CPP (uint16_t)
|
||||
#else
|
||||
#define GCC_CAST_CPP
|
||||
#endif
|
||||
#define SVCALL(number, return_type, signature) \
|
||||
_Pragma("GCC diagnostic push") \
|
||||
_Pragma("GCC diagnostic ignored \"-Wreturn-type\"") \
|
||||
__attribute__((naked)) \
|
||||
__attribute__((unused)) \
|
||||
static return_type signature \
|
||||
{ \
|
||||
__asm( \
|
||||
"svc %0\n" \
|
||||
"bx r14" : : "I" (GCC_CAST_CPP number) : "r0" \
|
||||
); \
|
||||
} \
|
||||
_Pragma("GCC diagnostic pop")
|
||||
|
||||
#elif defined (__ICCARM__)
|
||||
#define PRAGMA(x) _Pragma(#x)
|
||||
#define SVCALL(number, return_type, signature) \
|
||||
PRAGMA(swi_number = (number)) \
|
||||
__swi return_type signature;
|
||||
#else
|
||||
#define SVCALL(number, return_type, signature) return_type signature
|
||||
#endif
|
||||
#endif // SVCALL
|
||||
|
||||
#endif // SVCALL_AS_NORMAL_FUNCTION
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
#endif // NRF_SVC__
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,123 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include "mbed_assert.h"
|
||||
#include "analogin_api.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_drv_saadc.h"
|
||||
|
||||
#ifdef DEVICE_ANALOGIN
|
||||
|
||||
#define ADC_12BIT_RANGE 0xFFF
|
||||
#define ADC_RANGE ADC_12BIT_RANGE
|
||||
|
||||
__STATIC_INLINE nrf_saadc_input_t nrf_drv_saadc_gpio_to_ain(uint32_t pin);
|
||||
|
||||
|
||||
static void analog_in_event_handler(nrf_drv_saadc_evt_t const *p_event)// type of nrf_drv_saadc_event_handler_t
|
||||
{
|
||||
(void) p_event;
|
||||
}
|
||||
|
||||
static const nrf_drv_saadc_config_t saadc_config =
|
||||
{
|
||||
.resolution = NRF_SAADC_RESOLUTION_12BIT,
|
||||
.oversample = NRF_SAADC_OVERSAMPLE_DISABLED,
|
||||
.interrupt_priority = SAADC_CONFIG_IRQ_PRIORITY
|
||||
};
|
||||
|
||||
void SAADC_IRQHandler(void);
|
||||
|
||||
void analogin_init(analogin_t *obj, PinName pin)
|
||||
{
|
||||
ret_code_t ret_code;
|
||||
|
||||
NVIC_SetVector(SAADC_IRQn, (uint32_t)SAADC_IRQHandler);
|
||||
|
||||
ret_code = nrf_drv_saadc_init(&saadc_config, analog_in_event_handler);
|
||||
MBED_ASSERT(((ret_code == NRF_SUCCESS) || (ret_code == NRF_ERROR_INVALID_STATE))); //NRF_ERROR_INVALID_STATE expected for multiple channels used.
|
||||
|
||||
uint8_t saadcIn = nrf_drv_saadc_gpio_to_ain(pin);
|
||||
MBED_ASSERT(saadcIn != NRF_SAADC_INPUT_DISABLED);
|
||||
|
||||
obj->adc = ADC0_0; // only one instance of ADC in nRF52 SoC
|
||||
obj->adc_pin = saadcIn - 1;
|
||||
|
||||
nrf_saadc_channel_config_t channel_config =
|
||||
NRF_DRV_SAADC_DEFAULT_CHANNEL_CONFIG_SE(saadcIn); //Single ended, negative input to ADC shorted to GND.
|
||||
|
||||
ret_code = nrf_drv_saadc_channel_init(obj->adc_pin, &channel_config);
|
||||
MBED_ASSERT(ret_code == NRF_SUCCESS);
|
||||
}
|
||||
|
||||
|
||||
uint16_t analogin_read_u16(analogin_t *obj)
|
||||
{
|
||||
int16_t adc_value;
|
||||
ret_code_t ret_code;
|
||||
|
||||
ret_code = nrf_drv_saadc_sample_convert(obj->adc_pin, &adc_value);
|
||||
MBED_ASSERT(ret_code == NRF_SUCCESS);
|
||||
|
||||
if (adc_value < 0)
|
||||
{
|
||||
// Even in the single ended mode measured value can be {-0}. Saturation for avoid casting to a big integer.
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
return (uint16_t) adc_value;
|
||||
}
|
||||
}
|
||||
|
||||
float analogin_read(analogin_t *obj)
|
||||
{
|
||||
uint16_t value = analogin_read_u16(obj);
|
||||
return (float)value * (1.0f / (float)ADC_RANGE);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @brief Function for converting a GPIO pin number to an analog input pin number used in the channel
|
||||
* configuration.
|
||||
*
|
||||
* @param[in] pin GPIO pin.
|
||||
*
|
||||
* @return Value representing an analog input pin. The function returns @ref NRF_SAADC_INPUT_DISABLED
|
||||
* if the specified pin is not an analog input.
|
||||
*/
|
||||
__STATIC_INLINE nrf_saadc_input_t nrf_drv_saadc_gpio_to_ain(uint32_t pin)
|
||||
{
|
||||
// AIN0 - AIN3
|
||||
if (pin >= 2 && pin <= 5)
|
||||
{
|
||||
//0 means "not connected", hence this "+ 1"
|
||||
return (nrf_saadc_input_t)(pin - 2 + 1);
|
||||
}
|
||||
// AIN4 - AIN7
|
||||
else if (pin >= 28 && pin <= 31)
|
||||
{
|
||||
return (nrf_saadc_input_t)(pin - 24 + 1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRF_SAADC_INPUT_DISABLED;
|
||||
}
|
||||
}
|
||||
|
||||
#endif // DEVICE_ANALOGIN
|
|
@ -0,0 +1,57 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#ifndef COMMON_RTC_H
|
||||
#define COMMON_RTC_H
|
||||
|
||||
#include "nrf_rtc.h"
|
||||
|
||||
#define RTC_COUNTER_BITS 24u
|
||||
|
||||
// Instance 0 is reserved for SoftDevice.
|
||||
// Instance 1 is used as a common one for us_ticker, lp_ticker and (in case
|
||||
// of NRF51) as an alternative tick source for RTOS.
|
||||
// ["us_ticker.c" uses hard coded addresses of the 'NRF_RTC1->EVENT_COMPARE[1]'
|
||||
// register in inline assembly implementations of COMMON_RTC_IRQ_HANDLER,
|
||||
// please remember to update those in case of doing changes here]
|
||||
#define COMMON_RTC_INSTANCE NRF_RTC1
|
||||
#define COMMON_RTC_IRQ_HANDLER RTC1_IRQHandler
|
||||
#define US_TICKER_CC_CHANNEL 0
|
||||
#define OS_TICK_CC_CHANNEL 1
|
||||
#define LP_TICKER_CC_CHANNEL 2
|
||||
|
||||
#define COMMON_RTC_EVENT_COMPARE(channel) \
|
||||
CONCAT_2(NRF_RTC_EVENT_COMPARE_, channel)
|
||||
#define COMMON_RTC_INT_COMPARE_MASK(channel) \
|
||||
CONCAT_3(NRF_RTC_INT_COMPARE, channel, _MASK)
|
||||
|
||||
#define US_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(US_TICKER_CC_CHANNEL)
|
||||
#define US_TICKER_INT_MASK COMMON_RTC_INT_COMPARE_MASK(US_TICKER_CC_CHANNEL)
|
||||
#define OS_TICK_EVENT COMMON_RTC_EVENT_COMPARE(OS_TICK_CC_CHANNEL)
|
||||
#define OS_TICK_INT_MASK COMMON_RTC_INT_COMPARE_MASK(OS_TICK_CC_CHANNEL)
|
||||
#define LP_TICKER_EVENT COMMON_RTC_EVENT_COMPARE(LP_TICKER_CC_CHANNEL)
|
||||
#define LP_TICKER_INT_MASK COMMON_RTC_INT_COMPARE_MASK(LP_TICKER_CC_CHANNEL)
|
||||
|
||||
extern bool m_common_rtc_enabled;
|
||||
extern uint32_t volatile m_common_rtc_overflows;
|
||||
|
||||
void common_rtc_init(void);
|
||||
uint32_t common_rtc_32bit_ticks_get(void);
|
||||
uint64_t common_rtc_64bit_us_get(void);
|
||||
void common_rtc_set_interrupt(uint32_t us_timestamp, uint32_t cc_channel,
|
||||
uint32_t int_mask);
|
||||
|
||||
#endif // COMMON_RTC_H
|
|
@ -0,0 +1,283 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed_assert.h"
|
||||
#include "gpio_api.h"
|
||||
#include "gpio_irq_api.h"
|
||||
#include "pinmap.h"
|
||||
#include "nrf_drv_gpiote.h"
|
||||
|
||||
#if defined(TARGET_MCU_NRF51822)
|
||||
#define GPIO_PIN_COUNT 31
|
||||
#elif defined(TARGET_MCU_NRF52832)
|
||||
#define GPIO_PIN_COUNT 32
|
||||
#elif defined(TARGET_MCU_NRF52840)
|
||||
#define GPIO_PIN_COUNT 48
|
||||
#else
|
||||
#error not recognized gpio count for mcu
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
bool used_as_gpio : 1;
|
||||
PinDirection direction : 1;
|
||||
bool init_high : 1;
|
||||
PinMode pull : 2;
|
||||
bool used_as_irq : 1;
|
||||
bool irq_fall : 1;
|
||||
bool irq_rise : 1;
|
||||
} gpio_cfg_t;
|
||||
|
||||
#if GPIO_PIN_COUNT > 32
|
||||
typedef uint64_t gpio_mask_t;
|
||||
#else
|
||||
typedef uint32_t gpio_mask_t;
|
||||
#endif
|
||||
|
||||
static gpio_mask_t m_gpio_initialized;
|
||||
static gpio_cfg_t m_gpio_cfg[GPIO_PIN_COUNT];
|
||||
|
||||
|
||||
/***********
|
||||
GPIO IRQ
|
||||
***********/
|
||||
|
||||
static gpio_irq_handler m_irq_handler;
|
||||
static uint32_t m_channel_ids[GPIO_PIN_COUNT] = {0};
|
||||
static gpio_mask_t m_gpio_irq_enabled;
|
||||
|
||||
|
||||
static void gpiote_irq_handler(nrf_drv_gpiote_pin_t pin, nrf_gpiote_polarity_t action)
|
||||
{
|
||||
nrf_gpio_pin_sense_t sense = nrf_gpio_pin_sense_get(pin);
|
||||
gpio_irq_event event = (sense == NRF_GPIO_PIN_SENSE_LOW) ? IRQ_RISE : IRQ_FALL;
|
||||
|
||||
if (m_gpio_irq_enabled & ((gpio_mask_t)1 << pin))
|
||||
{
|
||||
if (((event == IRQ_RISE) && m_gpio_cfg[pin].irq_rise)
|
||||
|| ((event == IRQ_FALL) && m_gpio_cfg[pin].irq_fall))
|
||||
{
|
||||
m_irq_handler(m_channel_ids[pin], event);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GPIOTE_IRQHandler(void);// exported from nrf_drv_gpiote.c
|
||||
|
||||
void gpio_init(gpio_t *obj, PinName pin)
|
||||
{
|
||||
obj->pin = pin;
|
||||
if (pin == (PinName)NC)
|
||||
{
|
||||
return;
|
||||
}
|
||||
MBED_ASSERT((uint32_t)pin < GPIO_PIN_COUNT);
|
||||
|
||||
NVIC_SetVector(GPIOTE_IRQn, (uint32_t) GPIOTE_IRQHandler);
|
||||
|
||||
(void) nrf_drv_gpiote_init();
|
||||
|
||||
m_gpio_cfg[obj->pin].used_as_gpio = true;
|
||||
}
|
||||
|
||||
|
||||
int gpio_read(gpio_t *obj)
|
||||
{
|
||||
MBED_ASSERT(obj->pin != (PinName)NC);
|
||||
if (m_gpio_cfg[obj->pin].direction == PIN_OUTPUT)
|
||||
{
|
||||
return (nrf_gpio_pin_out_read(obj->pin) ? 1 : 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return nrf_gpio_pin_read(obj->pin);
|
||||
}
|
||||
}
|
||||
|
||||
static void gpiote_pin_uninit(uint8_t pin)
|
||||
{
|
||||
if (m_gpio_initialized & ((gpio_mask_t)1 << pin))
|
||||
{
|
||||
if ((m_gpio_cfg[pin].direction == PIN_OUTPUT) && (!m_gpio_cfg[pin].used_as_irq))
|
||||
{
|
||||
nrf_drv_gpiote_out_uninit(pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_drv_gpiote_in_uninit(pin);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void gpio_apply_config(uint8_t pin)
|
||||
{
|
||||
if (m_gpio_cfg[pin].used_as_gpio || m_gpio_cfg[pin].used_as_irq)
|
||||
{
|
||||
if ((m_gpio_cfg[pin].direction == PIN_INPUT)
|
||||
|| (m_gpio_cfg[pin].used_as_irq))
|
||||
{
|
||||
//Configure as input.
|
||||
nrf_drv_gpiote_in_config_t cfg;
|
||||
|
||||
cfg.hi_accuracy = false;
|
||||
cfg.is_watcher = false;
|
||||
cfg.sense = NRF_GPIOTE_POLARITY_TOGGLE;
|
||||
if (m_gpio_cfg[pin].used_as_irq)
|
||||
{
|
||||
cfg.pull = NRF_GPIO_PIN_PULLUP;
|
||||
nrf_drv_gpiote_in_init(pin, &cfg, gpiote_irq_handler);
|
||||
if ((m_gpio_irq_enabled & ((gpio_mask_t)1 << pin))
|
||||
&& (m_gpio_cfg[pin].irq_rise || m_gpio_cfg[pin].irq_fall))
|
||||
{
|
||||
nrf_drv_gpiote_in_event_enable(pin, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
switch (m_gpio_cfg[pin].pull)
|
||||
{
|
||||
case PullUp:
|
||||
cfg.pull = NRF_GPIO_PIN_PULLUP;
|
||||
break;
|
||||
case PullDown:
|
||||
cfg.pull = NRF_GPIO_PIN_PULLDOWN;
|
||||
break;
|
||||
default:
|
||||
cfg.pull = NRF_GPIO_PIN_NOPULL;
|
||||
break;
|
||||
}
|
||||
nrf_drv_gpiote_in_init(pin, &cfg, NULL);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Configure as output.
|
||||
nrf_drv_gpiote_out_config_t cfg = GPIOTE_CONFIG_OUT_SIMPLE(m_gpio_cfg[pin].init_high);
|
||||
nrf_drv_gpiote_out_init(pin, &cfg);
|
||||
}
|
||||
m_gpio_initialized |= ((gpio_mask_t)1 << pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_gpio_initialized &= ~((gpio_mask_t)1 << pin);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gpio_mode(gpio_t *obj, PinMode mode)
|
||||
{
|
||||
MBED_ASSERT(obj->pin != (PinName)NC);
|
||||
|
||||
gpiote_pin_uninit(obj->pin); // try to uninitialize gpio before a change.
|
||||
|
||||
m_gpio_cfg[obj->pin].pull = mode;
|
||||
gpio_apply_config(obj->pin);
|
||||
}
|
||||
|
||||
|
||||
void gpio_dir(gpio_t *obj, PinDirection direction)
|
||||
{
|
||||
MBED_ASSERT(obj->pin != (PinName)NC);
|
||||
|
||||
gpiote_pin_uninit(obj->pin); // try to uninitialize gpio before a change.
|
||||
|
||||
m_gpio_cfg[obj->pin].direction = direction;
|
||||
gpio_apply_config(obj->pin);
|
||||
}
|
||||
|
||||
|
||||
/***********
|
||||
GPIO IRQ
|
||||
***********/
|
||||
|
||||
int gpio_irq_init(gpio_irq_t *obj, PinName pin, gpio_irq_handler handler, uint32_t id)
|
||||
{
|
||||
if (pin == NC)
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
MBED_ASSERT((uint32_t)pin < GPIO_PIN_COUNT);
|
||||
(void) nrf_drv_gpiote_init();
|
||||
|
||||
gpiote_pin_uninit(pin); // try to uninitialize gpio before a change.
|
||||
|
||||
m_gpio_cfg[pin].used_as_irq = true;
|
||||
m_channel_ids[pin] = id;
|
||||
obj->ch = pin;
|
||||
m_irq_handler = handler;
|
||||
m_channel_ids[pin] = id;
|
||||
|
||||
gpio_apply_config(pin);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void gpio_irq_free(gpio_irq_t *obj)
|
||||
{
|
||||
nrf_drv_gpiote_in_uninit(obj->ch);
|
||||
m_gpio_cfg[obj->ch].used_as_irq = false;
|
||||
m_channel_ids[obj->ch] = 0;
|
||||
|
||||
gpio_apply_config(obj->ch);
|
||||
}
|
||||
|
||||
|
||||
void gpio_irq_set(gpio_irq_t *obj, gpio_irq_event event, uint32_t enable)
|
||||
{
|
||||
gpio_cfg_t* cfg = &m_gpio_cfg[obj->ch];
|
||||
bool irq_enabled_before =
|
||||
(m_gpio_irq_enabled & ((gpio_mask_t)1 << obj->ch)) &&
|
||||
(cfg->irq_rise || cfg->irq_fall);
|
||||
|
||||
if (event == IRQ_RISE)
|
||||
{
|
||||
cfg->irq_rise = enable ? true : false;
|
||||
}
|
||||
else if (event == IRQ_FALL)
|
||||
{
|
||||
cfg->irq_fall = enable ? true : false;
|
||||
}
|
||||
|
||||
bool irq_enabled_after = cfg->irq_rise || cfg->irq_fall;
|
||||
|
||||
if (irq_enabled_before != irq_enabled_after)
|
||||
{
|
||||
if (irq_enabled_after)
|
||||
{
|
||||
gpio_irq_enable(obj);
|
||||
}
|
||||
else
|
||||
{
|
||||
gpio_irq_disable(obj);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gpio_irq_enable(gpio_irq_t *obj)
|
||||
{
|
||||
m_gpio_irq_enabled |= ((gpio_mask_t)1 << obj->ch);
|
||||
if (m_gpio_cfg[obj->ch].irq_rise || m_gpio_cfg[obj->ch].irq_fall)
|
||||
{
|
||||
nrf_drv_gpiote_in_event_enable(obj->ch, true);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void gpio_irq_disable(gpio_irq_t *obj)
|
||||
{
|
||||
m_gpio_irq_enabled &= ~((gpio_mask_t)1 << obj->ch);
|
||||
nrf_drv_gpiote_in_event_disable(obj->ch);
|
||||
}
|
|
@ -0,0 +1,54 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#ifndef MBED_GPIO_OBJECT_H
|
||||
#define MBED_GPIO_OBJECT_H
|
||||
|
||||
#include "mbed_assert.h"
|
||||
|
||||
#include "nrf_gpio.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
typedef struct
|
||||
{
|
||||
PinName pin;
|
||||
} gpio_t;
|
||||
|
||||
static inline void gpio_write(gpio_t *obj, int value)
|
||||
{
|
||||
MBED_ASSERT(obj->pin != (PinName)NC);
|
||||
if (value)
|
||||
{
|
||||
nrf_gpio_pin_set(obj->pin);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_gpio_pin_clear(obj->pin);
|
||||
}
|
||||
}
|
||||
|
||||
static inline int gpio_is_connected(const gpio_t *obj)
|
||||
{
|
||||
return obj->pin != (PinName)NC;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,784 @@
|
|||
/*
|
||||
* Copyright (c) 2017 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
#include "i2c_api.h"
|
||||
|
||||
#if DEVICE_I2C
|
||||
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_error.h"
|
||||
#include "nrf_twi.h"
|
||||
#include "nrf_drv_common.h"
|
||||
#include "sdk_config.h"
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_gpio.h"
|
||||
#include "nrf_delay.h"
|
||||
|
||||
// An arbitrary value used as the counter in loops waiting for given event
|
||||
// (e.g. STOPPED), needed to avoid infinite loops (and not involve any timers
|
||||
// or tickers).
|
||||
#define TIMEOUT_VALUE 1000
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
#define TWI_IDX(obj) ((obj)->i2c.twi_idx)
|
||||
#else
|
||||
#define TWI_IDX(obj) ((obj)->twi_idx)
|
||||
#endif
|
||||
#define TWI_INFO(obj) (&m_twi_info[TWI_IDX(obj)])
|
||||
|
||||
#define TWI0_INSTANCE_INDEX 0
|
||||
#define TWI1_INSTANCE_INDEX TWI0_INSTANCE_INDEX+TWI0_ENABLED
|
||||
|
||||
typedef struct {
|
||||
bool initialized;
|
||||
uint32_t pselsda;
|
||||
uint32_t pselscl;
|
||||
nrf_twi_frequency_t frequency;
|
||||
bool start_twi;
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
volatile bool active;
|
||||
uint8_t const *tx;
|
||||
size_t tx_length;
|
||||
uint8_t *rx;
|
||||
size_t rx_length;
|
||||
bool stop;
|
||||
|
||||
volatile uint32_t events;
|
||||
void (*handler)(void);
|
||||
uint32_t evt_mask;
|
||||
#endif // DEVICE_I2C_ASYNCH
|
||||
} twi_info_t;
|
||||
static twi_info_t m_twi_info[TWI_COUNT];
|
||||
|
||||
static NRF_TWI_Type * const m_twi_instances[TWI_COUNT] = {
|
||||
#if TWI0_ENABLED
|
||||
NRF_TWI0,
|
||||
#endif
|
||||
#if TWI1_ENABLED
|
||||
NRF_TWI1,
|
||||
#endif
|
||||
};
|
||||
|
||||
void SPI0_TWI0_IRQHandler(void);
|
||||
void SPI1_TWI1_IRQHandler(void);
|
||||
|
||||
static const peripheral_handler_desc_t twi_handlers[TWI_COUNT] =
|
||||
{
|
||||
#if TWI0_ENABLED
|
||||
{
|
||||
SPI0_TWI0_IRQn,
|
||||
(uint32_t) SPI0_TWI0_IRQHandler
|
||||
},
|
||||
#endif
|
||||
#if TWI1_ENABLED
|
||||
{
|
||||
SPI1_TWI1_IRQn,
|
||||
(uint32_t) SPI1_TWI1_IRQHandler
|
||||
}
|
||||
#endif
|
||||
};
|
||||
#ifdef NRF51
|
||||
#define TWI_IRQ_PRIORITY APP_IRQ_PRIORITY_LOW
|
||||
#elif defined(NRF52) || defined(NRF52840_XXAA)
|
||||
#define TWI_IRQ_PRIORITY APP_IRQ_PRIORITY_LOWEST
|
||||
#endif
|
||||
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
static void start_asynch_rx(twi_info_t *twi_info, NRF_TWI_Type *twi)
|
||||
{
|
||||
if (twi_info->rx_length == 1 && twi_info->stop)
|
||||
{
|
||||
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
|
||||
}
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTRX);
|
||||
}
|
||||
|
||||
static void twi_irq_handler(uint8_t instance_idx)
|
||||
{
|
||||
twi_info_t *twi_info = &m_twi_info[instance_idx];
|
||||
|
||||
NRF_TWI_Type *twi = m_twi_instances[instance_idx];
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_ERROR))
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
|
||||
// In case of an error, force STOP.
|
||||
// The current transfer may be suspended (if it is RX), so it must be
|
||||
// resumed before the STOP task is triggered.
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
||||
|
||||
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(twi);
|
||||
twi_info->events |= I2C_EVENT_ERROR;
|
||||
if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
|
||||
{
|
||||
twi_info->events |= I2C_EVENT_ERROR_NO_SLAVE;
|
||||
}
|
||||
if (errorsrc & NRF_TWI_ERROR_DATA_NACK)
|
||||
{
|
||||
twi_info->events |= I2C_EVENT_TRANSFER_EARLY_NACK;
|
||||
}
|
||||
}
|
||||
|
||||
bool finished = false;
|
||||
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_TXDSENT))
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||
|
||||
MBED_ASSERT(twi_info->tx_length > 0);
|
||||
--(twi_info->tx_length);
|
||||
// Send next byte if there is still something to be sent.
|
||||
if (twi_info->tx_length > 0)
|
||||
{
|
||||
nrf_twi_txd_set(twi, *(twi_info->tx));
|
||||
++(twi_info->tx);
|
||||
// It TX is done, start RX if requested.
|
||||
}
|
||||
else if (twi_info->rx_length > 0)
|
||||
{
|
||||
start_asynch_rx(twi_info, twi);
|
||||
// If there is nothing more to do, finalize the transfer.
|
||||
}
|
||||
else
|
||||
{
|
||||
if (twi_info->stop)
|
||||
{
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_SUSPEND);
|
||||
finished = true;
|
||||
}
|
||||
twi_info->events |= I2C_EVENT_TRANSFER_COMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_RXDREADY))
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY);
|
||||
|
||||
MBED_ASSERT(twi_info->rx_length > 0);
|
||||
*(twi_info->rx) = nrf_twi_rxd_get(twi);
|
||||
++(twi_info->rx);
|
||||
--(twi_info->rx_length);
|
||||
|
||||
if (twi_info->rx_length > 0)
|
||||
{
|
||||
// If more bytes should be received, resume the transfer
|
||||
// (in case the stop condition should be generated after the next
|
||||
// byte, change the shortcuts configuration first).
|
||||
if (twi_info->rx_length == 1 && twi_info->stop)
|
||||
{
|
||||
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
||||
}
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
}
|
||||
else
|
||||
{
|
||||
// If all requested bytes were received, finalize the transfer.
|
||||
finished = true;
|
||||
twi_info->events |= I2C_EVENT_TRANSFER_COMPLETE;
|
||||
}
|
||||
}
|
||||
|
||||
if (finished ||
|
||||
nrf_twi_event_check(twi, NRF_TWI_EVENT_STOPPED) ||
|
||||
(nrf_twi_int_enable_check(twi, NRF_TWI_INT_SUSPENDED_MASK) &&
|
||||
nrf_twi_event_check(twi, NRF_TWI_EVENT_SUSPENDED)))
|
||||
{
|
||||
// There is no need to clear the STOPPED and SUSPENDED events here,
|
||||
// they will no longer generate the interrupt - see below.
|
||||
|
||||
nrf_twi_shorts_set(twi, 0);
|
||||
// Disable all interrupt sources.
|
||||
nrf_twi_int_disable(twi, UINT32_MAX);
|
||||
twi_info->active = false;
|
||||
|
||||
if (twi_info->handler)
|
||||
{
|
||||
twi_info->handler();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#if TWI0_ENABLED
|
||||
static void irq_handler_twi0(void)
|
||||
{
|
||||
twi_irq_handler(TWI0_INSTANCE_INDEX);
|
||||
}
|
||||
#endif
|
||||
#if TWI1_ENABLED
|
||||
static void irq_handler_twi1(void)
|
||||
{
|
||||
twi_irq_handler(TWI1_INSTANCE_INDEX);
|
||||
}
|
||||
#endif
|
||||
static nrf_drv_irq_handler_t const m_twi_irq_handlers[TWI_COUNT] =
|
||||
{
|
||||
#if TWI0_ENABLED
|
||||
irq_handler_twi0,
|
||||
#endif
|
||||
#if TWI1_ENABLED
|
||||
irq_handler_twi1,
|
||||
#endif
|
||||
};
|
||||
#endif // DEVICE_I2C_ASYNCH
|
||||
|
||||
|
||||
static void configure_twi_pin(uint32_t pin, nrf_gpio_pin_dir_t dir)
|
||||
{
|
||||
nrf_gpio_cfg(pin,
|
||||
dir,
|
||||
NRF_GPIO_PIN_INPUT_CONNECT,
|
||||
NRF_GPIO_PIN_PULLUP,
|
||||
NRF_GPIO_PIN_S0D1,
|
||||
NRF_GPIO_PIN_NOSENSE);
|
||||
}
|
||||
|
||||
static void twi_clear_bus(twi_info_t *twi_info)
|
||||
{
|
||||
// Try to set SDA high, and check if no slave tries to drive it low.
|
||||
nrf_gpio_pin_set(twi_info->pselsda);
|
||||
configure_twi_pin(twi_info->pselsda, NRF_GPIO_PIN_DIR_OUTPUT);
|
||||
// In case SDA is low, make up to 9 cycles on SCL line to help the slave
|
||||
// that pulls SDA low release it.
|
||||
if (!nrf_gpio_pin_read(twi_info->pselsda))
|
||||
{
|
||||
nrf_gpio_pin_set(twi_info->pselscl);
|
||||
configure_twi_pin(twi_info->pselscl, NRF_GPIO_PIN_DIR_OUTPUT);
|
||||
nrf_delay_us(4);
|
||||
|
||||
for (int i = 0; i < 9; i++)
|
||||
{
|
||||
if (nrf_gpio_pin_read(twi_info->pselsda))
|
||||
{
|
||||
break;
|
||||
}
|
||||
nrf_gpio_pin_clear(twi_info->pselscl);
|
||||
nrf_delay_us(4);
|
||||
nrf_gpio_pin_set(twi_info->pselscl);
|
||||
nrf_delay_us(4);
|
||||
}
|
||||
|
||||
// Finally, generate STOP condition to put the bus into initial state.
|
||||
nrf_gpio_pin_clear(twi_info->pselsda);
|
||||
nrf_delay_us(4);
|
||||
nrf_gpio_pin_set(twi_info->pselsda);
|
||||
}
|
||||
}
|
||||
|
||||
void i2c_init(i2c_t *obj, PinName sda, PinName scl)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < TWI_COUNT; ++i)
|
||||
{
|
||||
if (m_twi_info[i].initialized &&
|
||||
m_twi_info[i].pselsda == (uint32_t)sda &&
|
||||
m_twi_info[i].pselscl == (uint32_t)scl)
|
||||
{
|
||||
TWI_IDX(obj) = i;
|
||||
TWI_INFO(obj)->frequency = NRF_TWI_FREQ_100K;
|
||||
i2c_reset(obj);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < TWI_COUNT; ++i)
|
||||
{
|
||||
if (!m_twi_info[i].initialized)
|
||||
{
|
||||
TWI_IDX(obj) = i;
|
||||
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
twi_info->initialized = true;
|
||||
twi_info->pselsda = (uint32_t)sda;
|
||||
twi_info->pselscl = (uint32_t)scl;
|
||||
twi_info->frequency = NRF_TWI_FREQ_100K;
|
||||
twi_info->start_twi = false;
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
twi_info->active = false;
|
||||
#endif
|
||||
|
||||
twi_clear_bus(twi_info);
|
||||
|
||||
configure_twi_pin(twi_info->pselsda, NRF_GPIO_PIN_DIR_INPUT);
|
||||
configure_twi_pin(twi_info->pselscl, NRF_GPIO_PIN_DIR_INPUT);
|
||||
|
||||
i2c_reset(obj);
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
nrf_drv_common_per_res_acquire(m_twi_instances[i],
|
||||
m_twi_irq_handlers[i]);
|
||||
NVIC_SetVector(twi_handlers[i].IRQn, twi_handlers[i].vector);
|
||||
nrf_drv_common_irq_enable(twi_handlers[i].IRQn, TWI_IRQ_PRIORITY);
|
||||
#endif
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
error("No available I2C peripheral\r\n");
|
||||
}
|
||||
|
||||
void i2c_reset(i2c_t *obj)
|
||||
{
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
|
||||
nrf_twi_disable(twi);
|
||||
nrf_twi_pins_set(twi, twi_info->pselscl, twi_info->pselsda);
|
||||
nrf_twi_frequency_set(twi, twi_info->frequency);
|
||||
nrf_twi_enable(twi);
|
||||
}
|
||||
|
||||
int i2c_start(i2c_t *obj)
|
||||
{
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
if (twi_info->active)
|
||||
{
|
||||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
#endif
|
||||
twi_info->start_twi = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int i2c_stop(i2c_t *obj)
|
||||
{
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
|
||||
// The current transfer may be suspended (if it is RX), so it must be
|
||||
// resumed before the STOP task is triggered.
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
|
||||
do
|
||||
{
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_STOPPED))
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
while (--remaining_time);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
void i2c_frequency(i2c_t *obj, int hz)
|
||||
{
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
|
||||
if (hz < 250000)
|
||||
{
|
||||
twi_info->frequency = NRF_TWI_FREQ_100K;
|
||||
}
|
||||
else if (hz < 400000)
|
||||
{
|
||||
twi_info->frequency = NRF_TWI_FREQ_250K;
|
||||
}
|
||||
else
|
||||
{
|
||||
twi_info->frequency = NRF_TWI_FREQ_400K;
|
||||
}
|
||||
nrf_twi_frequency_set(twi, twi_info->frequency);
|
||||
}
|
||||
|
||||
static uint8_t twi_address(int i2c_address)
|
||||
{
|
||||
// The TWI peripheral requires 7-bit slave address (without R/W bit).
|
||||
return (i2c_address >> 1);
|
||||
}
|
||||
|
||||
static void start_twi_read(NRF_TWI_Type *twi, int address)
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_STOPPED);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
(void)nrf_twi_errorsrc_get_and_clear(twi);
|
||||
|
||||
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_SUSPEND_MASK);
|
||||
|
||||
nrf_twi_address_set(twi, twi_address(address));
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTRX);
|
||||
}
|
||||
|
||||
int i2c_read(i2c_t *obj, int address, char *data, int length, int stop)
|
||||
{
|
||||
// Zero-length RX transfers are not supported. Such transfers cannot
|
||||
// be easily achieved with TWI peripheral (some dirty tricks would be
|
||||
// required for this), and they are actually useless (TX can be used
|
||||
// to check if the address is acknowledged by a slave).
|
||||
MBED_ASSERT(length > 0);
|
||||
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
if (twi_info->active)
|
||||
{
|
||||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
#endif
|
||||
twi_info->start_twi = false;
|
||||
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
start_twi_read(twi, address);
|
||||
|
||||
int result = length;
|
||||
|
||||
while (length > 0)
|
||||
{
|
||||
int byte_read_result = i2c_byte_read(obj, (stop && length == 1));
|
||||
if (byte_read_result < 0)
|
||||
{
|
||||
// When an error occurs, return the number of bytes that have been
|
||||
// received successfully.
|
||||
result -= length;
|
||||
// Force STOP condition.
|
||||
stop = 1;
|
||||
break;
|
||||
}
|
||||
*data++ = (uint8_t)byte_read_result;
|
||||
--length;
|
||||
}
|
||||
|
||||
if (stop)
|
||||
{
|
||||
(void)i2c_stop(obj);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static uint8_t twi_byte_write(NRF_TWI_Type *twi, uint8_t data)
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
|
||||
nrf_twi_txd_set(twi, data);
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
|
||||
do
|
||||
{
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_TXDSENT))
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||
return 1; // ACK received
|
||||
}
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_ERROR))
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
return 0; // some error occurred
|
||||
}
|
||||
}
|
||||
while (--remaining_time);
|
||||
|
||||
return 2; // timeout;
|
||||
}
|
||||
|
||||
static void start_twi_write(NRF_TWI_Type *twi, int address)
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_STOPPED);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
(void)nrf_twi_errorsrc_get_and_clear(twi);
|
||||
|
||||
nrf_twi_shorts_set(twi, 0);
|
||||
|
||||
nrf_twi_address_set(twi, twi_address(address));
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTTX);
|
||||
}
|
||||
|
||||
int i2c_write(i2c_t *obj, int address, const char *data, int length, int stop)
|
||||
{
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
if (twi_info->active)
|
||||
{
|
||||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
#endif
|
||||
twi_info->start_twi = false;
|
||||
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
start_twi_write(twi, address);
|
||||
|
||||
// Special case - transaction with no data.
|
||||
// It can be used to check if a slave acknowledges the address.
|
||||
if (length == 0)
|
||||
{
|
||||
nrf_twi_event_t event;
|
||||
if (stop)
|
||||
{
|
||||
event = NRF_TWI_EVENT_STOPPED;
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
event = NRF_TWI_EVENT_SUSPENDED;
|
||||
nrf_twi_event_clear(twi, event);
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_SUSPEND);
|
||||
}
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
|
||||
do
|
||||
{
|
||||
if (nrf_twi_event_check(twi, event))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
while (--remaining_time);
|
||||
|
||||
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(twi);
|
||||
if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
|
||||
{
|
||||
if (!stop)
|
||||
{
|
||||
i2c_stop(obj);
|
||||
}
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
|
||||
return (remaining_time ? 0 : I2C_ERROR_BUS_BUSY);
|
||||
}
|
||||
|
||||
int result = length;
|
||||
|
||||
do
|
||||
{
|
||||
uint8_t byte_write_result = twi_byte_write(twi, (uint8_t)*data++);
|
||||
if (byte_write_result != 1)
|
||||
{
|
||||
if (byte_write_result == 0)
|
||||
{
|
||||
// Check what kind of error has been signaled by TWI.
|
||||
uint32_t errorsrc = nrf_twi_errorsrc_get_and_clear(twi);
|
||||
if (errorsrc & NRF_TWI_ERROR_ADDRESS_NACK)
|
||||
{
|
||||
result = I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Some other error - return the number of bytes that
|
||||
// have been sent successfully.
|
||||
result -= length;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
result = I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
// Force STOP condition.
|
||||
stop = 1;
|
||||
break;
|
||||
}
|
||||
--length;
|
||||
}
|
||||
while (length > 0);
|
||||
|
||||
if (stop)
|
||||
{
|
||||
(void)i2c_stop(obj);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
int i2c_byte_read(i2c_t *obj, int last)
|
||||
{
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
|
||||
if (last)
|
||||
{
|
||||
nrf_twi_shorts_set(twi, NRF_TWI_SHORT_BB_STOP_MASK);
|
||||
}
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
|
||||
uint32_t remaining_time = TIMEOUT_VALUE;
|
||||
|
||||
do
|
||||
{
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_RXDREADY))
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY);
|
||||
return nrf_twi_rxd_get(twi);
|
||||
}
|
||||
if (nrf_twi_event_check(twi, NRF_TWI_EVENT_ERROR))
|
||||
{
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
return I2C_ERROR_NO_SLAVE;
|
||||
}
|
||||
}
|
||||
while (--remaining_time);
|
||||
|
||||
return I2C_ERROR_BUS_BUSY;
|
||||
}
|
||||
|
||||
int i2c_byte_write(i2c_t *obj, int data)
|
||||
{
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
if (twi_info->start_twi)
|
||||
{
|
||||
twi_info->start_twi = false;
|
||||
|
||||
if (data & 1)
|
||||
{
|
||||
start_twi_read(twi, data);
|
||||
}
|
||||
else
|
||||
{
|
||||
start_twi_write(twi, data);
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
// 0 - TWI signaled error (NAK is the only possibility here)
|
||||
// 1 - ACK received
|
||||
// 2 - timeout (clock stretched for too long?)
|
||||
return twi_byte_write(twi, (uint8_t)data);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#if DEVICE_I2C_ASYNCH
|
||||
void i2c_transfer_asynch(i2c_t *obj, const void *tx, size_t tx_length,
|
||||
void *rx, size_t rx_length, uint32_t address,
|
||||
uint32_t stop, uint32_t handler,
|
||||
uint32_t event, DMAUsage hint)
|
||||
{
|
||||
(void)hint;
|
||||
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
if (twi_info->active)
|
||||
{
|
||||
return;
|
||||
}
|
||||
twi_info->active = true;
|
||||
twi_info->events = 0;
|
||||
twi_info->handler = (void (*)(void))handler;
|
||||
twi_info->evt_mask = event;
|
||||
twi_info->tx_length = tx_length;
|
||||
twi_info->tx = tx;
|
||||
twi_info->rx_length = rx_length;
|
||||
twi_info->rx = rx;
|
||||
twi_info->stop = stop;
|
||||
|
||||
NRF_TWI_Type *twi = m_twi_instances[TWI_IDX(obj)];
|
||||
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_TXDSENT);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_RXDREADY);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_STOPPED);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_SUSPENDED);
|
||||
nrf_twi_event_clear(twi, NRF_TWI_EVENT_ERROR);
|
||||
(void)nrf_twi_errorsrc_get_and_clear(twi);
|
||||
|
||||
nrf_twi_address_set(twi, twi_address(address));
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_RESUME);
|
||||
// TX only, or TX + RX (after a repeated start).
|
||||
if (tx_length > 0)
|
||||
{
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTTX);
|
||||
nrf_twi_txd_set(twi, *(twi_info->tx));
|
||||
++(twi_info->tx);
|
||||
// RX only.
|
||||
}
|
||||
else if (rx_length > 0)
|
||||
{
|
||||
start_asynch_rx(twi_info, twi);
|
||||
// Both 'tx_length' and 'rx_length' are 0 - this case may be used
|
||||
// to test if the slave is presentand ready for transfer (by just
|
||||
// sending the address and checking if it is acknowledged).
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STARTTX);
|
||||
if (stop)
|
||||
{
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_STOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
nrf_twi_task_trigger(twi, NRF_TWI_TASK_SUSPEND);
|
||||
nrf_twi_int_enable(twi, NRF_TWI_INT_SUSPENDED_MASK);
|
||||
}
|
||||
twi_info->events |= I2C_EVENT_TRANSFER_COMPLETE;
|
||||
}
|
||||
|
||||
nrf_twi_int_enable(twi, NRF_TWI_INT_TXDSENT_MASK |
|
||||
NRF_TWI_INT_RXDREADY_MASK |
|
||||
NRF_TWI_INT_STOPPED_MASK |
|
||||
NRF_TWI_INT_ERROR_MASK);
|
||||
}
|
||||
|
||||
uint32_t i2c_irq_handler_asynch(i2c_t *obj)
|
||||
{
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
return (twi_info->events & twi_info->evt_mask);
|
||||
}
|
||||
|
||||
uint8_t i2c_active(i2c_t *obj)
|
||||
{
|
||||
twi_info_t *twi_info = TWI_INFO(obj);
|
||||
return twi_info->active;
|
||||
}
|
||||
|
||||
void i2c_abort_asynch(i2c_t *obj)
|
||||
{
|
||||
i2c_reset(obj);
|
||||
}
|
||||
#endif // DEVICE_I2C_ASYNCH
|
||||
|
||||
#endif // DEVICE_I2C
|
|
@ -0,0 +1,55 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/**
|
||||
* @file irq_handlers_hw.h
|
||||
* @brief Heleper file for wiring irq handlers to theirs vectors.
|
||||
*/
|
||||
|
||||
#ifndef IRQ_HANDLERS_HW_H__
|
||||
#define IRQ_HANDLERS_HW_H__
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
IRQn_Type IRQn;
|
||||
uint32_t vector;
|
||||
} peripheral_handler_desc_t;
|
||||
|
||||
#endif // IRQ_HANDLERS_HW_H__
|
||||
|
|
@ -0,0 +1,48 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2015 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "lp_ticker_api.h"
|
||||
|
||||
#if DEVICE_LOWPOWERTIMER
|
||||
|
||||
#include "common_rtc.h"
|
||||
|
||||
void lp_ticker_init(void)
|
||||
{
|
||||
common_rtc_init();
|
||||
}
|
||||
|
||||
uint32_t lp_ticker_read()
|
||||
{
|
||||
return (uint32_t)common_rtc_64bit_us_get();
|
||||
}
|
||||
|
||||
void lp_ticker_set_interrupt(timestamp_t timestamp)
|
||||
{
|
||||
common_rtc_set_interrupt(timestamp,
|
||||
LP_TICKER_CC_CHANNEL, LP_TICKER_INT_MASK);
|
||||
}
|
||||
|
||||
void lp_ticker_disable_interrupt(void)
|
||||
{
|
||||
nrf_rtc_event_disable(COMMON_RTC_INSTANCE, LP_TICKER_INT_MASK);
|
||||
}
|
||||
|
||||
void lp_ticker_clear_interrupt(void)
|
||||
{
|
||||
nrf_rtc_event_clear(COMMON_RTC_INSTANCE, LP_TICKER_EVENT);
|
||||
}
|
||||
|
||||
#endif // DEVICE_LOWPOWERTIMER
|
|
@ -0,0 +1,59 @@
|
|||
/*
|
||||
* Copyright (c) 2015-2016, ARM Limited, All Rights Reserved
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License"); you may
|
||||
* not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
|
||||
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
#include <stdint.h> // uint32_t, UINT32_MAX
|
||||
#include <assert.h> // uint32_t, UINT32_MAX
|
||||
#include "cmsis.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "nrf_sdm.h"
|
||||
#include "nrf_nvic.h"
|
||||
|
||||
static uint8_t _sd_state = 0;
|
||||
static volatile uint32_t _entry_count = 0;
|
||||
|
||||
void core_util_critical_section_enter()
|
||||
{
|
||||
// if a critical section has already been entered, just update the counter
|
||||
if (_entry_count)
|
||||
{
|
||||
++_entry_count;
|
||||
return;
|
||||
}
|
||||
|
||||
// in this path, a critical section has never been entered
|
||||
// routine of SD V11 work even if the softdevice is not active
|
||||
sd_nvic_critical_region_enter(&_sd_state);
|
||||
|
||||
assert(_entry_count == 0); // entry count should always be equal to 0 at this point
|
||||
++_entry_count;
|
||||
}
|
||||
|
||||
void core_util_critical_section_exit()
|
||||
{
|
||||
assert(_entry_count > 0);
|
||||
--_entry_count;
|
||||
|
||||
// If their is other segments which have entered the critical section, just leave
|
||||
if (_entry_count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// This is the last segment of the critical section, state should be restored as before entering
|
||||
// the critical section
|
||||
sd_nvic_critical_region_exit(_sd_state);
|
||||
}
|
|
@ -0,0 +1,66 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef __NRF5X_LF_CLK_HELPER_H_
|
||||
|
||||
#ifndef MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC
|
||||
#define MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC (NRF_LF_SRC_XTAL)
|
||||
#warning No configuration for LF clock source. Xtal source will be used as a default configuration.
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
#define NRF_LF_SRC_XTAL 2
|
||||
#define NRF_LF_SRC_SYNTH 3
|
||||
#define NRF_LF_SRC_RC 4
|
||||
|
||||
#if MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC == NRF_LF_SRC_SYNTH
|
||||
#define CLOCK_LFCLKSRC_SRC_TO_USE (CLOCK_LFCLKSRC_SRC_Synth)
|
||||
#elif MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC == NRF_LF_SRC_XTAL
|
||||
#define CLOCK_LFCLKSRC_SRC_TO_USE (CLOCK_LFCLKSRC_SRC_Xtal)
|
||||
#elif MBED_CONF_NORDIC_NRF_LF_CLOCK_SRC == NRF_LF_SRC_RC
|
||||
#define CLOCK_LFCLKSRC_SRC_TO_USE (CLOCK_LFCLKSRC_SRC_RC)
|
||||
#else
|
||||
#error Bad LFCLK configuration. Declare proper source through mbed configuration.
|
||||
#endif
|
||||
|
||||
#undef NRF_LF_SRC_XTAL
|
||||
#undef NRF_LF_SRC_SYNTH
|
||||
#undef NRF_LF_SRC_RC
|
||||
|
||||
#endif
|
|
@ -0,0 +1,98 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef MBED_OBJECTS_H
|
||||
#define MBED_OBJECTS_H
|
||||
|
||||
#include "cmsis.h"
|
||||
#include "PortNames.h"
|
||||
#include "PeripheralNames.h"
|
||||
#include "PinNames.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
struct serial_s
|
||||
{
|
||||
uint32_t placeholder; // struct is unused by nRF5x API implementation
|
||||
}; // but it must be not empty (required by strict compiler - IAR)
|
||||
|
||||
struct spi_s
|
||||
{
|
||||
uint8_t spi_idx;
|
||||
};
|
||||
|
||||
struct port_s
|
||||
{
|
||||
PortName port;
|
||||
uint32_t mask;
|
||||
};
|
||||
|
||||
struct pwmout_s
|
||||
{
|
||||
PWMName pwm_name;
|
||||
PinName pin;
|
||||
uint8_t pwm_channel;
|
||||
void * pwm_struct;
|
||||
};
|
||||
|
||||
struct i2c_s
|
||||
{
|
||||
uint8_t twi_idx;
|
||||
};
|
||||
|
||||
struct analogin_s
|
||||
{
|
||||
ADCName adc;
|
||||
uint8_t adc_pin;
|
||||
};
|
||||
|
||||
struct gpio_irq_s
|
||||
{
|
||||
uint32_t ch;
|
||||
};
|
||||
|
||||
|
||||
#include "gpio_object.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
|
@ -0,0 +1,37 @@
|
|||
/* mbed Microcontroller Library
|
||||
* Copyright (c) 2006-2013 ARM Limited
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_error.h"
|
||||
#include "pinmap.h"
|
||||
|
||||
void pin_function(PinName pin, int function)
|
||||
{
|
||||
/* Avoid compiler warnings */
|
||||
(void) pin;
|
||||
(void) function;
|
||||
}
|
||||
|
||||
void pin_mode(PinName pin, PinMode mode)
|
||||
{
|
||||
MBED_ASSERT(pin != (PinName)NC);
|
||||
|
||||
uint32_t pin_number = (uint32_t)pin;
|
||||
|
||||
NRF_GPIO_Type * reg = nrf_gpio_pin_port_decode(&pin_number);
|
||||
|
||||
reg->PIN_CNF[pin_number] &= ~GPIO_PIN_CNF_PULL_Msk;
|
||||
reg->PIN_CNF[pin_number] |= (mode << GPIO_PIN_CNF_PULL_Pos);
|
||||
}
|
|
@ -0,0 +1,133 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "port_api.h"
|
||||
#include "pinmap.h"
|
||||
|
||||
static NRF_GPIO_Type * const m_ports[] = GPIO_REG_LIST;
|
||||
|
||||
#if defined(TARGET_MCU_NRF51822)
|
||||
static const uint32_t m_gpio_pin_count[] = {31};
|
||||
#elif defined(TARGET_MCU_NRF52832)
|
||||
static const uint32_t m_gpio_pin_count[] = {32};
|
||||
#elif defined(TARGET_MCU_NRF52840)
|
||||
static const uint32_t m_gpio_pin_count[] = {32, 16};
|
||||
#else
|
||||
#error not recognized gpio count for mcu
|
||||
#endif
|
||||
|
||||
#define GPIO_PORT_COUNT (sizeof(m_gpio_pin_count)/sizeof(uint32_t))
|
||||
|
||||
|
||||
PinName port_pin(PortName port, int pin_n)
|
||||
{
|
||||
return (PinName)NRF_GPIO_PIN_MAP(port, pin_n);
|
||||
}
|
||||
|
||||
void port_init(port_t *obj, PortName port, int mask, PinDirection dir)
|
||||
{
|
||||
MBED_ASSERT((uint32_t)port < GPIO_PORT_COUNT);
|
||||
|
||||
obj->port = port;
|
||||
obj->mask = mask;
|
||||
|
||||
port_dir(obj, dir);
|
||||
}
|
||||
|
||||
void port_mode(port_t *obj, PinMode mode)
|
||||
{
|
||||
uint32_t i;
|
||||
// The mode is set per pin: reuse pinmap logic
|
||||
for (i = 0; i < m_gpio_pin_count[obj->port]; i++)
|
||||
{
|
||||
if (obj->mask & (1 << i))
|
||||
{
|
||||
pin_mode(port_pin(obj->port, i), mode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void port_dir(port_t *obj, PinDirection dir)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
volatile uint32_t *reg_cnf = (volatile uint32_t*) m_ports[obj->port]->PIN_CNF;
|
||||
|
||||
switch (dir)
|
||||
{
|
||||
case PIN_INPUT:
|
||||
|
||||
for (i = 0; i < m_gpio_pin_count[obj->port]; i++)
|
||||
{
|
||||
if (obj->mask & (1 << i))
|
||||
{
|
||||
reg_cnf[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
|
||||
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
|
||||
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
|
||||
| (GPIO_PIN_CNF_DIR_Input << GPIO_PIN_CNF_DIR_Pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case PIN_OUTPUT:
|
||||
|
||||
for (i = 0; i < m_gpio_pin_count[obj->port]; i++)
|
||||
{
|
||||
if (obj->mask & (1 << i))
|
||||
{
|
||||
reg_cnf[i] = (GPIO_PIN_CNF_SENSE_Disabled << GPIO_PIN_CNF_SENSE_Pos)
|
||||
| (GPIO_PIN_CNF_DRIVE_S0S1 << GPIO_PIN_CNF_DRIVE_Pos)
|
||||
| (GPIO_PIN_CNF_PULL_Disabled << GPIO_PIN_CNF_PULL_Pos)
|
||||
| (GPIO_PIN_CNF_INPUT_Connect << GPIO_PIN_CNF_INPUT_Pos)
|
||||
| (GPIO_PIN_CNF_DIR_Output << GPIO_PIN_CNF_DIR_Pos);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void port_write(port_t *obj, int value)
|
||||
{
|
||||
m_ports[obj->port]->OUTSET = value & obj->mask;
|
||||
m_ports[obj->port]->OUTCLR = (~value) & obj->mask;
|
||||
}
|
||||
|
||||
int port_read(port_t *obj)
|
||||
{
|
||||
return ((m_ports[obj->port]->IN) & obj->mask);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* Copyright (c) <YEAR> Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
|
@ -0,0 +1,48 @@
|
|||
import os
|
||||
import re
|
||||
|
||||
|
||||
|
||||
|
||||
def replace_header(in_path):
|
||||
with open("copyright_header.txt", "r") as fd:
|
||||
header = fd.read()
|
||||
|
||||
for root, dirs, files in os.walk(in_path):
|
||||
for fn in [os.path.join(root, x) for x in files]:
|
||||
with open(fn, "r+") as fd:
|
||||
#print fn
|
||||
s = fd.read()
|
||||
start = s.find("/*")
|
||||
end = s.find("*/")
|
||||
copyright_str = s[start:end+2]
|
||||
if ("copyright (c)" in copyright_str.lower()) and ("nordic semiconductor" in copyright_str.lower()):
|
||||
|
||||
|
||||
pat_reg = r"copyright \(c\)[\s]{1,5}([0-9]{4})"
|
||||
find_obj = re.search(pat_reg, copyright_str.lower())
|
||||
|
||||
if find_obj == None:
|
||||
header_year = re.sub(r'(<YEAR>)',"2000",header)
|
||||
print "default date>>" + fn
|
||||
else:
|
||||
header_year = re.sub(r'(<YEAR>)',find_obj.group(1),header)
|
||||
|
||||
s = s.replace(copyright_str, header_year)
|
||||
|
||||
#print(header_year)
|
||||
|
||||
fd.seek(0)
|
||||
fd.write(s)
|
||||
fd.truncate()
|
||||
|
||||
##print "+"*35
|
||||
print fn
|
||||
|
||||
|
||||
pathes = ["..\\sdk",
|
||||
"..\\TARGET_MCU_NRF52832\\sdk",
|
||||
"..\\TARGET_MCU_NRF52840\\sdk"]
|
||||
|
||||
for path in pathes:
|
||||
replace_header(path)
|
|
@ -0,0 +1,277 @@
|
|||
#!python3
|
||||
import os, shutil, json, pprint, sys, string, json, argparse
|
||||
from collections import OrderedDict
|
||||
from shutil import copyfile, copytree
|
||||
|
||||
def rename_sdk_old_dirs(path, dry_run = False):
|
||||
# I make assumption that all old sdk dirs have "sdk" names.
|
||||
sdk_dir_name = "sdk"
|
||||
path = "."
|
||||
|
||||
for root, dirs, files in os.walk(path):
|
||||
for name in dirs:
|
||||
if name == "sdk":
|
||||
full_path = root + "\\" + name
|
||||
new_full_path = root + "\\_old_" + name
|
||||
print("rename " + full_path + " ---> " + new_full_path)
|
||||
if not dry_run:
|
||||
os.rename(full_path, new_full_path)
|
||||
os.mkdir(full_path)
|
||||
|
||||
def rename_dirs(sdk_dirs_in_mbed, new_name, dry_run=False):
|
||||
|
||||
for dir_path in sdk_dirs_in_mbed:
|
||||
xdir_path = os.path.join('.',dir_path)
|
||||
new_dir_path = os.path.join(os.path.dirname(xdir_path), new_name)
|
||||
print("rename " + xdir_path + " ---> " + new_dir_path)
|
||||
if not dry_run:
|
||||
os.rename(xdir_path, new_dir_path)
|
||||
|
||||
def get_file_pathes_couples(path_sdk_componets, skip_dirs = [], skip_files = [], verbose = False):
|
||||
mbed_list = []
|
||||
cutted_roots = []
|
||||
cutted_files = []
|
||||
|
||||
path_sdk_componets = path_sdk_componets + '\\'
|
||||
|
||||
for root, dirs, files in os.walk(path_sdk_componets):
|
||||
procced = True
|
||||
cutted_root = root[len(path_sdk_componets):]
|
||||
|
||||
for skip_d in skip_dirs:
|
||||
if 0 == string.find(cutted_root, skip_d):
|
||||
cutted_roots.append(cutted_root)
|
||||
procced = False
|
||||
|
||||
if procced:
|
||||
for file_name in files:
|
||||
|
||||
procced = True
|
||||
for skip_f in skip_files:
|
||||
if (-1) != string.find(file_name, skip_f):
|
||||
cutted_files.append(file_name)
|
||||
procced = False
|
||||
|
||||
if procced:
|
||||
if file_name.endswith((".c", ".h")):
|
||||
#cutted_path = cutted_root + "\\" + file_name
|
||||
cutted_path = os.path.join(cutted_root, file_name)
|
||||
#full_path = root + "\\" + file_name
|
||||
full_path = os.path.join(root, file_name)
|
||||
item = {"full_path": full_path, "id": cutted_path, "cutted_root": cutted_root}
|
||||
#mbed_list.append([full_path, cutted_path])
|
||||
mbed_list.append(item)
|
||||
|
||||
if verbose:
|
||||
print("\r\nskipped directories: {0:#d}".format(len(cutted_roots)))
|
||||
|
||||
for xitem in cutted_roots:
|
||||
print(xitem)
|
||||
|
||||
print("\r\nskipped files: {0:#d}".format(len(cutted_files)))
|
||||
|
||||
for kitem in cutted_files:
|
||||
print(kitem)
|
||||
|
||||
return mbed_list
|
||||
|
||||
def apply_replacement_id(mbed_list, replacemet_couples):
|
||||
for item in mbed_list:
|
||||
splited = os.path.split(item["id"])
|
||||
result = string.find(splited[1], replacemet_couples["old"])
|
||||
if result != -1:
|
||||
new_tail = replacemet_couples["new"] + splited[1][len(replacemet_couples["old"]):]
|
||||
item["id"] = os.path.join(splited[0],new_tail)
|
||||
#print('bingo!')
|
||||
#print(item)
|
||||
|
||||
return mbed_list
|
||||
|
||||
|
||||
def get_copying_automatic_list(list_mbed, list_sdk, mbed_port_path = '', verbose = False):
|
||||
copy_list = [] #list of copy items
|
||||
orphan_list = []
|
||||
|
||||
licz = 0
|
||||
for pathes_mbed in list_mbed:
|
||||
empty = True
|
||||
for pathes_sdk in list_sdk:
|
||||
if pathes_mbed["id"] == pathes_sdk["id"]:
|
||||
dest_path = pathes_mbed["full_path"]
|
||||
|
||||
dest_path = dest_path[ (len(mbed_port_path)):]
|
||||
|
||||
item = {"id" : pathes_mbed["id"], "src_path": pathes_sdk["full_path"], "dest_path": dest_path, "old_path": pathes_mbed["full_path"]}
|
||||
copy_list.append(item)
|
||||
|
||||
empty = False;
|
||||
|
||||
|
||||
if empty:
|
||||
orphan_list.append(pathes_mbed["full_path"])
|
||||
|
||||
print("\r\nfitted files: {0:#d}".format(len(copy_list)))
|
||||
|
||||
if verbose:
|
||||
for item in copy_list:
|
||||
str_verbose = "{0} --> {1}"
|
||||
print(str_verbose.format(item["id"], item["dest_path"]))
|
||||
|
||||
|
||||
print("\r\norphaned files: {0:#d}".format(len(orphan_list)))
|
||||
|
||||
if verbose:
|
||||
for xitem in orphan_list:
|
||||
print(xitem)
|
||||
|
||||
return copy_list
|
||||
|
||||
def is_in_copying_list(copy_list, file_id):
|
||||
for pathes_copy in copy_list:
|
||||
if pathes_copy["id"] == file_id:
|
||||
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
|
||||
def upgrade_copying_list(copy_list, pathes_sdk, dest_mbed_dir_path, print_list):
|
||||
splited = os.path.split(pathes_sdk["id"])
|
||||
dest_path = os.path.join(dest_mbed_dir_path, splited[1])
|
||||
item = {"id" : pathes_sdk["id"], "src_path": pathes_sdk["full_path"], "dest_path": dest_path} #, "old_path": pathes_mbed["full_path"]}
|
||||
copy_list.append(item)
|
||||
print_list.append(item)
|
||||
|
||||
|
||||
|
||||
|
||||
def upgrade_copying_list_by_dirs(copy_list, list_sdk, force_copy_dirs_list, port_relative_dir = '',verbose = False):
|
||||
print_list = []
|
||||
|
||||
for pathes_sdk in list_sdk:
|
||||
if is_in_copying_list(copy_list, pathes_sdk["id"]):
|
||||
|
||||
make_hard_copy = False
|
||||
|
||||
for hard_copy_dir in force_copy_dirs_list:
|
||||
|
||||
if 0 == string.find(pathes_sdk["cutted_root"], hard_copy_dir["sdk_dir"]):
|
||||
|
||||
make_hard_copy = True
|
||||
|
||||
post_path = os.path.relpath(pathes_sdk["cutted_root"], hard_copy_dir["sdk_dir"])
|
||||
|
||||
if post_path == '.':
|
||||
corect_hard_copy_dir = hard_copy_dir["mbed_dir"]
|
||||
if post_path != '.': # destynation is a nested directory
|
||||
corect_hard_copy_dir = os.path.join(hard_copy_dir["mbed_dir"], post_path)
|
||||
|
||||
corect_hard_copy_dir = os.path.join(port_relative_dir, corect_hard_copy_dir)
|
||||
|
||||
upgrade_copying_list(copy_list, pathes_sdk, corect_hard_copy_dir, print_list)
|
||||
break
|
||||
|
||||
|
||||
print("\r\nforced copy of files by directories: {0:#d}".format(len(print_list)))
|
||||
|
||||
if verbose:
|
||||
for item in print_list:
|
||||
str_verbose = "{0} --> {1}"
|
||||
print(str_verbose.format(item["id"], item["dest_path"]))
|
||||
|
||||
def upgrade_copying_list_by_files(copy_list, list_sdk, force_copy_files_list, port_relative_dir ='',verbose = False):
|
||||
print_list = []
|
||||
|
||||
for pathes_sdk in list_sdk:
|
||||
if is_in_copying_list(copy_list, pathes_sdk["id"]):
|
||||
|
||||
make_hard_copy = False
|
||||
|
||||
for hard_copy_file in force_copy_files_list:
|
||||
if pathes_sdk["id"] == hard_copy_file["sdk_file"]:
|
||||
make_hard_copy = True
|
||||
|
||||
corect_hard_copy_dir = os.path.join(port_relative_dir, hard_copy_file["mbed_dir"])
|
||||
|
||||
upgrade_copying_list(copy_list, pathes_sdk, corect_hard_copy_dir, print_list)
|
||||
break
|
||||
|
||||
print("\r\nforced copy of files by files: {0:#d}".format(len(print_list)))
|
||||
|
||||
if verbose:
|
||||
for item in print_list:
|
||||
str_verbose = "{0} --> {1}"
|
||||
print(str_verbose.format(item["id"], item["dest_path"]))
|
||||
|
||||
def copy_one_file(src, dest, verbose=False,dry_run=False):
|
||||
dirs_to_created = os.path.dirname(dest)
|
||||
|
||||
if not os.path.exists(dirs_to_created):
|
||||
if not dry_run:
|
||||
os.makedirs(dirs_to_created)
|
||||
|
||||
if verbose:
|
||||
print('makerdirs: {0}'.format(dirs_to_created))
|
||||
|
||||
if not dry_run:
|
||||
shutil.copyfile(src, dest)
|
||||
|
||||
if verbose:
|
||||
print('copy: {0} --> {1}'.format(src, dest))
|
||||
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
argument_parser = argparse.ArgumentParser()
|
||||
argument_parser.add_argument('-r', '--run', help='run', action='store_true')
|
||||
argument_parser.add_argument('-v', '--verbose', help='Verbose mode', action='store_true')
|
||||
#argument_parser.add_argument('-r', '--rename_only', help='rename only', action='store_true')
|
||||
|
||||
parser_args = vars(argument_parser.parse_args())
|
||||
|
||||
verbose = False
|
||||
|
||||
if parser_args['verbose'] or not parser_args['run']:
|
||||
verbose = True
|
||||
|
||||
with open('update_desc.json') as data_file:
|
||||
update_desc = json.load(data_file)
|
||||
|
||||
|
||||
#if not parser_args ['rename_only']:
|
||||
ignore_file_list = update_desc['ignore_file_list']
|
||||
ignore_dirs_list = update_desc['ignore_dirs_list']
|
||||
id_replacements = update_desc['id_replacements']
|
||||
force_copy_files_list = update_desc['force_copy_files_list']
|
||||
force_copy_dirs_list = update_desc['force_copy_dirs_list']
|
||||
sdk_dirs_in_mbed = update_desc['sdk_dirs_in_mbed']
|
||||
sdk_component_path = update_desc['sdk_component_path']
|
||||
port_relative_dir = update_desc['port_relative_dir_in_mbed']
|
||||
|
||||
list_sdk = get_file_pathes_couples(sdk_component_path,
|
||||
ignore_dirs_list,
|
||||
ignore_file_list,
|
||||
verbose)
|
||||
list_mbed = []
|
||||
for directory in sdk_dirs_in_mbed:
|
||||
list_mbed.extend(get_file_pathes_couples(directory))
|
||||
|
||||
list_mbed = apply_replacement_id(list_mbed, id_replacements)
|
||||
|
||||
mbed_port_path = ''
|
||||
|
||||
copy_list = get_copying_automatic_list(list_mbed, list_sdk, mbed_port_path, verbose)
|
||||
|
||||
upgrade_copying_list_by_dirs(copy_list, list_sdk, force_copy_dirs_list, port_relative_dir, verbose)
|
||||
upgrade_copying_list_by_files(copy_list, list_sdk, force_copy_files_list, port_relative_dir, verbose)
|
||||
|
||||
rename_dirs(sdk_dirs_in_mbed, '_old_sdk', not parser_args['run'])
|
||||
|
||||
for copy_item in copy_list:
|
||||
src = os.path.join('.',copy_item["src_path"])
|
||||
dest = os.path.join('.',copy_item["dest_path"])
|
||||
|
||||
copy_one_file(src, dest, verbose, not parser_args['run'])
|
||||
|
||||
with open('sdk_update_result.json', 'w') as fp:
|
||||
json.dump(copy_list, fp)
|
|
@ -0,0 +1,122 @@
|
|||
{
|
||||
"id_replacements" : {"old": "nrf_ble", "new": "ble"},
|
||||
"ignore_dirs_list" : [ "ant",
|
||||
"nfc",
|
||||
"proprietary_rf",
|
||||
"serialization",
|
||||
"toolchain",
|
||||
"ble\\ble_services\\ble_ancs_c",
|
||||
"ble\\ble_services\\ble_ans_c",
|
||||
"ble\\ble_services\\ble_bas",
|
||||
"ble\\ble_services\\ble_bas_c",
|
||||
"ble\\ble_services\\ble_bps",
|
||||
"ble\\ble_services\\ble_cscs",
|
||||
"ble\\ble_services\\ble_cts_c",
|
||||
"ble\\ble_services\\ble_dis",
|
||||
"ble\\ble_services\\ble_escs",
|
||||
"ble\\ble_services\\ble_gls",
|
||||
"ble\\ble_services\\ble_hids",
|
||||
"ble\\ble_services\\ble_hrs",
|
||||
"ble\\ble_services\\ble_hrs_c",
|
||||
"ble\\ble_services\\ble_hts",
|
||||
"ble\\ble_services\\ble_ias",
|
||||
"ble\\ble_services\\ble_ias_c",
|
||||
"ble\\ble_services\\ble_lbs",
|
||||
"ble\\ble_services\\ble_lbs_c",
|
||||
"ble\\ble_services\\ble_lls",
|
||||
"ble\\ble_services\\ble_nus",
|
||||
"ble\\ble_services\\ble_nus_c",
|
||||
"ble\\ble_services\\ble_rscs",
|
||||
"ble\\ble_services\\ble_rscs_c",
|
||||
"ble\\ble_services\\ble_tps",
|
||||
"ble\\ble_services\\experimental_ble_lns",
|
||||
"ble\\ble_services\\experimental_nrf_ble_bms",
|
||||
"ble\\ble_services\\experimental_nrf_ble_cgms",
|
||||
"drivers_ext",
|
||||
"softdevice\\s212",
|
||||
"softdevice\\s332",
|
||||
"ble\\nrf_ble_qwr",
|
||||
"libraries\\button",
|
||||
"libraries\\crc32",
|
||||
"libraries\\crypto",
|
||||
"libraries\\csense",
|
||||
"libraries\\ecc",
|
||||
"libraries\\fifo",
|
||||
"libraries\\gpiote",
|
||||
"libraries\\hardfault",
|
||||
"libraries\\ic_info",
|
||||
"libraries\\led_softblink",
|
||||
"libraries\\low_power_pwm",
|
||||
"libraries\\mailbox",
|
||||
"libraries\\mem_manager",
|
||||
"libraries\\sensorsim",
|
||||
"libraries\\sha256",
|
||||
"libraries\\simple_timer",
|
||||
"libraries\\slip",
|
||||
"libraries\\timer",
|
||||
"libraries\\twi",
|
||||
"libraries\\uart",
|
||||
"drivers_nrf\\twi_master\\deprecated"
|
||||
],
|
||||
|
||||
"ignore_file_list": [
|
||||
"dox_config.h",
|
||||
"ble_error_log.c",
|
||||
"ble_conn_params.c",
|
||||
"app_error_weak_cmock.c",
|
||||
"hci_slip.c",
|
||||
"hci_slip.h",
|
||||
"hci_transport.c",
|
||||
"hci_transport.h",
|
||||
"spi_5W_master.c",
|
||||
"spi_5W_master.h",
|
||||
"app_scheduler_serconn.c"
|
||||
],
|
||||
|
||||
"force_copy_files_list" : [{"sdk_file": "sdk_validation.h", "mbed_dir": "sdk"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_comp.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_egu.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_i2s.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_lpcomp.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_peripherals.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_qdec.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_rng.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_twim.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_twis.h", "mbed_dir": "sdk\\drivers_nrf\\hal"},
|
||||
{"sdk_file": "drivers_nrf\\hal\\nrf_uarte.h", "mbed_dir": "sdk\\drivers_nrf\\hal"}
|
||||
],
|
||||
|
||||
"force_copy_dirs_list" : [{"sdk_dir": "device", "mbed_dir": "sdk\\device"},
|
||||
{"sdk_dir": "ble\\ble_dtm", "mbed_dir": "sdk\\ble\\ble_dtm"},
|
||||
{"sdk_dir": "drivers_nrf\\comp", "mbed_dir": "sdk\\drivers_nrf\\comp"},
|
||||
{"sdk_dir": "drivers_nrf\\i2s", "mbed_dir": "sdk\\drivers_nrf\\i2s"},
|
||||
{"sdk_dir": "drivers_nrf\\lpcomp", "mbed_dir": "sdk\\drivers_nrf\\lpcomp"},
|
||||
{"sdk_dir": "drivers_nrf\\nrf_soc_nosd", "mbed_dir": "sdk\\drivers_nrf\\nrf_soc_nosd"},
|
||||
{"sdk_dir": "drivers_nrf\\pdm", "mbed_dir": "sdk\\drivers_nrf\\pdm"},
|
||||
{"sdk_dir": "drivers_nrf\\qdec", "mbed_dir": "sdk\\drivers_nrf\\qdec"},
|
||||
{"sdk_dir": "drivers_nrf\\radio_config", "mbed_dir": "sdk\\drivers_nrf\\radio_config"},
|
||||
{"sdk_dir": "drivers_nrf\\rng", "mbed_dir": "sdk\\drivers_nrf\\rng"},
|
||||
{"sdk_dir": "drivers_nrf\\rtc", "mbed_dir": "sdk\\drivers_nrf\\rtc"},
|
||||
{"sdk_dir": "drivers_nrf\\sdio", "mbed_dir": "sdk\\drivers_nrf\\sdio"},
|
||||
{"sdk_dir": "drivers_nrf\\swi", "mbed_dir": "sdk\\drivers_nrf\\swi"},
|
||||
{"sdk_dir": "drivers_nrf\\twis_slave", "mbed_dir": "sdk\\drivers_nrf\\twis_slave"},
|
||||
{"sdk_dir": "drivers_nrf\\uart", "mbed_dir": "sdk\\drivers_nrf\\uart"},
|
||||
{"sdk_dir": "drivers_nrf\\wdt", "mbed_dir": "sdk\\drivers_nrf\\wdt"},
|
||||
{"sdk_dir": "libraries\\log", "mbed_dir": "sdk\\libraries\\log"},
|
||||
{"sdk_dir": "libraries\\bootloader", "mbed_dir": "sdk\\libraries\\bootloader"},
|
||||
{"sdk_dir": "libraries\\svc", "mbed_dir": "sdk\\libraries\\svc"},
|
||||
{"sdk_dir": "ble\\ble_services\\ble_dfu", "mbed_dir": "ble\\ble_services\\ble_dfu"},
|
||||
{"sdk_dir": "libraries\\bootloader", "mbed_dir": "libraries\\bootloader"},
|
||||
{"sdk_dir": "softdevice\\s140", "mbed_dir": "TARGET_MCU_NRF52840\\sdk\\softdevice\\s140"},
|
||||
{"sdk_dir": "softdevice\\s140\\nrf52", "mbed_dir": "TARGET_MCU_NRF52840\\sdk\\softdevice\\s140\\nrf52"}
|
||||
],
|
||||
|
||||
"sdk_dirs_in_mbed" : [
|
||||
"..\\sdk",
|
||||
"..\\TARGET_MCU_NRF52832\\sdk"
|
||||
],
|
||||
|
||||
"port_relative_dir_in_mbed" : "..",
|
||||
|
||||
"sdk_component_path": "C:\\nRF5_SDK_13.0.0-1.alpha_055eef3\\components"
|
||||
}
|
|
@ -0,0 +1,399 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "mbed_assert.h"
|
||||
#include "mbed_error.h"
|
||||
#include "pwmout_api.h"
|
||||
#include "cmsis.h"
|
||||
#include "pinmap.h"
|
||||
|
||||
#if DEVICE_PWMOUT
|
||||
|
||||
#include "app_util_platform.h"
|
||||
#include "nrf_drv_pwm.h"
|
||||
|
||||
#define MAX_PWM_COUNTERTOP (0x7FFF) // 0x7FFF is the max of COUNTERTOP value for the PWM peripherial of the nRF52.
|
||||
#define MAX_PWM_PERIOD_US (MAX_PWM_COUNTERTOP * 8) // PWM hw is driven by 16 MHz clock, hence the tick is 1_us/16,
|
||||
// and 128 is the max prescaler value.
|
||||
#define MAX_PWM_PERIOD_MS ((MAX_PWM_PERIOD_US / 1000) + 1) // approximations advance
|
||||
#define MAX_PWM_PERIOD_S ((MAX_PWM_PERIOD_US / 1000000) + 1) // approximations advance
|
||||
|
||||
|
||||
#define PWM_INSTANCE_COUNT (PWM_COUNT) // import from the nrf_drv_config.h file
|
||||
|
||||
///> instances of nRF52 PWM driver
|
||||
static const nrf_drv_pwm_t m_pwm_driver[PWM_INSTANCE_COUNT] =
|
||||
{
|
||||
#if PWM0_ENABLED
|
||||
NRF_DRV_PWM_INSTANCE(0),
|
||||
#endif
|
||||
#if PWM1_ENABLED
|
||||
NRF_DRV_PWM_INSTANCE(1),
|
||||
#endif
|
||||
#if PWM2_ENABLED
|
||||
NRF_DRV_PWM_INSTANCE(2)
|
||||
#endif
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t period_us;
|
||||
uint32_t duty_us;
|
||||
float duty;
|
||||
} pwm_signal_t; /// PWM signal description type
|
||||
|
||||
typedef struct
|
||||
{
|
||||
nrf_drv_pwm_t * p_pwm_driver;
|
||||
pwm_signal_t signal;
|
||||
volatile nrf_pwm_values_common_t seq_values[1];
|
||||
} pwm_t; /// internal PWM instance support type
|
||||
|
||||
static pwm_t m_pwm[PWM_INSTANCE_COUNT] =
|
||||
{
|
||||
#if PWM0_ENABLED
|
||||
{.p_pwm_driver = NULL},
|
||||
#endif
|
||||
#if PWM1_ENABLED
|
||||
{.p_pwm_driver = NULL},
|
||||
#endif
|
||||
#if PWM2_ENABLED
|
||||
{.p_pwm_driver = NULL}
|
||||
#endif
|
||||
}; /// Array of internal PWM instances.
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint16_t period_hwu; // unit related to pwm_clk
|
||||
uint16_t duty_hwu; // unit related to pwm_clk
|
||||
nrf_pwm_clk_t pwm_clk;
|
||||
} pulsewidth_set_t; /// helper type for timing calculations
|
||||
|
||||
|
||||
static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization);
|
||||
|
||||
// extern PWM nIRQ handler implementations
|
||||
void PWM0_IRQHandler(void);
|
||||
void PWM1_IRQHandler(void);
|
||||
void PWM2_IRQHandler(void);
|
||||
|
||||
static const peripheral_handler_desc_t pwm_handlers[PWM_INSTANCE_COUNT] =
|
||||
{
|
||||
{
|
||||
PWM0_IRQn,
|
||||
(uint32_t)PWM0_IRQHandler
|
||||
},
|
||||
{
|
||||
PWM1_IRQn,
|
||||
(uint32_t)PWM1_IRQHandler
|
||||
},
|
||||
{
|
||||
PWM2_IRQn,
|
||||
(uint32_t)PWM2_IRQHandler
|
||||
}
|
||||
};
|
||||
|
||||
void pwmout_init(pwmout_t *obj, PinName pin)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; PWM_INSTANCE_COUNT; i++)
|
||||
{
|
||||
if (m_pwm[i].p_pwm_driver == NULL) // a driver instance not assigned to the obj?
|
||||
{
|
||||
NVIC_SetVector(pwm_handlers[i].IRQn, pwm_handlers[i].vector);
|
||||
|
||||
obj->pin = pin;
|
||||
|
||||
obj->pwm_channel = i;
|
||||
|
||||
m_pwm[i].p_pwm_driver = (nrf_drv_pwm_t *) &m_pwm_driver[i];
|
||||
m_pwm[i].signal.period_us = 200000; // 0.02 s
|
||||
m_pwm[i].signal.duty_us = 100000;
|
||||
m_pwm[i].signal.duty = 0.5f;
|
||||
|
||||
obj->pwm_struct = &m_pwm[i];
|
||||
|
||||
internal_pwmout_exe(obj, true, true);
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MBED_ASSERT(i != PWM_INSTANCE_COUNT); // assert if free instance was not found.
|
||||
}
|
||||
|
||||
void pwmout_free(pwmout_t *obj)
|
||||
{
|
||||
nrf_drv_pwm_uninit( (nrf_drv_pwm_t*) obj->pwm_struct );
|
||||
|
||||
m_pwm[obj->pwm_channel].p_pwm_driver = NULL;
|
||||
}
|
||||
|
||||
void pwmout_write(pwmout_t *obj, float percent)
|
||||
{
|
||||
|
||||
if (percent < 0)
|
||||
{
|
||||
percent = 0;
|
||||
}
|
||||
else if (percent > 1)
|
||||
{
|
||||
percent = 1;
|
||||
}
|
||||
|
||||
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
|
||||
|
||||
p_pwm_signal->duty = percent;
|
||||
|
||||
int us = (((int)p_pwm_signal->period_us) * percent);
|
||||
|
||||
pwmout_pulsewidth_us(obj, us);
|
||||
}
|
||||
|
||||
float pwmout_read(pwmout_t *obj)
|
||||
{
|
||||
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
|
||||
|
||||
return (float)p_pwm_signal->duty_us / (float)p_pwm_signal->period_us;
|
||||
}
|
||||
|
||||
void pwmout_period(pwmout_t *obj, float seconds)
|
||||
{
|
||||
// raught saturation < 0, quasi-max>
|
||||
if (seconds > MAX_PWM_PERIOD_S)
|
||||
{
|
||||
seconds = MAX_PWM_PERIOD_S;
|
||||
}
|
||||
else if (seconds < 0)
|
||||
{
|
||||
seconds = 0; // f. pwmout_period_us will set period to min. value
|
||||
}
|
||||
|
||||
int us = seconds * 1000000;
|
||||
|
||||
pwmout_period_us(obj, us);
|
||||
}
|
||||
|
||||
void pwmout_period_ms(pwmout_t *obj, int ms)
|
||||
{
|
||||
// reught saturation < 0, quasi-max>
|
||||
if (ms > MAX_PWM_PERIOD_MS)
|
||||
{
|
||||
ms = MAX_PWM_PERIOD_MS;
|
||||
}
|
||||
else if (ms < 0)
|
||||
{
|
||||
ms = 0; // f. pwmout_period_us will set period to min. value
|
||||
}
|
||||
|
||||
int us = ms * 1000;
|
||||
|
||||
pwmout_period_us(obj, us);
|
||||
}
|
||||
|
||||
|
||||
void pwmout_period_us(pwmout_t *obj, int us)
|
||||
{
|
||||
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
|
||||
|
||||
// saturation <1, real-max>
|
||||
if (us > MAX_PWM_PERIOD_US)
|
||||
{
|
||||
us = MAX_PWM_PERIOD_US;
|
||||
}
|
||||
else if (us < 1)
|
||||
{
|
||||
us = 1;
|
||||
}
|
||||
|
||||
p_pwm_signal->duty_us = (int)((float)us * p_pwm_signal->duty);
|
||||
|
||||
p_pwm_signal->period_us = us;
|
||||
|
||||
internal_pwmout_exe(obj, true, false);
|
||||
}
|
||||
|
||||
void pwmout_pulsewidth(pwmout_t *obj, float seconds)
|
||||
{
|
||||
// raught saturation < 0, quasi-max>
|
||||
if (seconds > MAX_PWM_PERIOD_S)
|
||||
{
|
||||
seconds = MAX_PWM_PERIOD_S;
|
||||
}
|
||||
else if (seconds < 0)
|
||||
{
|
||||
seconds = 0;
|
||||
}
|
||||
|
||||
int us = seconds * 1000000;
|
||||
|
||||
pwmout_pulsewidth_us(obj,us);
|
||||
}
|
||||
|
||||
void pwmout_pulsewidth_ms(pwmout_t *obj, int ms)
|
||||
{
|
||||
// raught saturation < 0, quasi-max>
|
||||
if (ms > MAX_PWM_PERIOD_MS)
|
||||
{
|
||||
ms = MAX_PWM_PERIOD_MS;
|
||||
}
|
||||
else if (ms < 0)
|
||||
{
|
||||
ms = 0;
|
||||
}
|
||||
|
||||
int us = ms * 1000;
|
||||
|
||||
pwmout_pulsewidth_us(obj, us);
|
||||
}
|
||||
|
||||
void pwmout_pulsewidth_us(pwmout_t *obj, int us)
|
||||
{
|
||||
// saturation <0, real-max>
|
||||
if (us > MAX_PWM_PERIOD_US)
|
||||
{
|
||||
us = MAX_PWM_PERIOD_US;
|
||||
}
|
||||
else if (us < 0)
|
||||
{
|
||||
us = 0;
|
||||
}
|
||||
|
||||
pwm_signal_t * p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
|
||||
|
||||
p_pwm_signal->duty_us = us;
|
||||
p_pwm_signal->duty = us / p_pwm_signal->period_us;
|
||||
|
||||
internal_pwmout_exe(obj, false, false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
static ret_code_t pulsewidth_us_set_get(int period_hwu, int duty_hwu, pulsewidth_set_t * p_settings)
|
||||
{
|
||||
uint16_t div;
|
||||
nrf_pwm_clk_t pwm_clk = NRF_PWM_CLK_16MHz;
|
||||
|
||||
for(div = 1; div <= 128 ; div <<= 1) // 128 is the maximum of clock prescaler for PWM peripherial
|
||||
{
|
||||
if (MAX_PWM_COUNTERTOP >= period_hwu)
|
||||
{
|
||||
p_settings->period_hwu = period_hwu; // unit [us/16 * div]
|
||||
p_settings->duty_hwu = duty_hwu; // unit [us/16 * div]
|
||||
p_settings->pwm_clk = pwm_clk;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
period_hwu >>= 1;
|
||||
duty_hwu >>= 1;
|
||||
pwm_clk++;
|
||||
}
|
||||
|
||||
return NRF_ERROR_INVALID_PARAM;
|
||||
}
|
||||
|
||||
|
||||
static void internal_pwmout_exe(pwmout_t *obj, bool new_period, bool initialization)
|
||||
{
|
||||
pulsewidth_set_t pulsewidth_set;
|
||||
pwm_signal_t * p_pwm_signal;
|
||||
nrf_drv_pwm_t * p_pwm_driver;
|
||||
ret_code_t ret_code;
|
||||
|
||||
p_pwm_signal = &(((pwm_t*)obj->pwm_struct)->signal);
|
||||
|
||||
if (NRF_SUCCESS == pulsewidth_us_set_get(p_pwm_signal->period_us * 16, // base clk for PWM is 16 MHz
|
||||
p_pwm_signal->duty_us * 16, // base clk for PWM is 16 MHz
|
||||
&pulsewidth_set))
|
||||
{
|
||||
p_pwm_driver = (((pwm_t*)obj->pwm_struct)->p_pwm_driver);
|
||||
|
||||
const nrf_pwm_sequence_t seq =
|
||||
{
|
||||
.values.p_common = (nrf_pwm_values_common_t*) (((pwm_t*)obj->pwm_struct)->seq_values),
|
||||
.length = 1,
|
||||
.repeats = 0,
|
||||
.end_delay = 0
|
||||
};
|
||||
|
||||
(((pwm_t*)obj->pwm_struct)->seq_values)[0] = pulsewidth_set.duty_hwu | 0x8000;
|
||||
|
||||
if (new_period)
|
||||
{
|
||||
nrf_drv_pwm_config_t config0 =
|
||||
{
|
||||
.output_pins =
|
||||
{
|
||||
obj->pin | NRF_DRV_PWM_PIN_INVERTED, // channel 0
|
||||
NRF_DRV_PWM_PIN_NOT_USED, // channel 1
|
||||
NRF_DRV_PWM_PIN_NOT_USED, // channel 2
|
||||
NRF_DRV_PWM_PIN_NOT_USED, // channel 3
|
||||
},
|
||||
.irq_priority = PWM_DEFAULT_CONFIG_IRQ_PRIORITY,
|
||||
.base_clock = pulsewidth_set.pwm_clk,
|
||||
.count_mode = NRF_PWM_MODE_UP,
|
||||
.top_value = pulsewidth_set.period_hwu,
|
||||
.load_mode = NRF_PWM_LOAD_COMMON,
|
||||
.step_mode = NRF_PWM_STEP_AUTO
|
||||
};
|
||||
|
||||
if (!initialization)
|
||||
{
|
||||
nrf_drv_pwm_uninit(p_pwm_driver);
|
||||
}
|
||||
|
||||
ret_code = nrf_drv_pwm_init( p_pwm_driver, &config0, NULL);
|
||||
|
||||
MBED_ASSERT(ret_code == NRF_SUCCESS); // assert if free instance was not found.
|
||||
}
|
||||
|
||||
nrf_drv_pwm_simple_playback(p_pwm_driver, &seq, 0, NRF_DRV_PWM_FLAG_LOOP);
|
||||
}
|
||||
else
|
||||
{
|
||||
MBED_ASSERT(0); // force assertion
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
#endif // DEVICE_PWMOUT
|
|
@ -0,0 +1,78 @@
|
|||
/*
|
||||
* Copyright (c) 2016 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "nrf.h"
|
||||
#include "cmsis_nvic.h"
|
||||
#include "stdint.h"
|
||||
#include "nrf_sdm.h"
|
||||
#include "section_vars.h"
|
||||
|
||||
#if defined(__CC_ARM)
|
||||
__attribute__ ((section("noinit"),zero_init))
|
||||
uint32_t nrf_dispatch_vector[NVIC_NUM_VECTORS];
|
||||
#elif defined(__GNUC__)
|
||||
__attribute__ ((section(".noinit")))
|
||||
uint32_t nrf_dispatch_vector[NVIC_NUM_VECTORS];
|
||||
#elif defined(__ICCARM__)
|
||||
uint32_t nrf_dispatch_vector[NVIC_NUM_VECTORS] @ ".noinit";
|
||||
#endif
|
||||
|
||||
|
||||
typedef void (*generic_irq_handler_t)(void);
|
||||
|
||||
|
||||
extern uint32_t __Vectors[];
|
||||
#define VECTORS_FLASH_START __Vectors
|
||||
|
||||
/**
|
||||
* @brief Function for relocation of the vector to RAM on nRF5x devices.
|
||||
* This function is intended to be called during startup.
|
||||
*/
|
||||
void nrf_reloc_vector_table(void)
|
||||
{
|
||||
// Copy and switch to dynamic vectors
|
||||
uint32_t *old_vectors = (uint32_t*)VECTORS_FLASH_START;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i< NVIC_NUM_VECTORS; i++)
|
||||
{
|
||||
nrf_dispatch_vector[i] = old_vectors[i];
|
||||
}
|
||||
|
||||
sd_softdevice_vector_table_base_set((uint32_t) nrf_dispatch_vector);
|
||||
}
|
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "rtc_api.h"
|
||||
|
||||
#if DEVICE_RTC
|
||||
|
||||
#include "common_rtc.h"
|
||||
#include "nrf_drv_clock.h"
|
||||
#include "app_util_platform.h"
|
||||
|
||||
static time_t m_time_base;
|
||||
|
||||
void rtc_init(void)
|
||||
{
|
||||
common_rtc_init();
|
||||
}
|
||||
|
||||
void rtc_free(void)
|
||||
{
|
||||
// A common counter is used for RTC, lp_ticker and us_ticker, so it can't be
|
||||
// disabled here, but this does not cause any extra cost. Besides, currently
|
||||
// this function is not used by RTC API in mbed-drivers.
|
||||
}
|
||||
|
||||
int rtc_isenabled(void)
|
||||
{
|
||||
return m_common_rtc_enabled;
|
||||
}
|
||||
|
||||
static uint32_t rtc_seconds_get(void)
|
||||
{
|
||||
// Convert current counter value to seconds.
|
||||
uint32_t seconds = nrf_rtc_counter_get(COMMON_RTC_INSTANCE) / RTC_INPUT_FREQ;
|
||||
// Add proper amount of seconds for each registered overflow of the counter.
|
||||
uint32_t seconds_per_overflow = (1uL << RTC_COUNTER_BITS) / RTC_INPUT_FREQ;
|
||||
return (seconds + (m_common_rtc_overflows * seconds_per_overflow));
|
||||
}
|
||||
|
||||
time_t rtc_read(void)
|
||||
{
|
||||
return m_time_base + rtc_seconds_get();
|
||||
}
|
||||
|
||||
void rtc_write(time_t t)
|
||||
{
|
||||
uint32_t seconds;
|
||||
|
||||
do
|
||||
{
|
||||
seconds = rtc_seconds_get();
|
||||
m_time_base = t - seconds;
|
||||
// If the number of seconds indicated by the counter changed during the
|
||||
// update of the time base, just repeat the update, now using the new
|
||||
// number of seconds.
|
||||
} while (seconds != rtc_seconds_get());
|
||||
}
|
||||
|
||||
#endif // DEVICE_RTC
|
|
@ -0,0 +1,717 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
#include "sdk_common.h"
|
||||
#if NRF_MODULE_ENABLED(BLE_ADVERTISING)
|
||||
#include "ble_advdata.h"
|
||||
#include "ble_advertising.h"
|
||||
#include "nrf_soc.h"
|
||||
#include "nrf_log.h"
|
||||
#include "fstorage.h"
|
||||
#include "sdk_errors.h"
|
||||
|
||||
|
||||
// Total number of possible advertising modes.
|
||||
#define BLE_ADV_MODES (5)
|
||||
|
||||
|
||||
static bool m_initialized;
|
||||
static bool m_advertising_start_pending; /**< Flag to keep track of ongoing operations in flash. */
|
||||
|
||||
static ble_adv_evt_t m_adv_evt; /**< Advertising event propogated to the main application. The event is either a transaction to a new advertising mode, or a request for whitelist or peer address. */
|
||||
|
||||
static ble_adv_mode_t m_adv_mode_current; /**< Variable to keep track of the current advertising mode. */
|
||||
static ble_adv_modes_config_t m_adv_modes_config; /**< Struct to keep track of disabled and enabled advertising modes, as well as time-outs and intervals.*/
|
||||
|
||||
static ble_gap_addr_t m_peer_address; /**< Address of the most recently connected peer, used for direct advertising. */
|
||||
static bool m_peer_addr_reply_expected; /**< Flag to verify that peer address is only set when requested. */
|
||||
|
||||
static ble_advdata_t m_advdata; /**< Used by the initialization function to set name, appearance, and UUIDs and advertising flags visible to peer devices. */
|
||||
static ble_advdata_manuf_data_t m_manuf_specific_data; /**< Manufacturer specific data structure*/
|
||||
static uint8_t m_manuf_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the Manufacturer specific data*/
|
||||
static ble_advdata_service_data_t m_service_data; /**< Service data structure. */
|
||||
static uint8_t m_service_data_array[BLE_GAP_ADV_MAX_SIZE]; /**< Array to store the service data. */
|
||||
static ble_advdata_conn_int_t m_slave_conn_int; /**< Connection interval range structure.*/
|
||||
static uint16_t m_current_slave_link_conn_handle; /**< Connection handle for the active link. */
|
||||
|
||||
static ble_advertising_evt_handler_t m_evt_handler; /**< Handler for the advertising events. Can be initialized as NULL if no handling is implemented on in the main application. */
|
||||
static ble_advertising_error_handler_t m_error_handler; /**< Handler for the advertising error events. */
|
||||
|
||||
static bool m_whitelist_temporarily_disabled; /**< Flag to keep track of temporary disabling of the whitelist. */
|
||||
static bool m_whitelist_reply_expected;
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
|
||||
// For SoftDevices v 2.x, this module caches a whitelist which is retrieved from the
|
||||
// application using an event, and which is passed as a parameter when calling
|
||||
// sd_ble_gap_adv_start().
|
||||
|
||||
static ble_gap_addr_t * m_p_whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
|
||||
static ble_gap_irk_t * m_p_whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
|
||||
static ble_gap_addr_t m_whitelist_addrs[BLE_GAP_WHITELIST_ADDR_MAX_COUNT];
|
||||
static ble_gap_irk_t m_whitelist_irks[BLE_GAP_WHITELIST_IRK_MAX_COUNT];
|
||||
|
||||
static ble_gap_whitelist_t m_whitelist =
|
||||
{
|
||||
.pp_addrs = m_p_whitelist_addrs,
|
||||
.pp_irks = m_p_whitelist_irks
|
||||
};
|
||||
|
||||
#else
|
||||
|
||||
// For SoftDevices v 3.x, this module does not need to cache a whitelist, but it needs to
|
||||
// be aware of whether or not a whitelist has been set (e.g. using the Peer Manager)
|
||||
// in order to start advertising with the proper advertising params (filter policy).
|
||||
|
||||
static bool m_whitelist_in_use;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
|
||||
static bool whitelist_has_entries()
|
||||
{
|
||||
return ((m_whitelist.addr_count != 0) || (m_whitelist.irk_count != 0));
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
static bool whitelist_has_entries()
|
||||
{
|
||||
return m_whitelist_in_use;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
/**@brief Function for checking if an address is valid.
|
||||
*/
|
||||
static bool addr_is_valid(uint8_t const * const addr)
|
||||
{
|
||||
for (uint32_t i = 0; i < BLE_GAP_ADDR_LEN; i++)
|
||||
{
|
||||
if (addr[i] != 0)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
static ble_adv_mode_t adv_mode_next_get(ble_adv_mode_t adv_mode)
|
||||
{
|
||||
return (ble_adv_mode_t)((adv_mode + 1) % BLE_ADV_MODES);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the Connected event.
|
||||
*
|
||||
* @param[in] p_ble_evt Event received from the BLE stack.
|
||||
*/
|
||||
static void on_connected(ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
if (p_ble_evt->evt.gap_evt.params.connected.role == BLE_GAP_ROLE_PERIPH)
|
||||
{
|
||||
m_current_slave_link_conn_handle = p_ble_evt->evt.gap_evt.conn_handle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the Disconnected event.
|
||||
*
|
||||
* @param[in] p_ble_evt Event received from the BLE stack.
|
||||
*/
|
||||
static void on_disconnected(ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
m_whitelist_temporarily_disabled = false;
|
||||
|
||||
if (p_ble_evt->evt.gap_evt.conn_handle == m_current_slave_link_conn_handle)
|
||||
{
|
||||
ret = ble_advertising_start(BLE_ADV_MODE_DIRECTED);
|
||||
if ((ret != NRF_SUCCESS) && (m_error_handler != NULL))
|
||||
{
|
||||
m_error_handler(ret);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling the Timeout event.
|
||||
*
|
||||
* @param[in] p_ble_evt Event received from the BLE stack.
|
||||
*/
|
||||
static void on_timeout(ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
ret_code_t ret;
|
||||
|
||||
if (p_ble_evt->evt.gap_evt.params.timeout.src != BLE_GAP_TIMEOUT_SRC_ADVERTISING)
|
||||
{
|
||||
// Nothing to do.
|
||||
return;
|
||||
}
|
||||
|
||||
// Start advertising in the next mode.
|
||||
ret = ble_advertising_start(adv_mode_next_get(m_adv_mode_current));
|
||||
|
||||
if ((ret != NRF_SUCCESS) && (m_error_handler != NULL))
|
||||
{
|
||||
m_error_handler(ret);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/** @brief Function to determine if a flash write operation in in progress.
|
||||
*
|
||||
* @return true if a flash operation is in progress, false if not.
|
||||
*/
|
||||
static bool flash_access_in_progress()
|
||||
{
|
||||
uint32_t count;
|
||||
|
||||
(void)fs_queued_op_count_get(&count);
|
||||
|
||||
return (count != 0);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Get the next available advertising mode.
|
||||
*
|
||||
* @param[in] adv_mode Requested advertising mode.
|
||||
*
|
||||
* @returns adv_mode if possible, or the best available mode if not.
|
||||
*/
|
||||
static ble_adv_mode_t adv_mode_next_avail_get(ble_adv_mode_t adv_mode)
|
||||
{
|
||||
bool peer_addr_is_valid = addr_is_valid(m_peer_address.addr);
|
||||
|
||||
// If a mode is disabled, continue to the next mode.
|
||||
|
||||
switch (adv_mode)
|
||||
{
|
||||
case BLE_ADV_MODE_DIRECTED:
|
||||
if ((m_adv_modes_config.ble_adv_directed_enabled) && peer_addr_is_valid)
|
||||
{
|
||||
return BLE_ADV_MODE_DIRECTED;
|
||||
}
|
||||
// Fallthrough.
|
||||
|
||||
case BLE_ADV_MODE_DIRECTED_SLOW:
|
||||
if ((m_adv_modes_config.ble_adv_directed_slow_enabled) && peer_addr_is_valid)
|
||||
{
|
||||
return BLE_ADV_MODE_DIRECTED_SLOW;
|
||||
}
|
||||
// Fallthrough.
|
||||
|
||||
case BLE_ADV_MODE_FAST:
|
||||
if (m_adv_modes_config.ble_adv_fast_enabled)
|
||||
{
|
||||
return BLE_ADV_MODE_FAST;
|
||||
}
|
||||
// Fallthrough.
|
||||
|
||||
case BLE_ADV_MODE_SLOW:
|
||||
if (m_adv_modes_config.ble_adv_slow_enabled)
|
||||
{
|
||||
return BLE_ADV_MODE_SLOW;
|
||||
}
|
||||
// Fallthrough.
|
||||
|
||||
default:
|
||||
return BLE_ADV_MODE_IDLE;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for starting directed advertising.
|
||||
*
|
||||
* @param[out] p_adv_params Advertising parameters.
|
||||
*
|
||||
* @return NRF_SUCCESS
|
||||
*/
|
||||
static ret_code_t set_adv_mode_directed(ble_gap_adv_params_t * p_adv_params)
|
||||
{
|
||||
m_adv_evt = BLE_ADV_EVT_DIRECTED;
|
||||
|
||||
p_adv_params->p_peer_addr = &m_peer_address;
|
||||
p_adv_params->type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND;
|
||||
p_adv_params->timeout = 0;
|
||||
p_adv_params->interval = 0;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for starting directed slow advertising.
|
||||
*
|
||||
* @param[out] p_adv_params Advertising parameters.
|
||||
*
|
||||
* @return NRF_SUCCESS
|
||||
*/
|
||||
static ret_code_t set_adv_mode_directed_slow(ble_gap_adv_params_t * p_adv_params)
|
||||
{
|
||||
m_adv_evt = BLE_ADV_EVT_DIRECTED_SLOW;
|
||||
|
||||
p_adv_params->p_peer_addr = &m_peer_address;
|
||||
p_adv_params->type = BLE_GAP_ADV_TYPE_ADV_DIRECT_IND;
|
||||
p_adv_params->timeout = m_adv_modes_config.ble_adv_directed_slow_timeout;
|
||||
p_adv_params->interval = m_adv_modes_config.ble_adv_directed_slow_interval;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for starting fast advertising.
|
||||
*
|
||||
* @param[out] p_adv_params Advertising parameters.
|
||||
*
|
||||
* @return NRF_SUCCESS or an error from @ref ble_advdata_set().
|
||||
*/
|
||||
static ret_code_t set_adv_mode_fast(ble_gap_adv_params_t * p_adv_params)
|
||||
{
|
||||
ret_code_t ret;
|
||||
|
||||
p_adv_params->interval = m_adv_modes_config.ble_adv_fast_interval;
|
||||
p_adv_params->timeout = m_adv_modes_config.ble_adv_fast_timeout;
|
||||
|
||||
if ((m_adv_modes_config.ble_adv_whitelist_enabled) &&
|
||||
(!m_whitelist_temporarily_disabled) &&
|
||||
(whitelist_has_entries()))
|
||||
{
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
p_adv_params->p_whitelist = &m_whitelist;
|
||||
#endif
|
||||
|
||||
p_adv_params->fp = BLE_GAP_ADV_FP_FILTER_CONNREQ;
|
||||
m_advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
|
||||
|
||||
ret = ble_advdata_set(&m_advdata, NULL);
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
m_adv_evt = BLE_ADV_EVT_FAST_WHITELIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_adv_evt = BLE_ADV_EVT_FAST;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for starting slow advertising.
|
||||
*
|
||||
* @param[out] p_adv_params Advertising parameters.
|
||||
*
|
||||
* @return NRF_SUCCESS or an error from @ref ble_advdata_set().
|
||||
*/
|
||||
static ret_code_t set_adv_mode_slow(ble_gap_adv_params_t * p_adv_params)
|
||||
{
|
||||
ret_code_t ret;
|
||||
|
||||
p_adv_params->interval = m_adv_modes_config.ble_adv_slow_interval;
|
||||
p_adv_params->timeout = m_adv_modes_config.ble_adv_slow_timeout;
|
||||
|
||||
if ((m_adv_modes_config.ble_adv_whitelist_enabled) &&
|
||||
(!m_whitelist_temporarily_disabled) &&
|
||||
(whitelist_has_entries()))
|
||||
{
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
{
|
||||
p_adv_params->p_whitelist = &m_whitelist;
|
||||
}
|
||||
#endif
|
||||
|
||||
p_adv_params->fp = BLE_GAP_ADV_FP_FILTER_CONNREQ;
|
||||
m_advdata.flags = BLE_GAP_ADV_FLAG_BR_EDR_NOT_SUPPORTED;
|
||||
|
||||
ret = ble_advdata_set(&m_advdata, NULL);
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
m_adv_evt = BLE_ADV_EVT_SLOW_WHITELIST;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_adv_evt = BLE_ADV_EVT_SLOW;
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_advertising_init(ble_advdata_t const * p_advdata,
|
||||
ble_advdata_t const * p_srdata,
|
||||
ble_adv_modes_config_t const * p_config,
|
||||
ble_advertising_evt_handler_t const evt_handler,
|
||||
ble_advertising_error_handler_t const error_handler)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
if ((p_advdata == NULL) || (p_config == NULL))
|
||||
{
|
||||
return NRF_ERROR_NULL;
|
||||
}
|
||||
|
||||
m_initialized = true;
|
||||
m_adv_mode_current = BLE_ADV_MODE_IDLE;
|
||||
m_adv_modes_config = *p_config;
|
||||
m_evt_handler = evt_handler;
|
||||
m_error_handler = error_handler;
|
||||
m_current_slave_link_conn_handle = BLE_CONN_HANDLE_INVALID;
|
||||
|
||||
memset(&m_peer_address, 0, sizeof(m_peer_address));
|
||||
memset(&m_advdata, 0, sizeof(m_advdata));
|
||||
|
||||
// Copy advertising data.
|
||||
m_advdata.name_type = p_advdata->name_type;
|
||||
m_advdata.include_appearance = p_advdata->include_appearance;
|
||||
m_advdata.flags = p_advdata->flags;
|
||||
m_advdata.short_name_len = p_advdata->short_name_len;
|
||||
|
||||
m_advdata.uuids_complete = p_advdata->uuids_complete;
|
||||
m_advdata.uuids_more_available = p_advdata->uuids_more_available;
|
||||
m_advdata.uuids_solicited = p_advdata->uuids_solicited;
|
||||
|
||||
if (p_advdata->p_manuf_specific_data != NULL)
|
||||
{
|
||||
m_advdata.p_manuf_specific_data = &m_manuf_specific_data;
|
||||
m_manuf_specific_data.data.p_data = m_manuf_data_array;
|
||||
m_advdata.p_manuf_specific_data->company_identifier =
|
||||
p_advdata->p_manuf_specific_data->company_identifier;
|
||||
m_advdata.p_manuf_specific_data->data.size = p_advdata->p_manuf_specific_data->data.size;
|
||||
|
||||
for (uint32_t i = 0; i < m_advdata.p_manuf_specific_data->data.size; i++)
|
||||
{
|
||||
m_manuf_data_array[i] = p_advdata->p_manuf_specific_data->data.p_data[i];
|
||||
}
|
||||
}
|
||||
|
||||
if (p_advdata->p_service_data_array != NULL)
|
||||
{
|
||||
m_service_data.data.p_data = m_service_data_array;
|
||||
m_advdata.p_service_data_array = &m_service_data;
|
||||
m_advdata.p_service_data_array->data.p_data = m_service_data_array;
|
||||
m_advdata.p_service_data_array->data.size = p_advdata->p_service_data_array->data.size;
|
||||
m_advdata.p_service_data_array->service_uuid = p_advdata->p_service_data_array->service_uuid;
|
||||
|
||||
for (uint32_t i = 0; i < m_advdata.p_service_data_array->data.size; i++)
|
||||
{
|
||||
m_service_data_array[i] = p_advdata->p_service_data_array->data.p_data[i];
|
||||
}
|
||||
|
||||
m_advdata.service_data_count = p_advdata->service_data_count;
|
||||
}
|
||||
|
||||
if (p_advdata->p_slave_conn_int != NULL)
|
||||
{
|
||||
m_advdata.p_slave_conn_int = &m_slave_conn_int;
|
||||
m_advdata.p_slave_conn_int->max_conn_interval = p_advdata->p_slave_conn_int->max_conn_interval;
|
||||
m_advdata.p_slave_conn_int->min_conn_interval = p_advdata->p_slave_conn_int->min_conn_interval;
|
||||
}
|
||||
|
||||
if (p_advdata->p_tx_power_level != NULL)
|
||||
{
|
||||
m_advdata.p_tx_power_level = p_advdata->p_tx_power_level;
|
||||
}
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
for (int i = 0; i <BLE_GAP_WHITELIST_ADDR_MAX_COUNT ; i++)
|
||||
{
|
||||
m_whitelist.pp_addrs[i] = &m_whitelist_addrs[i];
|
||||
}
|
||||
|
||||
for (int i = 0; i <BLE_GAP_WHITELIST_IRK_MAX_COUNT ; i++)
|
||||
{
|
||||
m_whitelist.pp_irks[i] = &m_whitelist_irks[i];
|
||||
}
|
||||
#endif
|
||||
|
||||
ret = ble_advdata_set(&m_advdata, p_srdata);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_advertising_start(ble_adv_mode_t advertising_mode)
|
||||
{
|
||||
uint32_t ret;
|
||||
ble_gap_adv_params_t adv_params;
|
||||
|
||||
if (m_initialized == false)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
m_adv_mode_current = advertising_mode;
|
||||
|
||||
// Delay starting advertising until the flash operations are complete.
|
||||
if (flash_access_in_progress())
|
||||
{
|
||||
m_advertising_start_pending = true;
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
memset(&m_peer_address, 0, sizeof(m_peer_address));
|
||||
|
||||
if ( ((m_adv_modes_config.ble_adv_directed_enabled) && (m_adv_mode_current == BLE_ADV_MODE_DIRECTED))
|
||||
||((m_adv_modes_config.ble_adv_directed_slow_enabled) && (m_adv_mode_current == BLE_ADV_MODE_DIRECTED))
|
||||
||((m_adv_modes_config.ble_adv_directed_slow_enabled) && (m_adv_mode_current == BLE_ADV_MODE_DIRECTED_SLOW))
|
||||
)
|
||||
{
|
||||
if (m_evt_handler != NULL)
|
||||
{
|
||||
m_peer_addr_reply_expected = true;
|
||||
m_evt_handler(BLE_ADV_EVT_PEER_ADDR_REQUEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_peer_addr_reply_expected = false;
|
||||
}
|
||||
}
|
||||
|
||||
m_adv_mode_current = adv_mode_next_avail_get(advertising_mode);
|
||||
|
||||
// Fetch the whitelist.
|
||||
if ((m_evt_handler != NULL) &&
|
||||
(m_adv_mode_current == BLE_ADV_MODE_FAST || m_adv_mode_current == BLE_ADV_MODE_SLOW) &&
|
||||
(m_adv_modes_config.ble_adv_whitelist_enabled) &&
|
||||
(!m_whitelist_temporarily_disabled))
|
||||
{
|
||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
||||
m_whitelist_in_use = false;
|
||||
#endif
|
||||
m_whitelist_reply_expected = true;
|
||||
m_evt_handler(BLE_ADV_EVT_WHITELIST_REQUEST);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_whitelist_reply_expected = false;
|
||||
}
|
||||
|
||||
// Initialize advertising parameters with default values.
|
||||
memset(&adv_params, 0, sizeof(adv_params));
|
||||
|
||||
adv_params.type = BLE_GAP_ADV_TYPE_ADV_IND;
|
||||
adv_params.fp = BLE_GAP_ADV_FP_ANY;
|
||||
|
||||
// Set advertising parameters and events according to selected advertising mode.
|
||||
switch (m_adv_mode_current)
|
||||
{
|
||||
case BLE_ADV_MODE_DIRECTED:
|
||||
ret = set_adv_mode_directed(&adv_params);
|
||||
break;
|
||||
|
||||
case BLE_ADV_MODE_DIRECTED_SLOW:
|
||||
ret = set_adv_mode_directed_slow(&adv_params);
|
||||
break;
|
||||
|
||||
case BLE_ADV_MODE_FAST:
|
||||
ret = set_adv_mode_fast(&adv_params);
|
||||
break;
|
||||
|
||||
case BLE_ADV_MODE_SLOW:
|
||||
ret = set_adv_mode_slow(&adv_params);
|
||||
break;
|
||||
|
||||
case BLE_ADV_MODE_IDLE:
|
||||
m_adv_evt = BLE_ADV_EVT_IDLE;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (m_adv_mode_current != BLE_ADV_MODE_IDLE)
|
||||
{
|
||||
ret = sd_ble_gap_adv_start(&adv_params);
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (m_evt_handler != NULL)
|
||||
{
|
||||
m_evt_handler(m_adv_evt);
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
void ble_advertising_on_ble_evt(ble_evt_t const * p_ble_evt)
|
||||
{
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GAP_EVT_CONNECTED:
|
||||
on_connected(p_ble_evt);
|
||||
break;
|
||||
|
||||
// Upon disconnection, whitelist will be activated and direct advertising is started.
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
on_disconnected(p_ble_evt);
|
||||
break;
|
||||
|
||||
// Upon time-out, the next advertising mode is started.
|
||||
case BLE_GAP_EVT_TIMEOUT:
|
||||
on_timeout(p_ble_evt);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ble_advertising_on_sys_evt(uint32_t sys_evt)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
switch (sys_evt)
|
||||
{
|
||||
//When a flash operation finishes, re-attempt to start advertising operations.
|
||||
case NRF_EVT_FLASH_OPERATION_SUCCESS:
|
||||
case NRF_EVT_FLASH_OPERATION_ERROR:
|
||||
if (m_advertising_start_pending)
|
||||
{
|
||||
m_advertising_start_pending = false;
|
||||
ret = ble_advertising_start(m_adv_mode_current);
|
||||
if ((ret != NRF_SUCCESS) && (m_error_handler != NULL))
|
||||
{
|
||||
m_error_handler(ret);
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
// No implementation needed.
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_advertising_peer_addr_reply(ble_gap_addr_t * p_peer_address)
|
||||
{
|
||||
if (!m_peer_addr_reply_expected)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
m_peer_addr_reply_expected = false;
|
||||
|
||||
memcpy(&m_peer_address, p_peer_address, sizeof(m_peer_address));
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_advertising_whitelist_reply(ble_gap_addr_t const * p_gap_addrs,
|
||||
uint32_t addr_cnt,
|
||||
ble_gap_irk_t const * p_gap_irks,
|
||||
uint32_t irk_cnt)
|
||||
{
|
||||
if (!m_whitelist_reply_expected)
|
||||
{
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
m_whitelist_reply_expected = false;
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION <= 2)
|
||||
|
||||
m_whitelist.addr_count = addr_cnt;
|
||||
m_whitelist.irk_count = irk_cnt;
|
||||
|
||||
for (uint32_t i = 0; i < addr_cnt; i++)
|
||||
{
|
||||
*m_whitelist.pp_addrs[i] = p_gap_addrs[i];
|
||||
}
|
||||
|
||||
for (uint32_t i = 0; i < irk_cnt; i++)
|
||||
{
|
||||
*m_whitelist.pp_irks[i] = p_gap_irks[i];
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
m_whitelist_in_use = ((addr_cnt > 0) || (irk_cnt > 0));
|
||||
|
||||
#endif
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_advertising_restart_without_whitelist(void)
|
||||
{
|
||||
uint32_t ret;
|
||||
|
||||
(void) sd_ble_gap_adv_stop();
|
||||
|
||||
m_whitelist_temporarily_disabled = true;
|
||||
|
||||
#if (NRF_SD_BLE_API_VERSION >= 3)
|
||||
m_whitelist_in_use = false;
|
||||
#endif
|
||||
|
||||
m_advdata.flags = BLE_GAP_ADV_FLAGS_LE_ONLY_GENERAL_DISC_MODE;
|
||||
|
||||
ret = ble_advdata_set(&m_advdata, NULL);
|
||||
if (ret != NRF_SUCCESS)
|
||||
{
|
||||
return ret;
|
||||
}
|
||||
|
||||
ret = ble_advertising_start(m_adv_mode_current);
|
||||
if ((ret != NRF_SUCCESS) && (m_error_handler != NULL))
|
||||
{
|
||||
m_error_handler(ret);
|
||||
}
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
#endif // NRF_MODULE_ENABLED(BLE_ADVERTISING)
|
|
@ -0,0 +1,261 @@
|
|||
/*
|
||||
* Copyright (c) 2015 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup ble_advertising Advertising Module
|
||||
* @{
|
||||
* @ingroup ble_sdk_lib
|
||||
* @brief Module for handling connectable BLE advertising.
|
||||
*
|
||||
* @details The Advertising Module handles connectable advertising for your application. It can
|
||||
* be configured with advertising modes to suit most typical use cases.
|
||||
* Your main application can react to changes in advertising modes
|
||||
* if an event handler is provided.
|
||||
*
|
||||
* @note The Advertising Module supports only applications with a single peripheral link.
|
||||
*
|
||||
* The application must propagate BLE stack events to this module by calling
|
||||
* @ref ble_advertising_on_ble_evt() and system events by calling
|
||||
* @ref ble_advertising_on_sys_evt().
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLE_ADVERTISING_H__
|
||||
#define BLE_ADVERTISING_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf_error.h"
|
||||
#include "headers/ble.h"
|
||||
#include "ble_gattc.h"
|
||||
#include "ble_advdata.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
/**@brief Advertising modes.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
BLE_ADV_MODE_IDLE, /**< Idle; no connectable advertising is ongoing. */
|
||||
BLE_ADV_MODE_DIRECTED, /**< Directed advertising attempts to connect to the most recently disconnected peer. */
|
||||
BLE_ADV_MODE_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) attempts to connect to the most recently disconnected peer. */
|
||||
BLE_ADV_MODE_FAST, /**< Fast advertising will connect to any peer device, or filter with a whitelist if one exists. */
|
||||
BLE_ADV_MODE_SLOW, /**< Slow advertising is similar to fast advertising. By default, it uses a longer advertising interval and time-out than fast advertising. However, these options are defined by the user. */
|
||||
} ble_adv_mode_t;
|
||||
|
||||
/**@brief Advertising events.
|
||||
*
|
||||
* @details These events are propagated to the main application if a handler was provided during
|
||||
* initialization of the Advertising Module. Events for modes that are not used can be
|
||||
* ignored. Similarly, BLE_ADV_EVT_WHITELIST_REQUEST and BLE_ADV_EVT_PEER_ADDR_REQUEST
|
||||
* can be ignored if whitelist and direct advertising is not used.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
BLE_ADV_EVT_IDLE, /**< Idle; no connectable advertising is ongoing.*/
|
||||
BLE_ADV_EVT_DIRECTED, /**< Direct advertising mode has started. */
|
||||
BLE_ADV_EVT_DIRECTED_SLOW, /**< Directed advertising (low duty cycle) has started. */
|
||||
BLE_ADV_EVT_FAST, /**< Fast advertising mode has started. */
|
||||
BLE_ADV_EVT_SLOW, /**< Slow advertising mode has started. */
|
||||
BLE_ADV_EVT_FAST_WHITELIST, /**< Fast advertising mode using the whitelist has started. */
|
||||
BLE_ADV_EVT_SLOW_WHITELIST, /**< Slow advertising mode using the whitelist has started. */
|
||||
BLE_ADV_EVT_WHITELIST_REQUEST, /**< Request a whitelist from the main application. For whitelist advertising to work, the whitelist must be set when this event occurs. */
|
||||
BLE_ADV_EVT_PEER_ADDR_REQUEST /**< Request a peer address from the main application. For directed advertising to work, the peer address must be set when this event occurs. */
|
||||
} ble_adv_evt_t;
|
||||
|
||||
|
||||
/**@brief Options for the different advertisement modes.
|
||||
*
|
||||
* @details This structure is used to enable or disable advertising modes and to configure time-out
|
||||
* periods and advertising intervals.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
bool ble_adv_whitelist_enabled; /**< Enable or disable use of the whitelist. */
|
||||
bool ble_adv_directed_enabled; /**< Enable or disable direct advertising mode. */
|
||||
bool ble_adv_directed_slow_enabled; /**< Enable or disable direct advertising mode. */
|
||||
bool ble_adv_fast_enabled; /**< Enable or disable fast advertising mode. */
|
||||
bool ble_adv_slow_enabled; /**< Enable or disable slow advertising mode. */
|
||||
uint32_t ble_adv_directed_slow_interval; /**< Advertising interval for directed advertising. */
|
||||
uint32_t ble_adv_directed_slow_timeout; /**< Time-out (number of tries) for direct advertising. */
|
||||
uint32_t ble_adv_fast_interval; /**< Advertising interval for fast advertising. */
|
||||
uint32_t ble_adv_fast_timeout; /**< Time-out (in seconds) for fast advertising. */
|
||||
uint32_t ble_adv_slow_interval; /**< Advertising interval for slow advertising. */
|
||||
uint32_t ble_adv_slow_timeout; /**< Time-out (in seconds) for slow advertising. */
|
||||
} ble_adv_modes_config_t;
|
||||
|
||||
|
||||
typedef struct
|
||||
{
|
||||
uint32_t interval;
|
||||
uint32_t timeout;
|
||||
bool enabled;
|
||||
} ble_adv_mode_config_t;
|
||||
|
||||
|
||||
/**@brief BLE advertising event handler type. */
|
||||
typedef void (*ble_advertising_evt_handler_t) (ble_adv_evt_t const adv_evt);
|
||||
|
||||
/**@brief BLE advertising error handler type. */
|
||||
typedef void (*ble_advertising_error_handler_t) (uint32_t nrf_error);
|
||||
|
||||
/**@brief Initialization parameters for the Advertising Module.
|
||||
* @details This structure is used to pass advertising options, advertising data, and an event handler to the Advertising Module during initialization. */
|
||||
typedef struct
|
||||
{
|
||||
ble_adv_modes_config_t options; /**< Parameters for advertising modes.*/
|
||||
ble_advdata_t advdata; /**< Advertising data. */
|
||||
ble_advertising_evt_handler_t evt_handler; /**< Event handler. */
|
||||
} ble_adv_init_t;
|
||||
|
||||
|
||||
/**@brief Function for handling BLE events.
|
||||
*
|
||||
* @details This function must be called from the BLE stack event dispatcher for
|
||||
* the module to handle BLE events that are relevant for the Advertising Module.
|
||||
*
|
||||
* @param[in] p_ble_evt BLE stack event.
|
||||
*/
|
||||
void ble_advertising_on_ble_evt(const ble_evt_t * const p_ble_evt);
|
||||
|
||||
|
||||
/**@brief Function for handling system events.
|
||||
*
|
||||
* @details This function must be called to handle system events that are relevant
|
||||
* for the Advertising Module. Specifically, the advertising module can not use the
|
||||
* softdevice as long as there are pending writes to the flash memory. This
|
||||
* event handler is designed to delay advertising until there is no flash operation.
|
||||
*
|
||||
* @param[in] sys_evt System event.
|
||||
*/
|
||||
void ble_advertising_on_sys_evt(uint32_t sys_evt);
|
||||
|
||||
|
||||
/**@brief Function for initializing the Advertising Module.
|
||||
*
|
||||
* @details Encodes the required advertising data and passes it to the stack.
|
||||
* Also builds a structure to be passed to the stack when starting advertising.
|
||||
* The supplied advertising data is copied to a local structure and is manipulated
|
||||
* depending on what advertising modes are started in @ref ble_advertising_start.
|
||||
*
|
||||
* @param[in] p_advdata Advertising data: name, appearance, discovery flags, and more.
|
||||
* @param[in] p_srdata Scan response data: Supplement to advertising data.
|
||||
* @param[in] p_config Select which advertising modes and intervals will be utilized.
|
||||
* @param[in] evt_handler Event handler that will be called upon advertising events.
|
||||
* @param[in] error_handler Error handler that will propogate internal errors to the main applications.
|
||||
*
|
||||
* @retval NRF_SUCCESS If initialization was successful. Otherwise, an error code is returned.
|
||||
*/
|
||||
uint32_t ble_advertising_init(ble_advdata_t const * p_advdata,
|
||||
ble_advdata_t const * p_srdata,
|
||||
ble_adv_modes_config_t const * p_config,
|
||||
ble_advertising_evt_handler_t const evt_handler,
|
||||
ble_advertising_error_handler_t const error_handler);
|
||||
|
||||
|
||||
/**@brief Function for starting advertising.
|
||||
*
|
||||
* @details You can start advertising in any of the advertising modes that you enabled
|
||||
* during initialization.
|
||||
*
|
||||
* @param[in] advertising_mode Advertising mode.
|
||||
*
|
||||
* @retval @ref NRF_SUCCESS On success, else an error code indicating reason for failure.
|
||||
* @retval @ref NRF_ERROR_INVALID_STATE If the module is not initialized.
|
||||
*/
|
||||
uint32_t ble_advertising_start(ble_adv_mode_t advertising_mode);
|
||||
|
||||
|
||||
/**@brief Function for setting the peer address.
|
||||
*
|
||||
* @details The peer address must be set by the application upon receiving a
|
||||
* @ref BLE_ADV_EVT_PEER_ADDR_REQUEST event. Without the peer address, the directed
|
||||
* advertising mode will not be run.
|
||||
*
|
||||
* @param[in] p_peer_addr Pointer to a peer address.
|
||||
*
|
||||
* @retval @ref NRF_SUCCESS Successfully stored the peer address pointer in the advertising module.
|
||||
* @retval @ref NRF_ERROR_INVALID_STATE If a reply was not expected.
|
||||
*/
|
||||
uint32_t ble_advertising_peer_addr_reply(ble_gap_addr_t * p_peer_addr);
|
||||
|
||||
|
||||
/**@brief Function for setting a whitelist.
|
||||
*
|
||||
* @details The whitelist must be set by the application upon receiving a
|
||||
* @ref BLE_ADV_EVT_WHITELIST_REQUEST event. Without the whitelist, the whitelist
|
||||
* advertising for fast and slow modes will not be run.
|
||||
*
|
||||
* @param[in] p_gap_addrs The list of GAP addresses to whitelist.
|
||||
* @param[in] addr_cnt The number of GAP addresses to whitelist.
|
||||
* @param[in] p_gap_irks The list of peer IRK to whitelist.
|
||||
* @param[in] irk_cnt The number of peer IRK to whitelist.
|
||||
*
|
||||
* @retval @ref NRF_SUCCESS If the operation was successful.
|
||||
* @retval @ref NRF_ERROR_INVALID_STATE If a call to this function was made without a
|
||||
* BLE_ADV_EVT_WHITELIST_REQUEST event being received.
|
||||
*/
|
||||
uint32_t ble_advertising_whitelist_reply(ble_gap_addr_t const * p_gap_addrs,
|
||||
uint32_t addr_cnt,
|
||||
ble_gap_irk_t const * p_gap_irks,
|
||||
uint32_t irk_cnt);
|
||||
|
||||
|
||||
/**@brief Function for disabling whitelist advertising.
|
||||
*
|
||||
* @details This function temporarily disables whitelist advertising.
|
||||
* Calling this function resets the current time-out countdown.
|
||||
*
|
||||
* @retval @ref NRF_SUCCESS On success, else an error message propogated from the Softdevice.
|
||||
*/
|
||||
uint32_t ble_advertising_restart_without_whitelist(void);
|
||||
|
||||
/** @} */
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // BLE_ADVERTISING_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,989 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "sdk_common.h"
|
||||
#if NRF_MODULE_ENABLED(BLE_DB_DISCOVERY)
|
||||
#include "ble_db_discovery.h"
|
||||
#include <stdlib.h>
|
||||
#include "headers\ble.h"
|
||||
#include "ble_srv_common.h"
|
||||
#define NRF_LOG_MODULE_NAME "BLE_DB_DISC"
|
||||
#include "nrf_log.h"
|
||||
|
||||
#define SRV_DISC_START_HANDLE 0x0001 /**< The start handle value used during service discovery. */
|
||||
#define DB_DISCOVERY_MAX_USERS BLE_DB_DISCOVERY_MAX_SRV /**< The maximum number of users/registrations allowed by this module. */
|
||||
#define MODULE_INITIALIZED (m_initialized == true) /**< Macro designating whether the module has been initialized properly. */
|
||||
|
||||
|
||||
/**@brief Array of structures containing information about the registered application modules. */
|
||||
static ble_uuid_t m_registered_handlers[DB_DISCOVERY_MAX_USERS];
|
||||
|
||||
|
||||
/**@brief Array of structures containing pending events to be sent to the application modules.
|
||||
*
|
||||
* @details Whenever a discovery related event is to be raised to a user module, it will be stored
|
||||
* in this array first. When all services needed to be discovered have been
|
||||
* discovered, all pending events will be sent to the corresponding user modules.
|
||||
**/
|
||||
static struct
|
||||
{
|
||||
ble_db_discovery_evt_t evt; /**< The pending event. */
|
||||
ble_db_discovery_evt_handler_t evt_handler; /**< The event handler which should be called to raise this event. */
|
||||
} m_pending_user_evts[DB_DISCOVERY_MAX_USERS];
|
||||
|
||||
static ble_db_discovery_evt_handler_t m_evt_handler;
|
||||
static uint32_t m_pending_usr_evt_index; /**< The index to the pending user event array, pointing to the last added pending user event. */
|
||||
static uint32_t m_num_of_handlers_reg; /**< The number of handlers registered with the DB Discovery module. */
|
||||
static bool m_initialized = false; /**< This variable Indicates if the module is initialized or not. */
|
||||
|
||||
/**@brief Function for fetching the event handler provided by a registered application module.
|
||||
*
|
||||
* @param[in] srv_uuid UUID of the service.
|
||||
*
|
||||
* @retval evt_handler Event handler of the module, registered for the given service UUID.
|
||||
* @retval NULL If no event handler is found.
|
||||
*/
|
||||
static ble_db_discovery_evt_handler_t registered_handler_get(const ble_uuid_t * const p_srv_uuid)
|
||||
{
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < m_num_of_handlers_reg; i++)
|
||||
{
|
||||
if (BLE_UUID_EQ(&(m_registered_handlers[i]), p_srv_uuid))
|
||||
{
|
||||
return (m_evt_handler);
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for storing the event handler provided by a registered application module.
|
||||
*
|
||||
* @param[in] p_srv_uuid The UUID of the service.
|
||||
* @param[in] p_evt_handler The event handler provided by the application.
|
||||
*
|
||||
* @retval NRF_SUCCESS If the handler was stored or already present in the list.
|
||||
* @retval NRF_ERROR_NO_MEM If there is no space left to store the handler.
|
||||
*/
|
||||
static uint32_t registered_handler_set(const ble_uuid_t * const p_srv_uuid,
|
||||
ble_db_discovery_evt_handler_t p_evt_handler)
|
||||
{
|
||||
if (registered_handler_get(p_srv_uuid) != NULL)
|
||||
{
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
if (m_num_of_handlers_reg < DB_DISCOVERY_MAX_USERS)
|
||||
{
|
||||
m_registered_handlers[m_num_of_handlers_reg] = *p_srv_uuid;
|
||||
|
||||
m_num_of_handlers_reg++;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
else
|
||||
{
|
||||
return NRF_ERROR_NO_MEM;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for sending all pending discovery events to the corresponding user modules.
|
||||
*/
|
||||
static void pending_user_evts_send(void)
|
||||
{
|
||||
uint32_t i = 0;
|
||||
|
||||
for (i = 0; i < m_num_of_handlers_reg; i++)
|
||||
{
|
||||
// Pass the event to the corresponding event handler.
|
||||
m_pending_user_evts[i].evt_handler(&(m_pending_user_evts[i].evt));
|
||||
}
|
||||
m_pending_usr_evt_index = 0;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for indicating error to the application.
|
||||
*
|
||||
* @details This function will fetch the event handler based on the UUID of the service being
|
||||
* discovered. (The event handler is registered by the application beforehand).
|
||||
* The error code is added to the pending events together with the event handler.
|
||||
* If no event handler was found, then this function will do nothing.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB discovery structure.
|
||||
* @param[in] err_code Error code that should be provided to the application.
|
||||
* @param[in] conn_handle Connection Handle.
|
||||
*
|
||||
*/
|
||||
static void discovery_error_evt_trigger(ble_db_discovery_t * const p_db_discovery,
|
||||
uint32_t err_code,
|
||||
uint16_t const conn_handle)
|
||||
{
|
||||
ble_db_discovery_evt_handler_t p_evt_handler;
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid));
|
||||
|
||||
if (p_evt_handler != NULL)
|
||||
{
|
||||
ble_db_discovery_evt_t evt;
|
||||
|
||||
evt.conn_handle = conn_handle;
|
||||
evt.evt_type = BLE_DB_DISCOVERY_ERROR;
|
||||
evt.params.err_code = err_code;
|
||||
|
||||
p_evt_handler(&evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for triggering a Discovery Complete or Service Not Found event to the
|
||||
* application.
|
||||
*
|
||||
* @details This function will fetch the event handler based on the UUID of the service being
|
||||
* discovered. (The event handler is registered by the application beforehand).
|
||||
* It then triggers an event indicating the completion of the service discovery.
|
||||
* If no event handler was found, then this function will do nothing.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB discovery structure.
|
||||
* @param[in] is_srv_found Variable to indicate if the service was found at the peer.
|
||||
* @param[in] conn_handle Connection Handle.
|
||||
*/
|
||||
static void discovery_complete_evt_trigger(ble_db_discovery_t * const p_db_discovery,
|
||||
bool is_srv_found,
|
||||
uint16_t const conn_handle)
|
||||
{
|
||||
ble_db_discovery_evt_handler_t p_evt_handler;
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
p_evt_handler = registered_handler_get(&(p_srv_being_discovered->srv_uuid));
|
||||
|
||||
if (p_evt_handler != NULL)
|
||||
{
|
||||
if (m_pending_usr_evt_index < DB_DISCOVERY_MAX_USERS)
|
||||
{
|
||||
// Insert an event into the pending event list.
|
||||
m_pending_user_evts[m_pending_usr_evt_index].evt.conn_handle = conn_handle;
|
||||
|
||||
m_pending_user_evts[m_pending_usr_evt_index].evt.params.discovered_db =
|
||||
*p_srv_being_discovered;
|
||||
if (is_srv_found)
|
||||
{
|
||||
m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type =
|
||||
BLE_DB_DISCOVERY_COMPLETE;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_pending_user_evts[m_pending_usr_evt_index].evt.evt_type =
|
||||
BLE_DB_DISCOVERY_SRV_NOT_FOUND;
|
||||
}
|
||||
m_pending_user_evts[m_pending_usr_evt_index].evt_handler = p_evt_handler;
|
||||
|
||||
m_pending_usr_evt_index++;
|
||||
|
||||
if (m_pending_usr_evt_index == m_num_of_handlers_reg)
|
||||
{
|
||||
// All registered modules have pending events. Send all pending events to the user
|
||||
// modules.
|
||||
pending_user_evts_send();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Too many events pending. Do nothing. (Ideally this should not happen.)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling service discovery completion.
|
||||
*
|
||||
* @details This function will be used to determine if there are more services to be discovered,
|
||||
* and if so, initiate the discovery of the next service.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery Structure.
|
||||
* @param[in] conn_handle Connection Handle.
|
||||
*/
|
||||
static void on_srv_disc_completion(ble_db_discovery_t * p_db_discovery,
|
||||
uint16_t const conn_handle)
|
||||
{
|
||||
p_db_discovery->discoveries_count++;
|
||||
|
||||
// Check if more services need to be discovered.
|
||||
if (p_db_discovery->discoveries_count < m_num_of_handlers_reg)
|
||||
{
|
||||
// Reset the current characteristic index since a new service discovery is about to start.
|
||||
p_db_discovery->curr_char_ind = 0;
|
||||
|
||||
// Initiate discovery of the next service.
|
||||
p_db_discovery->curr_srv_ind++;
|
||||
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind];
|
||||
|
||||
// Reset the characteristic count in the current service to zero since a new service
|
||||
// discovery is about to start.
|
||||
p_srv_being_discovered->char_count = 0;
|
||||
|
||||
NRF_LOG_INFO("Starting discovery of service with UUID 0x%x for Connection handle %d\r\n",
|
||||
p_srv_being_discovered->srv_uuid.uuid, conn_handle);
|
||||
|
||||
uint32_t err_code;
|
||||
|
||||
err_code = sd_ble_gattc_primary_services_discover
|
||||
(
|
||||
conn_handle,
|
||||
SRV_DISC_START_HANDLE,
|
||||
&(p_srv_being_discovered->srv_uuid)
|
||||
);
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
p_db_discovery->discovery_in_progress = false;
|
||||
|
||||
// Error with discovering the service.
|
||||
// Indicate the error to the registered user application.
|
||||
discovery_error_evt_trigger(p_db_discovery, err_code, conn_handle);
|
||||
|
||||
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
|
||||
m_pending_user_evts[0].evt.conn_handle = conn_handle;
|
||||
// m_evt_handler(&m_pending_user_evts[0].evt);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// No more service discovery is needed.
|
||||
p_db_discovery->discovery_in_progress = false;
|
||||
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
|
||||
m_pending_user_evts[0].evt.conn_handle = conn_handle;
|
||||
//m_evt_handler(&m_pending_user_evts[0].evt);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for finding out if a characteristic discovery should be performed after the
|
||||
* last discovered characteristic.
|
||||
*
|
||||
* @details This function is used during the time of database discovery to find out if there is
|
||||
* a need to do more characteristic discoveries. The value handles of the
|
||||
* last discovered characteristic is compared with the end handle of the service.
|
||||
* If the service handle is greater than one of the former characteristic handles,
|
||||
* it means that a characteristic discovery is required.
|
||||
*
|
||||
* @param[in] p_db_discovery The pointer to the DB Discovery structure.
|
||||
* @param[in] p_after_char The pointer to the last discovered characteristic.
|
||||
*
|
||||
* @retval True if a characteristic discovery is required.
|
||||
* @retval False if a characteristic discovery is NOT required.
|
||||
*/
|
||||
static bool is_char_discovery_reqd(ble_db_discovery_t * const p_db_discovery,
|
||||
ble_gattc_char_t * p_after_char)
|
||||
{
|
||||
if (
|
||||
p_after_char->handle_value <
|
||||
p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle
|
||||
)
|
||||
{
|
||||
// Handle value of the characteristic being discovered is less than the end handle of
|
||||
// the service being discovered. There is a possibility of more characteristics being
|
||||
// present. Hence a characteristic discovery is required.
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function to find out if a descriptor discovery is required.
|
||||
*
|
||||
* @details This function finds out if there is a possibility of existence of descriptors between
|
||||
* current characteristic and the next characteristic. If so, this function will compute
|
||||
* the handle range on which the descriptors may be present and will return it.
|
||||
* If the current characteristic is the last known characteristic, then this function
|
||||
* will use the service end handle to find out if the current characteristic can have
|
||||
* descriptors.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] p_curr_char Pointer to the current characteristic.
|
||||
* @param[in] p_next_char Pointer to the next characteristic. This should be NULL if the
|
||||
* caller knows that there is no characteristic after the current
|
||||
* characteristic at the peer.
|
||||
* @param[out] p_handle_range Pointer to the handle range in which descriptors may exist at the
|
||||
* the peer.
|
||||
*
|
||||
* @retval True If a descriptor discovery is required.
|
||||
* @retval False If a descriptor discovery is NOT required.
|
||||
*/
|
||||
static bool is_desc_discovery_reqd(ble_db_discovery_t * p_db_discovery,
|
||||
ble_gatt_db_char_t * p_curr_char,
|
||||
ble_gatt_db_char_t * p_next_char,
|
||||
ble_gattc_handle_range_t * p_handle_range)
|
||||
{
|
||||
if (p_next_char == NULL)
|
||||
{
|
||||
// Current characteristic is the last characteristic in the service. Check if the value
|
||||
// handle of the current characteristic is equal to the service end handle.
|
||||
if (
|
||||
p_curr_char->characteristic.handle_value ==
|
||||
p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle
|
||||
)
|
||||
{
|
||||
// No descriptors can be present for the current characteristic. p_curr_char is the last
|
||||
// characteristic with no descriptors.
|
||||
return false;
|
||||
}
|
||||
|
||||
p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1;
|
||||
|
||||
// Since the current characteristic is the last characteristic in the service, the end
|
||||
// handle should be the end handle of the service.
|
||||
p_handle_range->end_handle =
|
||||
p_db_discovery->services[p_db_discovery->curr_srv_ind].handle_range.end_handle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// p_next_char != NULL. Check for existence of descriptors between the current and the next
|
||||
// characteristic.
|
||||
if ((p_curr_char->characteristic.handle_value + 1) == p_next_char->characteristic.handle_decl)
|
||||
{
|
||||
// No descriptors can exist between the two characteristic.
|
||||
return false;
|
||||
}
|
||||
|
||||
p_handle_range->start_handle = p_curr_char->characteristic.handle_value + 1;
|
||||
p_handle_range->end_handle = p_next_char->characteristic.handle_decl - 1;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for performing characteristic discovery.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] conn_handle Connection Handle.
|
||||
*
|
||||
* @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the characteristic
|
||||
* discovery. Otherwise an error code. This function returns the error code returned
|
||||
* by the SoftDevice API @ref sd_ble_gattc_characteristics_discover.
|
||||
*/
|
||||
static uint32_t characteristics_discover(ble_db_discovery_t * const p_db_discovery,
|
||||
uint16_t const conn_handle)
|
||||
{
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
ble_gattc_handle_range_t handle_range;
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
if (p_db_discovery->curr_char_ind != 0)
|
||||
{
|
||||
// This is not the first characteristic being discovered. Hence the 'start handle' to be
|
||||
// used must be computed using the handle_value of the previous characteristic.
|
||||
ble_gattc_char_t * p_prev_char;
|
||||
uint8_t prev_char_ind = p_db_discovery->curr_char_ind - 1;
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
p_prev_char = &(p_srv_being_discovered->charateristics[prev_char_ind].characteristic);
|
||||
|
||||
handle_range.start_handle = p_prev_char->handle_value + 1;
|
||||
}
|
||||
else
|
||||
{
|
||||
// This is the first characteristic of this service being discovered.
|
||||
handle_range.start_handle = p_srv_being_discovered->handle_range.start_handle;
|
||||
}
|
||||
|
||||
handle_range.end_handle = p_srv_being_discovered->handle_range.end_handle;
|
||||
|
||||
return sd_ble_gattc_characteristics_discover(conn_handle, &handle_range);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for performing descriptor discovery, if required.
|
||||
*
|
||||
* @details This function will check if descriptor discovery is required and then perform it if
|
||||
* needed. If no more descriptor discovery is required for the service, then the output
|
||||
* parameter p_raise_discov_complete is set to true, indicating to the caller that a
|
||||
* discovery complete event can be triggered to the application.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[out] p_raise_discov_complete The value pointed to by this pointer will be set to true if
|
||||
* the Discovery Complete event can be triggered to the
|
||||
* application.
|
||||
* @param[in] conn_handle Connection Handle.
|
||||
*
|
||||
* @return NRF_SUCCESS if the SoftDevice was successfully requested to perform the descriptor
|
||||
* discovery, or if no more descriptor discovery is required. Otherwise an error code.
|
||||
* This function returns the error code returned by the SoftDevice API @ref
|
||||
* sd_ble_gattc_descriptors_discover.
|
||||
*/
|
||||
static uint32_t descriptors_discover(ble_db_discovery_t * const p_db_discovery,
|
||||
bool * p_raise_discov_complete,
|
||||
uint16_t const conn_handle)
|
||||
{
|
||||
ble_gattc_handle_range_t handle_range;
|
||||
ble_gatt_db_char_t * p_curr_char_being_discovered;
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
bool is_discovery_reqd = false;
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
p_curr_char_being_discovered =
|
||||
&(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]);
|
||||
|
||||
if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count)
|
||||
{
|
||||
// This is the last characteristic of this service.
|
||||
is_discovery_reqd = is_desc_discovery_reqd(p_db_discovery,
|
||||
p_curr_char_being_discovered,
|
||||
NULL,
|
||||
&handle_range);
|
||||
}
|
||||
else
|
||||
{
|
||||
uint8_t i;
|
||||
ble_gatt_db_char_t * p_next_char;
|
||||
|
||||
for (i = p_db_discovery->curr_char_ind;
|
||||
i < p_srv_being_discovered->char_count;
|
||||
i++)
|
||||
{
|
||||
|
||||
if (i == (p_srv_being_discovered->char_count - 1))
|
||||
{
|
||||
// The current characteristic is the last characteristic in the service.
|
||||
p_next_char = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
p_next_char = &(p_srv_being_discovered->charateristics[i + 1]);
|
||||
}
|
||||
|
||||
// Check if it is possible for the current characteristic to have a descriptor.
|
||||
if (is_desc_discovery_reqd(p_db_discovery,
|
||||
p_curr_char_being_discovered,
|
||||
p_next_char,
|
||||
&handle_range))
|
||||
{
|
||||
is_discovery_reqd = true;
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
// No descriptors can exist.
|
||||
p_curr_char_being_discovered = p_next_char;
|
||||
p_db_discovery->curr_char_ind++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!is_discovery_reqd)
|
||||
{
|
||||
// No more descriptor discovery required. Discovery is complete.
|
||||
// This informs the caller that a discovery complete event can be triggered.
|
||||
*p_raise_discov_complete = true;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
*p_raise_discov_complete = false;
|
||||
|
||||
return sd_ble_gattc_descriptors_discover(conn_handle, &handle_range);
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling primary service discovery response.
|
||||
*
|
||||
* @details This function will handle the primary service discovery response and start the
|
||||
* discovery of characteristics within that service.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
|
||||
*/
|
||||
static void on_primary_srv_discovery_rsp(ble_db_discovery_t * const p_db_discovery,
|
||||
const ble_gattc_evt_t * const p_ble_gattc_evt)
|
||||
{
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
|
||||
{
|
||||
uint32_t err_code;
|
||||
const ble_gattc_evt_prim_srvc_disc_rsp_t * p_prim_srvc_disc_rsp_evt;
|
||||
|
||||
NRF_LOG_INFO("Found service UUID 0x%x\r\n", p_srv_being_discovered->srv_uuid.uuid);
|
||||
|
||||
p_prim_srvc_disc_rsp_evt = &(p_ble_gattc_evt->params.prim_srvc_disc_rsp);
|
||||
|
||||
p_srv_being_discovered->srv_uuid = p_prim_srvc_disc_rsp_evt->services[0].uuid;
|
||||
p_srv_being_discovered->handle_range = p_prim_srvc_disc_rsp_evt->services[0].handle_range;
|
||||
|
||||
err_code = characteristics_discover(p_db_discovery,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
p_db_discovery->discovery_in_progress = false;
|
||||
|
||||
// Error with discovering the service.
|
||||
// Indicate the error to the registered user application.
|
||||
discovery_error_evt_trigger(p_db_discovery,
|
||||
err_code,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
|
||||
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
|
||||
//m_evt_handler(&m_pending_user_evts[0].evt);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
NRF_LOG_INFO("Service UUID 0x%x Not found\r\n", p_srv_being_discovered->srv_uuid.uuid);
|
||||
// Trigger Service Not Found event to the application.
|
||||
discovery_complete_evt_trigger(p_db_discovery,
|
||||
false,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
on_srv_disc_completion(p_db_discovery,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling characteristic discovery response.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
|
||||
*/
|
||||
static void on_characteristic_discovery_rsp(ble_db_discovery_t * const p_db_discovery,
|
||||
const ble_gattc_evt_t * const p_ble_gattc_evt)
|
||||
{
|
||||
uint32_t err_code;
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
bool perform_desc_discov = false;
|
||||
|
||||
if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
|
||||
{
|
||||
const ble_gattc_evt_char_disc_rsp_t * p_char_disc_rsp_evt;
|
||||
|
||||
p_char_disc_rsp_evt = &(p_ble_gattc_evt->params.char_disc_rsp);
|
||||
|
||||
// Find out the number of characteristics that were previously discovered (in earlier
|
||||
// characteristic discovery responses, if any).
|
||||
uint8_t num_chars_prev_disc = p_srv_being_discovered->char_count;
|
||||
|
||||
// Find out the number of characteristics that are currently discovered (in the
|
||||
// characteristic discovery response being handled).
|
||||
uint8_t num_chars_curr_disc = p_char_disc_rsp_evt->count;
|
||||
|
||||
// Check if the total number of discovered characteristics are supported by this module.
|
||||
if ((num_chars_prev_disc + num_chars_curr_disc) <= BLE_GATT_DB_MAX_CHARS)
|
||||
{
|
||||
// Update the characteristics count.
|
||||
p_srv_being_discovered->char_count += num_chars_curr_disc;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The number of characteristics discovered at the peer is more than the supported
|
||||
// maximum. This module will store only the characteristics found up to this point.
|
||||
p_srv_being_discovered->char_count = BLE_GATT_DB_MAX_CHARS;
|
||||
}
|
||||
|
||||
uint32_t i;
|
||||
uint32_t j;
|
||||
|
||||
for (i = num_chars_prev_disc, j = 0; i < p_srv_being_discovered->char_count; i++, j++)
|
||||
{
|
||||
p_srv_being_discovered->charateristics[i].characteristic =
|
||||
p_char_disc_rsp_evt->chars[j];
|
||||
|
||||
p_srv_being_discovered->charateristics[i].cccd_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_srv_being_discovered->charateristics[i].ext_prop_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_srv_being_discovered->charateristics[i].user_desc_handle = BLE_GATT_HANDLE_INVALID;
|
||||
p_srv_being_discovered->charateristics[i].report_ref_handle = BLE_GATT_HANDLE_INVALID;
|
||||
}
|
||||
|
||||
ble_gattc_char_t * p_last_known_char;
|
||||
|
||||
p_last_known_char = &(p_srv_being_discovered->charateristics[i - 1].characteristic);
|
||||
|
||||
// If no more characteristic discovery is required, or if the maximum number of supported
|
||||
// characteristic per service has been reached, descriptor discovery will be performed.
|
||||
if (
|
||||
!is_char_discovery_reqd(p_db_discovery, p_last_known_char) ||
|
||||
(p_srv_being_discovered->char_count == BLE_GATT_DB_MAX_CHARS)
|
||||
)
|
||||
{
|
||||
perform_desc_discov = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Update the current characteristic index.
|
||||
p_db_discovery->curr_char_ind = p_srv_being_discovered->char_count;
|
||||
|
||||
// Perform another round of characteristic discovery.
|
||||
err_code = characteristics_discover(p_db_discovery,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
p_db_discovery->discovery_in_progress = false;
|
||||
|
||||
discovery_error_evt_trigger(p_db_discovery,
|
||||
err_code,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
|
||||
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
|
||||
//m_evt_handler(&m_pending_user_evts[0].evt);
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The previous characteristic discovery resulted in no characteristics.
|
||||
// descriptor discovery should be performed.
|
||||
perform_desc_discov = true;
|
||||
}
|
||||
|
||||
if (perform_desc_discov)
|
||||
{
|
||||
bool raise_discov_complete;
|
||||
|
||||
p_db_discovery->curr_char_ind = 0;
|
||||
|
||||
err_code = descriptors_discover(p_db_discovery,
|
||||
&raise_discov_complete,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
p_db_discovery->discovery_in_progress = false;
|
||||
|
||||
discovery_error_evt_trigger(p_db_discovery,
|
||||
err_code,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
|
||||
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
|
||||
//m_evt_handler(&m_pending_user_evts[0].evt);
|
||||
|
||||
return;
|
||||
}
|
||||
if (raise_discov_complete)
|
||||
{
|
||||
// No more characteristics and descriptors need to be discovered. Discovery is complete.
|
||||
// Send a discovery complete event to the user application.
|
||||
NRF_LOG_INFO("Discovery of service with UUID 0x%x completed with success for Connection"
|
||||
" handle %d\r\n", p_srv_being_discovered->srv_uuid.uuid,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
discovery_complete_evt_trigger(p_db_discovery,
|
||||
true,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
on_srv_disc_completion(p_db_discovery,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling descriptor discovery response.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] p_ble_gattc_evt Pointer to the GATT Client event.
|
||||
*/
|
||||
static void on_descriptor_discovery_rsp(ble_db_discovery_t * const p_db_discovery,
|
||||
const ble_gattc_evt_t * const p_ble_gattc_evt)
|
||||
{
|
||||
const ble_gattc_evt_desc_disc_rsp_t * p_desc_disc_rsp_evt;
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
|
||||
if (p_ble_gattc_evt->conn_handle != p_db_discovery->conn_handle)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
p_desc_disc_rsp_evt = &(p_ble_gattc_evt->params.desc_disc_rsp);
|
||||
|
||||
ble_gatt_db_char_t * p_char_being_discovered =
|
||||
&(p_srv_being_discovered->charateristics[p_db_discovery->curr_char_ind]);
|
||||
|
||||
if (p_ble_gattc_evt->gatt_status == BLE_GATT_STATUS_SUCCESS)
|
||||
{
|
||||
// The descriptor was found at the peer.
|
||||
// Iterate through and collect CCCD, Extended Properties,
|
||||
// User Description & Report Reference descriptor handles.
|
||||
for (uint32_t i = 0; i < p_desc_disc_rsp_evt->count; i++)
|
||||
{
|
||||
switch (p_desc_disc_rsp_evt->descs[i].uuid.uuid)
|
||||
{
|
||||
case BLE_UUID_DESCRIPTOR_CLIENT_CHAR_CONFIG:
|
||||
p_char_being_discovered->cccd_handle =
|
||||
p_desc_disc_rsp_evt->descs[i].handle;
|
||||
break;
|
||||
|
||||
case BLE_UUID_DESCRIPTOR_CHAR_EXT_PROP:
|
||||
p_char_being_discovered->ext_prop_handle =
|
||||
p_desc_disc_rsp_evt->descs[i].handle;
|
||||
break;
|
||||
|
||||
case BLE_UUID_DESCRIPTOR_CHAR_USER_DESC:
|
||||
p_char_being_discovered->user_desc_handle =
|
||||
p_desc_disc_rsp_evt->descs[i].handle;
|
||||
break;
|
||||
|
||||
case BLE_UUID_REPORT_REF_DESCR:
|
||||
p_char_being_discovered->report_ref_handle =
|
||||
p_desc_disc_rsp_evt->descs[i].handle;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Break if we've found all the descriptors we are looking for. */
|
||||
if (p_char_being_discovered->cccd_handle != BLE_GATT_HANDLE_INVALID &&
|
||||
p_char_being_discovered->ext_prop_handle != BLE_GATT_HANDLE_INVALID &&
|
||||
p_char_being_discovered->user_desc_handle != BLE_GATT_HANDLE_INVALID &&
|
||||
p_char_being_discovered->report_ref_handle != BLE_GATT_HANDLE_INVALID)
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
bool raise_discov_complete = false;
|
||||
|
||||
if ((p_db_discovery->curr_char_ind + 1) == p_srv_being_discovered->char_count)
|
||||
{
|
||||
// No more characteristics and descriptors need to be discovered. Discovery is complete.
|
||||
// Send a discovery complete event to the user application.
|
||||
|
||||
raise_discov_complete = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Begin discovery of descriptors for the next characteristic.
|
||||
uint32_t err_code;
|
||||
|
||||
p_db_discovery->curr_char_ind++;
|
||||
|
||||
err_code = descriptors_discover(p_db_discovery,
|
||||
&raise_discov_complete,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
if (err_code != NRF_SUCCESS)
|
||||
{
|
||||
p_db_discovery->discovery_in_progress = false;
|
||||
|
||||
// Error with discovering the service.
|
||||
// Indicate the error to the registered user application.
|
||||
discovery_error_evt_trigger(p_db_discovery,
|
||||
err_code,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
m_pending_user_evts[0].evt.evt_type = BLE_DB_DISCOVERY_AVAILABLE;
|
||||
m_pending_user_evts[0].evt.conn_handle = p_ble_gattc_evt->conn_handle;
|
||||
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (raise_discov_complete)
|
||||
{
|
||||
NRF_LOG_INFO("Discovery of service with UUID 0x%x completed with success for Connection"
|
||||
" handle %d\r\n", p_srv_being_discovered->srv_uuid.uuid,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
discovery_complete_evt_trigger(p_db_discovery,
|
||||
true,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
|
||||
on_srv_disc_completion(p_db_discovery,
|
||||
p_ble_gattc_evt->conn_handle);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_db_discovery_init(const ble_db_discovery_evt_handler_t evt_handler)
|
||||
{
|
||||
uint32_t err_code = NRF_SUCCESS;
|
||||
VERIFY_PARAM_NOT_NULL(evt_handler);
|
||||
|
||||
m_num_of_handlers_reg = 0;
|
||||
m_initialized = true;
|
||||
m_pending_usr_evt_index = 0;
|
||||
m_evt_handler = evt_handler;
|
||||
|
||||
return err_code;
|
||||
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_db_discovery_close()
|
||||
{
|
||||
m_num_of_handlers_reg = 0;
|
||||
m_initialized = false;
|
||||
m_pending_usr_evt_index = 0;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_db_discovery_evt_register(const ble_uuid_t * const p_uuid)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL(p_uuid);
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
|
||||
return registered_handler_set(p_uuid, m_evt_handler);
|
||||
}
|
||||
|
||||
|
||||
uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery,
|
||||
uint16_t conn_handle)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL(p_db_discovery);
|
||||
VERIFY_MODULE_INITIALIZED();
|
||||
|
||||
if (m_num_of_handlers_reg == 0)
|
||||
{
|
||||
// No user modules were registered. There are no services to discover.
|
||||
return NRF_ERROR_INVALID_STATE;
|
||||
}
|
||||
|
||||
if (p_db_discovery->discovery_in_progress)
|
||||
{
|
||||
return NRF_ERROR_BUSY;
|
||||
}
|
||||
|
||||
p_db_discovery->conn_handle = conn_handle;
|
||||
ble_gatt_db_srv_t * p_srv_being_discovered;
|
||||
|
||||
m_pending_usr_evt_index = 0;
|
||||
|
||||
p_db_discovery->discoveries_count = 0;
|
||||
p_db_discovery->curr_srv_ind = 0;
|
||||
p_db_discovery->curr_char_ind = 0;
|
||||
|
||||
p_srv_being_discovered = &(p_db_discovery->services[p_db_discovery->curr_srv_ind]);
|
||||
|
||||
p_srv_being_discovered->srv_uuid = m_registered_handlers[p_db_discovery->curr_srv_ind];
|
||||
|
||||
NRF_LOG_INFO("Starting discovery of service with UUID 0x%x for Connection handle %d\r\n",
|
||||
p_srv_being_discovered->srv_uuid.uuid, conn_handle);
|
||||
|
||||
uint32_t err_code;
|
||||
|
||||
err_code = sd_ble_gattc_primary_services_discover(conn_handle,
|
||||
SRV_DISC_START_HANDLE,
|
||||
&(p_srv_being_discovered->srv_uuid));
|
||||
VERIFY_SUCCESS(err_code);
|
||||
p_db_discovery->discovery_in_progress = true;
|
||||
|
||||
return NRF_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/**@brief Function for handling disconnected event.
|
||||
*
|
||||
* @param[in] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] p_ble_gattc_evt Pointer to the GAP event.
|
||||
*/
|
||||
static void on_disconnected(ble_db_discovery_t * const p_db_discovery,
|
||||
const ble_gap_evt_t * const p_evt)
|
||||
{
|
||||
if (p_evt->conn_handle == p_db_discovery->conn_handle)
|
||||
{
|
||||
p_db_discovery->discovery_in_progress = false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void ble_db_discovery_on_ble_evt(ble_db_discovery_t * const p_db_discovery,
|
||||
const ble_evt_t * const p_ble_evt)
|
||||
{
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_db_discovery);
|
||||
VERIFY_PARAM_NOT_NULL_VOID(p_ble_evt);
|
||||
VERIFY_MODULE_INITIALIZED_VOID();
|
||||
|
||||
switch (p_ble_evt->header.evt_id)
|
||||
{
|
||||
case BLE_GATTC_EVT_PRIM_SRVC_DISC_RSP:
|
||||
on_primary_srv_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_CHAR_DISC_RSP:
|
||||
on_characteristic_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
|
||||
break;
|
||||
|
||||
case BLE_GATTC_EVT_DESC_DISC_RSP:
|
||||
on_descriptor_discovery_rsp(p_db_discovery, &(p_ble_evt->evt.gattc_evt));
|
||||
break;
|
||||
|
||||
case BLE_GAP_EVT_DISCONNECTED:
|
||||
on_disconnected(p_db_discovery, &(p_ble_evt->evt.gap_evt));
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
#endif // NRF_MODULE_ENABLED(BLE_DB_DISCOVERY)
|
|
@ -0,0 +1,216 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/**@file
|
||||
*
|
||||
* @defgroup ble_db_discovery Database Discovery
|
||||
* @{
|
||||
* @ingroup ble_sdk_lib
|
||||
* @brief Database discovery module.
|
||||
*
|
||||
* @details This module contains the APIs and types exposed by the DB Discovery module. These APIs
|
||||
* and types can be used by the application to perform discovery of a service and its
|
||||
* characteristics at the peer server. This module can also be used to discover the
|
||||
* desired services in multiple remote devices.
|
||||
*
|
||||
* @warning The maximum number of characteristics per service that can be discovered by this module
|
||||
* is determined by the number of characteristics in the service structure defined in
|
||||
* db_disc_config.h. If the peer has more than the supported number of characteristics, then
|
||||
* the first found will be discovered and any further characteristics will be ignored. Only the
|
||||
* following descriptors will be searched for at the peer: Client Characteristic Configuration,
|
||||
* Characteristic Extended Properties, Characteristic User Description, and Report Reference.
|
||||
*
|
||||
* @note Presently only one instance of a Primary Service can be discovered by this module. If
|
||||
* there are multiple instances of the service at the peer, only the first instance
|
||||
* of it at the peer is fetched and returned to the application.
|
||||
*
|
||||
* @note The application must propagate BLE stack events to this module by calling
|
||||
* ble_db_discovery_on_ble_evt().
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLE_DB_DISCOVERY_H__
|
||||
#define BLE_DB_DISCOVERY_H__
|
||||
|
||||
#include <stdint.h>
|
||||
#include "nrf_error.h"
|
||||
#include "headers\ble.h"
|
||||
#include "ble_gattc.h"
|
||||
#include "ble_srv_common.h"
|
||||
#include "ble_gatt_db.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
|
||||
#define BLE_DB_DISCOVERY_MAX_SRV 6 /**< Maximum number of services supported by this module. This also indicates the maximum number of users allowed to be registered to this module. (one user per service). */
|
||||
|
||||
|
||||
/**@brief Type of the DB Discovery event.
|
||||
*/
|
||||
typedef enum
|
||||
{
|
||||
BLE_DB_DISCOVERY_COMPLETE, /**< Event indicating that the GATT Database discovery is complete. */
|
||||
BLE_DB_DISCOVERY_ERROR, /**< Event indicating that an internal error has occurred in the DB Discovery module. This could typically be because of the SoftDevice API returning an error code during the DB discover.*/
|
||||
BLE_DB_DISCOVERY_SRV_NOT_FOUND, /**< Event indicating that the service was not found at the peer.*/
|
||||
BLE_DB_DISCOVERY_AVAILABLE /**< Event indicating that the DB discovery module is available.*/
|
||||
} ble_db_discovery_evt_type_t;
|
||||
|
||||
|
||||
|
||||
/**@brief Structure for holding the information related to the GATT database at the server.
|
||||
*
|
||||
* @details This module identifies a remote database. Use one instance of this structure per
|
||||
* connection.
|
||||
*
|
||||
* @warning This structure must be zero-initialized.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ble_gatt_db_srv_t services[BLE_DB_DISCOVERY_MAX_SRV]; /**< Information related to the current service being discovered. This is intended for internal use during service discovery.*/
|
||||
uint8_t srv_count; /**< Number of services at the peers GATT database.*/
|
||||
uint8_t curr_char_ind; /**< Index of the current characteristic being discovered. This is intended for internal use during service discovery.*/
|
||||
uint8_t curr_srv_ind; /**< Index of the current service being discovered. This is intended for internal use during service discovery.*/
|
||||
bool discovery_in_progress; /**< Variable to indicate if there is a service discovery in progress. */
|
||||
uint8_t discoveries_count; /**< Number of service discoveries made, both successful and unsuccessful. */
|
||||
uint16_t conn_handle; /**< Connection handle on which the discovery is started*/
|
||||
} ble_db_discovery_t;
|
||||
|
||||
|
||||
/**@brief Structure containing the event from the DB discovery module to the application.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
ble_db_discovery_evt_type_t evt_type; /**< Type of event. */
|
||||
uint16_t conn_handle; /**< Handle of the connection for which this event has occurred. */
|
||||
union
|
||||
{
|
||||
ble_gatt_db_srv_t discovered_db; /**< Structure containing the information about the GATT Database at the server. This will be filled when the event type is @ref BLE_DB_DISCOVERY_COMPLETE.*/
|
||||
uint32_t err_code; /**< nRF Error code indicating the type of error which occurred in the DB Discovery module. This will be filled when the event type is @ref BLE_DB_DISCOVERY_ERROR. */
|
||||
} params;
|
||||
} ble_db_discovery_evt_t;
|
||||
|
||||
|
||||
/**@brief DB Discovery event handler type. */
|
||||
typedef void (* ble_db_discovery_evt_handler_t)(ble_db_discovery_evt_t * p_evt);
|
||||
|
||||
|
||||
/**@brief Function for initializing the DB Discovery module.
|
||||
*
|
||||
* @param[in] evt_handler Event handler to be called by the DB discovery module when any event
|
||||
* related to discovery of the registered service occurs.
|
||||
*
|
||||
* @retval NRF_SUCCESS On successful initialization.
|
||||
* @retval NRF_ERROR_NULL If the handler was NULL.
|
||||
*/
|
||||
uint32_t ble_db_discovery_init(ble_db_discovery_evt_handler_t evt_handler);
|
||||
|
||||
|
||||
/**@brief Function for closing the DB Discovery module.
|
||||
*
|
||||
* @details This function will clear up any internal variables and states maintained by the
|
||||
* module. To re-use the module after calling this function, the function @ref
|
||||
* ble_db_discovery_init must be called again.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
*/
|
||||
uint32_t ble_db_discovery_close(void);
|
||||
|
||||
|
||||
/**@brief Function for registering with the DB Discovery module.
|
||||
*
|
||||
* @details The application can use this function to inform which service it is interested in
|
||||
* discovering at the server.
|
||||
*
|
||||
* @param[in] p_uuid Pointer to the UUID of the service to be discovered at the server.
|
||||
*
|
||||
* @note The total number of services that can be discovered by this module is @ref
|
||||
* BLE_DB_DISCOVERY_MAX_SRV. This effectively means that the maximum number of
|
||||
* registrations possible is equal to the @ref BLE_DB_DISCOVERY_MAX_SRV.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NULL When a NULL pointer is passed as input.
|
||||
* @retval NRF_ERROR_INVALID_STATE If this function is called without calling the
|
||||
* @ref ble_db_discovery_init.
|
||||
* @retval NRF_ERROR_NO_MEM The maximum number of registrations allowed by this module
|
||||
* has been reached.
|
||||
*/
|
||||
uint32_t ble_db_discovery_evt_register(const ble_uuid_t * const p_uuid);
|
||||
|
||||
|
||||
/**@brief Function for starting the discovery of the GATT database at the server.
|
||||
*
|
||||
* @warning p_db_discovery structure must be zero-initialized.
|
||||
*
|
||||
* @param[out] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] conn_handle The handle of the connection for which the discovery should be
|
||||
* started.
|
||||
*
|
||||
* @retval NRF_SUCCESS Operation success.
|
||||
* @retval NRF_ERROR_NULL When a NULL pointer is passed as input.
|
||||
* @retval NRF_ERROR_INVALID_STATE If this function is called without calling the
|
||||
* @ref ble_db_discovery_init, or without calling
|
||||
* @ref ble_db_discovery_evt_register.
|
||||
* @retval NRF_ERROR_BUSY If a discovery is already in progress for the current
|
||||
* connection.
|
||||
*
|
||||
* @return This API propagates the error code returned by the
|
||||
* SoftDevice API @ref sd_ble_gattc_primary_services_discover.
|
||||
*/
|
||||
uint32_t ble_db_discovery_start(ble_db_discovery_t * const p_db_discovery,
|
||||
uint16_t conn_handle);
|
||||
|
||||
|
||||
/**@brief Function for handling the Application's BLE Stack events.
|
||||
*
|
||||
* @param[in,out] p_db_discovery Pointer to the DB Discovery structure.
|
||||
* @param[in] p_ble_evt Pointer to the BLE event received.
|
||||
*/
|
||||
void ble_db_discovery_on_ble_evt(ble_db_discovery_t * const p_db_discovery,
|
||||
const ble_evt_t * const p_ble_evt);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif // BLE_DB_DISCOVERY_H__
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,81 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "ble_debug_assert_handler.h"
|
||||
#include <string.h>
|
||||
#include "nrf.h"
|
||||
#include "ble_error_log.h"
|
||||
#include "nordic_common.h"
|
||||
|
||||
#define MAX_LENGTH_FILENAME 128 /**< Max length of filename to copy for the debug error handlier. */
|
||||
|
||||
|
||||
// WARNING - DO NOT USE THIS FUNCTION IN END PRODUCT. - WARNING
|
||||
// WARNING - FOR DEBUG PURPOSES ONLY. - WARNING
|
||||
void ble_debug_assert_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name)
|
||||
{
|
||||
// Copying parameters to static variables because parameters may not be accessible in debugger.
|
||||
static volatile uint8_t s_file_name[MAX_LENGTH_FILENAME];
|
||||
static volatile uint16_t s_line_num;
|
||||
static volatile uint32_t s_error_code;
|
||||
|
||||
strncpy((char *)s_file_name, (const char *)p_file_name, MAX_LENGTH_FILENAME - 1);
|
||||
s_file_name[MAX_LENGTH_FILENAME - 1] = '\0';
|
||||
s_line_num = line_num;
|
||||
s_error_code = error_code;
|
||||
UNUSED_VARIABLE(s_file_name);
|
||||
UNUSED_VARIABLE(s_line_num);
|
||||
UNUSED_VARIABLE(s_error_code);
|
||||
|
||||
// WARNING: The PRIMASK register is set to disable ALL interrups during writing the error log.
|
||||
//
|
||||
// Do not use __disable_irq() in normal operation.
|
||||
__disable_irq();
|
||||
|
||||
// This function will write error code, filename, and line number to the flash.
|
||||
// In addition, the Cortex-M0 stack memory will also be written to the flash.
|
||||
//(void) ble_error_log_write(error_code, p_file_name, line_num);
|
||||
|
||||
// For debug purposes, this function never returns.
|
||||
// Attach a debugger for tracing the error cause.
|
||||
for (;;)
|
||||
{
|
||||
// Do nothing.
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,86 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Nordic Semiconductor ASA
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without modification,
|
||||
* are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice, this list
|
||||
* of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form, except as embedded into a Nordic Semiconductor ASA
|
||||
* integrated circuit in a product or a software update for such product, must reproduce
|
||||
* the above copyright notice, this list of conditions and the following disclaimer in
|
||||
* the documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* 3. Neither the name of Nordic Semiconductor ASA nor the names of its contributors may be
|
||||
* used to endorse or promote products derived from this software without specific prior
|
||||
* written permission.
|
||||
*
|
||||
* 4. This software, with or without modification, must only be used with a
|
||||
* Nordic Semiconductor ASA integrated circuit.
|
||||
*
|
||||
* 5. Any software provided in binary or object form under this license must not be reverse
|
||||
* engineered, decompiled, modified and/or disassembled.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
|
||||
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
|
||||
* DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR
|
||||
* ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
|
||||
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
|
||||
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
|
||||
* ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
|
||||
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
|
||||
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
/** @file
|
||||
*
|
||||
* @defgroup ble_debug_assert_handler Assert handler for debug purposes
|
||||
* @{
|
||||
* @ingroup ble_sdk_lib
|
||||
* @brief Module for handling of assert during application development when debugging.
|
||||
*
|
||||
* @details This module may be used during development of an application to facilitate debugging.
|
||||
* It contains a function to write file name, line number and the Stack Memory to flash.
|
||||
* This module is ONLY for debugging purposes and must never be used in final product.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef BLE_DEBUG_ASSERT_HANDLER_H__
|
||||
#define BLE_DEBUG_ASSERT_HANDLER_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
/**@brief Function for handling the Debug assert, which can be called from an error handler.
|
||||
* To be used only for debugging purposes.
|
||||
*
|
||||
*@details This code will copy the filename and line number into local variables for them to always
|
||||
* be accessible in Keil debugger. The function will also write the ARM Cortex-M0 stack
|
||||
* memory into flash where it can be retrieved and manually un-winded in order to
|
||||
* back-trace the location where the error ocured.<br>
|
||||
* @warning <b>ALL INTERRUPTS WILL BE DISABLED.</b>
|
||||
*
|
||||
* @note This function will never return but loop forever for debug purposes.
|
||||
*
|
||||
* @param[in] error_code Error code supplied to the handler.
|
||||
* @param[in] line_num Line number where the original handler is called.
|
||||
* @param[in] p_file_name Pointer to the file name.
|
||||
*/
|
||||
void ble_debug_assert_handler(uint32_t error_code, uint32_t line_num, const uint8_t * p_file_name);
|
||||
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* BLE_DEBUG_ASSERT_HANDLER_H__ */
|
||||
|
||||
|
||||
/** @} */
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue